Input/Output (IO) in .NET Framework
This section covers the fundamental classes and concepts for performing input and output operations in .NET Framework applications. IO operations allow your applications to interact with external resources like files, streams, and the console.
Core Concepts
The .NET Framework provides a rich set of classes for handling IO, primarily found within the System.IO
namespace. Key concepts include:
- Streams: Abstract representations of sequences of bytes. They are the foundation for most IO operations.
- Files: Representing and interacting with files on the file system.
- Directories: Managing and navigating through file system directories.
- Readers and Writers: Classes designed for reading and writing characters or text.
Working with Streams
Streams are fundamental. They are abstract and can represent data from various sources, such as files, network connections, or in-memory buffers.
Common Stream Types:
FileStream
: For reading from and writing to files.MemoryStream
: For working with data in memory as if it were a stream.NetworkStream
: For sending and receiving data over a network.BufferedStream
: Wraps another stream to improve performance by buffering read/write operations.
All stream classes inherit from the abstract Stream
class, which provides methods like Read()
, Write()
, Seek()
, and Flush()
.
Example: Reading from a File
using System;
using System.IO;
public class FileReader
{
public static void Main(string[] args)
{
string filePath = "example.txt";
try
{
// Open a StreamReader to read text from a file
using (StreamReader sr = new StreamReader(filePath))
{
string line;
// Read line by line until the end of the file
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine($"Error: The file '{filePath}' was not found.");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
}
File Operations
The File
class provides static methods for common file operations, such as creating, copying, deleting, and moving files.
Common File
Class Methods:
File.Create(path)
: Creates a new file.File.Copy(source, destination)
: Copies an existing file.File.Delete(path)
: Deletes a file.File.Exists(path)
: Determines whether a file exists.File.ReadAllText(path)
: Opens a text file, reads all lines, and then closes the file.File.WriteAllText(path, contents)
: Creates a new file, writes the specified string to the file, and then closes the file.
Directory Operations
Similarly, the Directory
class provides static methods for managing directories.
Common Directory
Class Methods:
Directory.CreateDirectory(path)
: Creates all directories and subdirectories.Directory.Delete(path, recursive)
: Deletes a directory and its contents.Directory.Exists(path)
: Determines whether a directory exists.Directory.GetFiles(path)
: Retrieves the names of files in a specified directory.Directory.GetDirectories(path)
: Retrieves the names of subdirectories in a specified directory.
Working with Text (Readers and Writers)
For character-based IO, you'll often use classes like StreamReader
and StreamWriter
, which wrap byte-based streams to handle encoding and character manipulation.
StreamWriter
Example: Writing to a File
using System;
using System.IO;
public class FileWriter
{
public static void Main(string[] args)
{
string filePath = "output.txt";
try
{
// Open a StreamWriter to write text to a file
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.WriteLine("This is the first line.");
sw.WriteLine("This is the second line.");
sw.Write("This is a single line without a newline.");
sw.WriteLine(" And this continues on the same line.");
}
Console.WriteLine($"Successfully wrote to '{filePath}'");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
}
Best Practices
- Use `using` statements: Always use the
using
statement when working with streams and other disposable objects to ensure resources are properly released, even if exceptions occur. - Handle Exceptions: IO operations can fail for many reasons (permissions, disk full, file not found). Implement robust error handling using
try-catch
blocks. - Buffering: For performance-critical applications, consider using
BufferedStream
to reduce the number of physical IO operations. - Asynchronous IO: For UI applications or web servers, use asynchronous IO methods (e.g.,
ReadAsync
,WriteAsync
) to avoid blocking the main thread.
Tip: Path Manipulation
The Path
class provides utility methods for working with file and directory paths in a platform-independent manner (e.g., Path.Combine()
, Path.GetFileName()
).
Important: File Locking
When a file is opened by one process, it might be locked, preventing other processes from accessing it. Be mindful of file locking behavior and handle potential IOException
s.