C# File Class: Static File Operations Explained
c# file class: Learn how to use the C# File class for reading, writing, and managing files. Covers static methods, streams, async operations, and error handling.
c# file class requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
The File class in System.IO provides static methods for creating, copying, deleting, moving, and opening files. Unlike FileInfo, which requires an instance, File methods are called directly on the type, making them convenient for one-off operations. The most common use cases involve reading and writing text, but the class also exposes lower-level stream access and file attribute queries.
Reading Text Files with ReadAllText and ReadAllLines
For small to medium-sized text files, File.ReadAllText and File.ReadAllLines are the simplest entry points. ReadAllText returns the entire file as a single string, while ReadAllLines returns a string array where each element is one line. Both methods handle encoding detection by default, using UTF-8 when no BOM is present.
string content = File.ReadAllText("config.json"); string[] lines = File.ReadAllLines("log.txt");
These methods are convenient because they encapsulate opening, reading, and closing the file. However, they load the entire file into memory. For a file that is several hundred megabytes, this can cause high memory pressure. In such cases, consider using File.OpenText or a StreamReader to process lines incrementally.
Writing Text Files with WriteAllText and AppendAllText
File.WriteAllText creates a new file and writes the given string to it, overwriting the file if it already exists. File.AppendAllText adds text to the end of the file, creating it if necessary. Both methods accept an optional encoding parameter; the default is UTF-8 without a BOM.
File.WriteAllText("output.txt", "Hello, world!"); File.AppendAllText("output.txt", "\nSecond line");
These static methods are atomic in the sense that they open, write, and close the file in one operation. But they are not suitable for high-frequency writes because each call opens and closes the file handle. For repeated appends, a StreamWriter kept open for the duration of the operation is more efficient.
Checking File Existence and Attributes
File.Exists returns true if the specified file exists and the caller has permission to read it. It returns false for a null or empty path, or if the path is a directory. File.GetAttributes returns a FileAttributes enum value that can be used to check for ReadOnly, Hidden, System, or Directory flags.
if (File.Exists("data.csv")) { FileAttributes attrs = File.GetAttributes("data.csv"); bool isReadOnly = (attrs & FileAttributes.ReadOnly) != 0; }
A common mistake is to call File.Exists immediately before reading or writing, then assume the file is still present. The file system can change between the check and the operation, leading to a FileNotFoundException. It is safer to attempt the operation and catch the exception, or use a file handle that is opened once.
Working with Streams: OpenRead, OpenWrite, and FileStream
When you need more control over reading or writing, File.OpenRead returns a read-only FileStream, and File.OpenWrite returns a write-only FileStream. These methods allow you to read or write in chunks, seek to specific positions, and manage the buffer size.
using (FileStream fs = File.OpenRead("large.bin")) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) { // Process the chunk } }
File.OpenWrite creates a new file or overwrites an existing one. If you need to append, use File.Open with FileMode.Append instead. The FileStream returned by these methods is IDisposable, so a using statement is required to release the handle promptly.
Async File Operations: ReadAllTextAsync and WriteAllTextAsync
For I/O-bound operations, async versions of the common methods exist: ReadAllTextAsync, WriteAllTextAsync, ReadAllLinesAsync, and AppendAllTextAsync. These methods release the calling thread while the file I/O is in progress, which is valuable in UI applications or high-concurrency web servers.
string content = await File.ReadAllTextAsync("data.json"); await File.WriteAllTextAsync("result.txt", content);
Async methods do not improve disk throughput; they improve thread utilization. For a single file operation in a console app, the overhead of async may not be worth it. Use async when the application needs to handle many concurrent file operations or when the calling thread is a UI thread that should not block.
File vs FileInfo: Choosing the Right Abstraction
File is a static class, while FileInfo is an instance class that represents a specific file. FileInfo is useful when you need to perform multiple operations on the same file, because it caches the path and provides instance methods like CopyTo, MoveTo, and Delete. It also exposes properties such as Length, LastWriteTime, and Attributes without re-parsing the path.
| Criterion | File (static) | FileInfo (instance) |
|---|---|---|
| Usage | One-off operations | Repeated operations on same file |
| Path handling | Passed to each method | Stored in the instance |
| Property access | Requires File.Get* calls | Direct properties |
| Best fit | Quick read/write | Multiple checks or operations |
For example, if you need to check a file's length and then read its contents, FileInfo avoids calling File.GetLength and File.ReadAllText with the same string path twice. But for a single read, the static File method is simpler.
Error Handling and File Sharing Considerations
File operations can fail for many reasons: the file does not exist, the caller lacks permission, the file is locked by another process, or the path is invalid. The File class throws specific exceptions that you should handle based on the context.
FileNotFoundExceptionwhen the file is missing.UnauthorizedAccessExceptionwhen access is denied.IOExceptionfor generic I/O errors, including sharing violations.ArgumentExceptionorNotSupportedExceptionfor invalid paths.
When another process holds an exclusive lock, File.OpenRead will throw IOException. To control sharing behavior, use File.Open with a FileShare value. For example, FileShare.ReadWrite allows other processes to read and write while the file is open, but this can lead to data corruption if not coordinated.
using (FileStream fs = new FileStream("shared.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { // Read while allowing others to read/write }
For production code, avoid catching Exception broadly. Instead, catch the specific exceptions that are expected for the operation and let unexpected ones propagate. Also, consider using FileOptions.Asynchronous when creating a FileStream if you plan to use async methods, though the static async methods handle this internally.
A final note on performance: each static File method opens and closes the file handle. If you perform many operations on the same file, reuse a single FileStream or StreamReader/StreamWriter instance. For large files, always prefer streaming over loading the entire content into memory. And remember that File.Exists is not a guarantee for subsequent operations; handle the exceptions that may occur instead of relying on a pre-check.