File I/O
File Static Class
The File class provides static methods for file operations, suitable for one-time reads/writes or simple operations. Common methods include ReadAllText, WriteAllText, AppendAllText, Exists, Copy, Move, Delete, and ReadAllLines.
Example
using System;
using System.IO;
string path = "test.txt";
File.WriteAllText(path, "Hello, World!");
string content = File.ReadAllText(path);
Console.WriteLine(content);
File.AppendAllText(path, "\nAppended line.");
string[] lines = File.ReadAllLines(path);
foreach (string line in lines)
{
Console.WriteLine($"Line: {line}");
}
Console.WriteLine($"Exists: {File.Exists(path)}");
File.Copy(path, "copy.txt", overwrite: true);
File.Move("copy.txt", "moved.txt");
File.Delete("moved.txt");
File.Delete(path);
Hello, World!
Line: Hello, World!
Line: Appended line.
Exists: True
Directory Static Class
The Directory class provides static methods for directory operations, including creating, deleting, checking existence, and listing subdirectories and files.
Example
using System;
using System.IO;
string dir = "MyFolder";
Directory.CreateDirectory(dir);
Console.WriteLine($"Exists: {Directory.Exists(dir)}");
File.WriteAllText(Path.Combine(dir, "a.txt"), "aaa");
File.WriteAllText(Path.Combine(dir, "b.txt"), "bbb");
Directory.CreateDirectory(Path.Combine(dir, "SubDir"));
string[] files = Directory.GetFiles(dir);
Console.WriteLine("Files:");
foreach (string f in files)
{
Console.WriteLine($" {Path.GetFileName(f)}");
}
string[] dirs = Directory.GetDirectories(dir);
Console.WriteLine("Dirs:");
foreach (string d in dirs)
{
Console.WriteLine($" {Path.GetFileName(d)}");
}
Directory.Delete(dir, recursive: true);
Exists: True
Files:
a.txt
b.txt
Dirs:
SubDir
FileInfo and DirectoryInfo Classes
FileInfo and DirectoryInfo are instance classes, suitable for performing multiple operations on the same file or directory. They avoid repeated path validation and offer better performance.
Example
using System;
using System.IO;
FileInfo fi = new FileInfo("demo.txt");
fi.WriteAllText("File info demo");
Console.WriteLine($"Name: {fi.Name}");
Console.WriteLine($"Length: {fi.Length}");
Console.WriteLine($"Extension: {fi.Extension}");
Console.WriteLine($"FullName: {fi.FullName}");
fi.Delete();
DirectoryInfo di = new DirectoryInfo("DemoDir");
di.Create();
Console.WriteLine($"Dir exists: {di.Exists}");
di.CreateSubdirectory("Child");
foreach (DirectoryInfo child in di.GetDirectories())
{
Console.WriteLine($"Sub: {child.Name}");
}
di.Delete(recursive: true);
Name: demo.txt
Length: 14
Extension: .txt
FullName: ...\demo.txt
Dir exists: True
Sub: Child
Stream Abstract Class and FileStream
Stream is the abstract base class for all streams, providing Read, Write, and Seek methods. FileStream is its derived class that performs low-level byte-level read/write operations.
Example
using System;
using System.IO;
using System.Text;
string filePath = "data.bin";
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
byte[] data = Encoding.UTF8.GetBytes("FileStream demo");
fs.Write(data, 0, data.Length);
}
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
Console.WriteLine(Encoding.UTF8.GetString(buffer));
}
File.Delete(filePath);
FileStream demo
StreamReader and StreamWriter
StreamReader and StreamWriter are text-oriented readers/writers that encapsulate encoding handling, making them easier to use than FileStream. StreamReader reads line by line via ReadLine, and StreamWriter writes via WriteLine.
Example
using System;
using System.IO;
string path = "text.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine("First line");
writer.WriteLine("Second line");
writer.Write("No newline here ");
writer.Write("appended.");
}
using (StreamReader reader = new StreamReader(path))
{
string? line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
File.Delete(path);
First line
Second line
No newline here appended.
BinaryReader and BinaryWriter
BinaryReader and BinaryWriter are used to read and write binary data, supporting various primitive types (int, double, string, etc.). They are suitable for handling non-text formats.
Example
using System;
using System.IO;
string path = "binary.dat";
using (BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Create)))
{
bw.Write(42);
bw.Write(3.14);
bw.Write("hello");
}
using (BinaryReader br = new BinaryReader(File.Open(path, FileMode.Open)))
{
int num = br.ReadInt32();
double d = br.ReadDouble();
string s = br.ReadString();
Console.WriteLine($"Int: {num}, Double: {d}, String: {s}");
}
File.Delete(path);
Int: 42, Double: 3.14, String: hello
Path Helper Class
The Path class provides static methods for path operations, handling path separators in a cross-platform way to avoid errors from manual string concatenation. Common methods include Combine, GetExtension, GetFileName, GetDirectoryName, and GetTempPath.
Example
using System;
using System.IO;
string fullPath = Path.Combine("folder", "sub", "file.txt");
Console.WriteLine($"Combine: {fullPath}");
Console.WriteLine($"Extension: {Path.GetExtension(fullPath)}");
Console.WriteLine($"FileName: {Path.GetFileName(fullPath)}");
Console.WriteLine($"FileNameNoExt: {Path.GetFileNameWithoutExtension(fullPath)}");
Console.WriteLine($"DirectoryName: {Path.GetDirectoryName(fullPath)}");
Console.WriteLine($"TempPath: {Path.GetTempPath()}");
Combine: folder\sub\file.txt
Extension: .txt
FileName: file.txt
FileNameNoExt: file
DirectoryName: folder\sub
TempPath: ...\Temp\
using Statement and IDisposable
Resources such as files and streams need to be released promptly. The using statement ensures that Dispose is called even if an exception occurs. C# 8+ supports the using var declaration syntax. All resource classes that need cleanup implement the IDisposable interface.
Example
using System;
using System.IO;
string path = "using_demo.txt";
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine("Block using");
}
using StreamReader sr = new StreamReader(path);
Console.WriteLine(sr.ReadLine());
File.Delete(path);
Console.WriteLine(typeof(Stream).GetInterface("IDisposable") != null);
Block using
True
❓ FAQ
📖 Summary
- File static class is suitable for one-time file operations
- Directory static class manages directory creation, deletion, and traversal
- FileInfo/DirectoryInfo instance classes are better for multiple operations on the same target
- Stream is the abstract base class for streams; FileStream provides byte-level read/write
- StreamReader/StreamWriter encapsulate encoding and simplify text I/O
- BinaryReader/BinaryWriter handle binary primitive type data
- Path class handles cross-platform path operations safely
- using statement ensures IDisposable resources are released promptly
📝 Exercises
- Write a program that uses File.WriteAllText to save a poem, then reads and outputs it with File.ReadAllText
- Use Directory.CreateDirectory to create a multi-level directory, then iterate and output its subdirectories and files
- Use StreamWriter to write 5 lines of log entries, then use StreamReader to read line by line and print line numbers
- Use BinaryWriter to write a set of int values, then use BinaryReader to read them back and compute the sum
- Use Path.Combine to join a path, then output the file name, extension, and directory name separately



