1. The File Class: Simple and Efficient
The System.IO.File class is all about "one operation — one method." It gives you a set of high-level methods that wrap up all the complicated OS logic, so you can just focus on what you need to do.
So, what exactly can the File class do?
- Write text or any binary data to a file.
- Read file contents all at once or line by line (for text files).
- Copy, delete, and rename existing files.
- Check if a file exists at a given path.
- Work with file attributes (like creation date, size – via related classes).
Why is this so handy?
All File methods are static. That means you don't need to create an object to use them, just call the method you want, like:
File.WriteAllText("data.txt", "Hello, file!");
This style is a lot like working with the Console class: it's simple and clear, nothing to "create," no need to mess with streams.
If you want a universal and convenient tool for working with files, the System.IO.File class is exactly that. It offers tons of methods for reading, writing, copying, deleting, and other basic file operations—like a Swiss Army knife for your file system.
How do you use File?
All methods in the File class are static, so you don't need to create an object to use them—just write File.Something(). It's a lot like calling Console.WriteLine(), but now for files.
string text = "Hello, world!";
string path = "hello.txt";
// Write text to a file (if the file exists, it'll overwrite it!)
File.WriteAllText(path, text);
// Read the whole file into a single string
string readText = File.ReadAllText(path);
Console.WriteLine("File contents: " + readText);
Pro tip: If you find yourself writing ReadAllText and WriteAllText ten times in a row, you're probably doing something wrong—these methods are great for simple scenarios and small files.
Most Used Methods of the File Class
| Method | Description |
|---|---|
|
Checks if a file exists at the given path |
|
Deletes a file |
|
Copies a file |
|
Moves (or renames) a file |
|
Reads the whole file as a single string |
|
Writes a string to a file (overwrites if it exists) |
|
Reads all lines of a file into a string array |
|
Writes an array of strings to a file (each string is a separate line) |
|
Reads all bytes of a file into a byte array |
|
Writes a byte array to a file |
2. Writing and Reading Text Files
Let's check out the most commonly used methods of the File class with some practical examples. To use them, you always need the using System.IO; directive at the top of your code file.
using System;
using System.IO; // Required for working with the File class
using System.Linq; // Might be needed for ReadLines
Reading a File All at Once
This is one of the most common tasks: saving text data to a file or loading it back.
Writing a single line (or all text) to a file: File.WriteAllText() This method creates a new file at the given path. If a file with that name already exists, its contents will be completely overwritten with the new text.
string myFilePath = "notes.txt";
string textContent = "Today is a great day to learn C#.\nDon't forget to do your homework.";
// Write all text to the file
File.WriteAllText(myFilePath, textContent);
Console.WriteLine($"File '{myFilePath}' created/overwritten successfully.");
Reading a file all at once into a single string: File.ReadAllText() This method reads the entire contents of a text file from start to finish and returns it as one big string.
string myFilePath = "notes.txt";
// Important: always check if the file exists before reading to avoid errors!
if (File.Exists(myFilePath))
{
string content = File.ReadAllText(myFilePath);
Console.WriteLine($"Contents of file '{myFilePath}':\n{content}");
}
else
{
Console.WriteLine($"Error: File '{myFilePath}' not found for reading.");
}
Important note: The File.WriteAllText() and File.ReadAllText() methods are great for small and medium files (like text notes, config files, short logs). But if the file is really big (like tens or hundreds of megabytes, or even gigabytes), loading all its contents into a single string in RAM can eat up a ton of memory and even cause a OutOfMemoryException. For those cases, there are more efficient approaches (more on that below and in future lectures).
3. Reading a File Line by Line
When you're working with big text files, like huge CSV reports, long log files, or text databases, reading them all at once into memory (loading the whole file from disk into your computer's RAM) becomes inefficient or even impossible. That's where File.ReadLines() comes in.
File.ReadLines(path) — this method doesn't load the whole file at once. Instead, it returns a special collection (IEnumerable<string>) that lets you read the file line by line as needed. This is called "lazy reading" or "streaming."
string logFilePath = "application.log";
string text = """
INFO: Application started.
WARN: Problem detected in module X.
ERROR: Critical network error.
INFO: Application stopped.
""";
// Let's say we have a log file with lots of lines.
File.WriteAllText(logFilePath, text);
// Each loop iteration reads and processes just ONE line
foreach (string line in File.ReadLines(logFilePath))
Console.WriteLine($"- {line}");
Advantage: The file is read and processed in chunks, which really cuts down on memory usage when working with big files.
Difference between File.ReadLines() and File.ReadAllLines():
- File.ReadAllLines(path): Loads all lines of the file at once into memory and returns them as a string[] array. After calling this method, the whole file is already in memory. This is handy if you need full access to all lines at once (like for sorting or searching).
- File.ReadLines(path): Returns an IEnumerable<string> that lets you loop through the file line by line. The file is only read when you ask for the next line (like in a foreach loop). This is more efficient for really big files when you can't or don't want to load everything into memory.
4. Writing an Array of Strings
Sometimes you have a list of strings (like from a collection), and you want to write each string as a separate entry in a file.
File.WriteAllLines(path, contents)
This method takes an array of strings (or any string collection) and writes each string as a separate line in the file. Just like WriteAllText(), it overwrites the file if it already exists.
string membersFilePath = "participants.txt";
string[] names = { "Ivan Petrov", "Maria Sidorova", "Sergey Kozlov", "Anna Kuznetsova" };
// Each array element will be written as a separate line in the file
File.WriteAllLines(membersFilePath, names);
// Let's check the contents
Console.WriteLine($"Contents of '{membersFilePath}':");
foreach (string line in File.ReadLines(membersFilePath))
Console.WriteLine($"- {line}");
5. Working with Binary Files
The File class isn't just for text data. It also gives you handy methods for reading and writing binary data, meaning raw bytes. This is useful, for example, when saving settings in a custom format, working with images, audio, or any data that's not plain text.
Writing a byte array: File.WriteAllBytes() Creates or overwrites a file, writing the whole byte array you give it.
string binaryDataPath = "settings.bin";
// Example binary data: image, video, any data
byte[] settingsData = { 0x01, 0x0A, 0x2C, 0xFF, 0x00, 0x3F }; // Some "raw" settings
File.WriteAllBytes(binaryDataPath, settingsData);
Console.WriteLine($"Binary data written to file '{binaryDataPath}'.");
Heads up: if you try to open 'settings.bin' in Notepad, you'll see unreadable characters ("gibberish"), because these bytes aren't meant to be interpreted as text.
Reading a byte array: File.ReadAllBytes() Reads all the contents of a binary file into a byte array.
if (File.Exists(binaryDataPath))
{
byte[] readSettings = File.ReadAllBytes(binaryDataPath);
Console.WriteLine($"Read {readSettings.Length} bytes from file '{binaryDataPath}'.");
Console.Write("Read bytes (in hex): ");
foreach (byte b in readSettings)
Console.Write($"{b:X2} "); // :X2 formats the byte as a two-digit hex number
Console.WriteLine();
}
else
{
Console.WriteLine($"Error: Binary file '{binaryDataPath}' not found.");
}
These methods are super handy for saving small chunks of binary data, like caching small images or serialized objects.
6. Managing Files on Disk
The File class also gives you methods for managing files on disk.
Checking if a file exists: File.Exists(path) Returns true if a file exists at the given path, and false otherwise. It's highly recommended to use this method before trying to read, delete, or do other stuff that could throw an error if the file isn't found.
string myFileToCheck = "report.txt";
// Let's create it for the example
File.WriteAllText(myFileToCheck, "Sample report.");
if (File.Exists(myFileToCheck))
{
Console.WriteLine($"File '{myFileToCheck}' found.");
// Now it's safe to read, delete, etc.
}
else
{
Console.WriteLine($"File '{myFileToCheck}' not found.");
}
Deleting a file: File.Delete(path) permanently deletes a file from disk. Be super careful, this can't be undone!
string fileToDelete = "temp_file.txt";
// Create the file for the example
File.WriteAllText(fileToDelete, "This file will be deleted.");
if (File.Exists(fileToDelete))
{
File.Delete(fileToDelete);
Console.WriteLine($"File '{fileToDelete}' deleted successfully.");
}
else
{
Console.WriteLine($"File '{fileToDelete}' doesn't exist or was already deleted.");
}
7. Exceptions When Working with Files
Working with files always means dealing with the OS and external resources, which makes it potentially error-prone.
Handle exceptions (errors)! Lots of things can go wrong when working with files, and your program should handle them gracefully instead of just crashing. Typical situations:
- FileNotFoundException: The file you're trying to access doesn't exist at the given path.
- DirectoryNotFoundException: The folder where you're trying to create or find a file doesn't exist.
- UnauthorizedAccessException: Your program doesn't have permission to read, write, or delete the file/folder (like if it's a system file or in a protected area).
- IOException: General input/output error, often happens when the file is already open in another program and locked, or there's no space on disk.
Always use a try-catch block for safe file operations. This lets you "catch" the error and do something about it (like show a message to the user, write to a log, etc).
string sensitiveFilePath = "secret_data.txt";
try
{
// Trying to read a file that might not exist or you might not have access to
string secretContent = File.ReadAllText(sensitiveFilePath);
Console.WriteLine($"Read secret content: {secretContent}");
}
catch (FileNotFoundException) // Specific error: file not found
{
Console.WriteLine($"Error: File '{sensitiveFilePath}' not found. Make sure the path is correct.");
}
catch (IOException ex) // General input/output error (like file is locked)
{
Console.WriteLine($"I/O error when working with file '{sensitiveFilePath}': {ex.Message}");
}
catch (Exception ex) // Any other unexpected error
{
Console.WriteLine($"An unexpected error occurred: {ex.Message}");
}
8. When is System.IO.File Not the Best Choice?
Even though the File class is super versatile, there are situations where it's not optimal or even possible to use:
Huge files (tens of gigabytes+): The ReadAllText()/ReadAllBytes() methods load the whole file into memory. For extremely large files, this will cause a OutOfMemoryException. In those cases, use File.ReadLines() (for text) or go straight to streams (FileStream) to read/write in chunks. (We'll talk about streams in the next lecture).
Fine-grained file access control: If you need really specific control over how a file is opened (like exclusive access so nobody else can read or write, or the opposite—multiple processes reading at once), File doesn't give you that level of detail. For that, you need lower-level stream classes.
Asynchronous operations: For high-performance apps that need to do file operations without blocking the main thread (like web servers), you need async methods (like ReadAllTextAsync()), which are also based on streams.
Partial read/write: If you need to read just part of a file from a certain offset or write data into the middle of an existing file, File methods won't cut it. For that, you need direct access to the file stream.
9. Summary
Why is System.IO.File so popular?
- Simplicity and brevity: Its static methods let you do complex stuff in literally one or two lines of code. That makes development way easier and your code more readable.
- Automatic resource management: File takes care of opening and closing files for each operation, so you don't have to manage resources manually (which often leads to bugs).
- Versatile for everyday tasks: For most typical operations with small and medium-sized text and binary files, File is more than enough.
- Widespread: In most practical tasks and interviews, it's expected that you know how to confidently use the File class methods.
- Hidden complexity: All the methods are written to encapsulate the complicated OS logic, giving you a clean and understandable interface.
Frequently Asked Questions and Clarifications
What's the max file size for File.ReadAllText()?
For files up to a few dozen megabytes (< 100 MB) you usually won't have any problems. If the file is bigger (hundreds of MB, gigabytes), using File.ReadAllText() can eat up all your RAM (and throw a OutOfMemoryException). In those cases, use File.ReadLines() for line-by-line reading or more advanced streaming tools, which you'll learn about later.
Can you create/write a file in a folder that doesn't exist?
Nope. The File.WriteAllText(), File.WriteAllBytes() and other methods don't create parent directories automatically. If you specify a path like C:\MyAppData\Logs\current.log, but the MyAppData or Logs folders don't exist, you'll get a DirectoryNotFoundException. You need to make sure all the folders exist first, using methods from the System.IO.Directory class (like Directory.CreateDirectory("myfolder")).
How do you find out a file's creation date, modification date, or size?
To get more detailed info about a file, like creation date, last modified date, size, attributes (hidden, read-only, etc.), use the System.IO.FileInfo class. It gives you lots of useful properties.
GO TO FULL VERSION