FileReader provides secure file reading operations with shared access support, particularly useful when reading sensitive content as bytes to avoid immutable strings in memory.
- ✅ Shared Access - Opens files with
FileShare.ReadWrite- works even when other processes have the file open for writing - ✅ BOM Handling - Optional UTF-8 BOM (Byte Order Mark) stripping for text files
- ✅ Security - Byte arrays can be zeroed out after use (unlike strings which are immutable in .NET)
- ✅ Try-pattern -
TryReadAllBytesreturnsnullinstead of throwing for missing files - ✅ Validation - Proper argument validation and meaningful error messages
Reads all bytes from a file with shared read/write access.
publicstaticbyte[]ReadAllBytes(stringpath,boolstripUtf8Bom=false)Parameters:
path- Path to the file to read (required)stripUtf8Bom- Iftrue, removes UTF-8 BOM (EF BB BF) from the beginning if present (default:false)
Returns:
- Byte array containing the file contents
Exceptions:
ArgumentNullException- WhenpathisnullArgumentException- Whenpathis empty or whitespaceFileNotFoundException- When file does not existIOException- When file cannot be read completely or file is larger thanint.MaxValuebytes
Attempts to read all bytes from a file with shared read/write access. Returns null if the file does not exist.
publicstaticbyte[]?TryReadAllBytes(stringpath,boolstripUtf8Bom=false)Parameters:
path- Path to the file to read (required)stripUtf8Bom- Iftrue, removes UTF-8 BOM (EF BB BF) from the beginning if present (default:false)
Returns:
- Byte array containing the file contents, or
nullif file does not exist
Exceptions:
ArgumentNullException- WhenpathisnullArgumentException- Whenpathis empty or whitespaceIOException- When file exists but cannot be read completely
usingCocoar.FileSystem;// Read any filebyte[]data=FileReader.ReadAllBytes(@"C:\data\file.bin");Console.WriteLine($"Read {data.Length} bytes");// Read with BOM strippingbyte[]textData=FileReader.ReadAllBytes(@"C:\data\file.txt",stripUtf8Bom:true);stringtext=Encoding.UTF8.GetString(textData);Read sensitive data and clear it from memory after use:
usingCocoar.FileSystem;byte[]?passwordBytes=null;try{passwordBytes=FileReader.ReadAllBytes(@"C:\secrets\password.dat");// Use the passwordAuthenticate(passwordBytes);}finally{// CRITICAL: Zero out the byte array to remove from memoryif(passwordBytes!=null){Array.Clear(passwordBytes,0,passwordBytes.Length);}}Handle optional files gracefully:
usingCocoar.FileSystem;// Try to read optional configurationbyte[]?configData=FileReader.TryReadAllBytes(@"C:\config\override.json");if(configData!=null){Console.WriteLine("Override configuration found");ApplyOverride(configData);}else{Console.WriteLine("No override, using defaults");}Read files that are currently open by other processes:
usingCocoar.FileSystem;// This works even if another process has the file open for writing// (e.g., a logging process writing to an active log file)byte[]logData=FileReader.ReadAllBytes(@"C:\logs\application.log");// Process the log dataAnalyzeLogs(logData);Properly handle text files with or without BOM:
usingCocoar.FileSystem;usingSystem.Text;// Strip BOM if present - ensures clean UTF-8 textbyte[]textBytes=FileReader.ReadAllBytes(@"C:\data\textfile.txt",stripUtf8Bom:true);stringtext=Encoding.UTF8.GetString(textBytes);// File with BOM (EF BB BF + "Hello"): Returns "Hello"// File without BOM ("Hello"): Returns "Hello"// Empty file: Returns ""// Only BOM (EF BB BF): Returns ""When reading sensitive information, always zero out the byte array:
byte[]?sensitiveData=null;try{sensitiveData=FileReader.ReadAllBytes(secretFilePath);ProcessSecret(sensitiveData);}finally{if(sensitiveData!=null){Array.Clear(sensitiveData,0,sensitiveData.Length);}}Prefer TryReadAllBytes over catching FileNotFoundException:
// ❌ Badbyte[]?data=null;try{data=FileReader.ReadAllBytes(optionalPath);}catch(FileNotFoundException){// File doesn't exist}// ✅ Goodbyte[]?data=FileReader.TryReadAllBytes(optionalPath);if(data!=null){ProcessData(data);}When reading text files, enable BOM stripping to ensure clean text:
// ✅ Good - handles files with or without BOMbyte[]textBytes=FileReader.ReadAllBytes(textPath,stripUtf8Bom:true);stringtext=Encoding.UTF8.GetString(textBytes);FileReader uses FileShare.ReadWrite, allowing you to read files that are:
- Currently being written by another process
- Open in another application
- Locked for writing (but not exclusive access)
// This works even if the log file is actively being writtenbyte[]currentLog=FileReader.ReadAllBytes(@"C:\logs\active.log");publicclassConfigReader{publicConfigLoadConfig(stringpath){byte[]data=FileReader.ReadAllBytes(path,stripUtf8Bom:true);stringjson=Encoding.UTF8.GetString(data);returnJsonSerializer.Deserialize<Config>(json)!;}publicConfig?LoadOptionalConfig(stringpath){byte[]?data=FileReader.TryReadAllBytes(path,stripUtf8Bom:true);if(data==null)returnnull;stringjson=Encoding.UTF8.GetString(data);returnJsonSerializer.Deserialize<Config>(json);}}publicclassLogAnalyzer{publicLogStatsAnalyzeActiveLog(stringlogPath){// Can read even while logger is writing to itbyte[]logData=FileReader.ReadAllBytes(logPath);// Parse and analyzereturnParseLogEntries(logData);}}publicclassSecretManager{publicvoidUseSecret(stringsecretPath,Action<byte[]>action){byte[]?secret=null;try{secret=FileReader.ReadAllBytes(secretPath);action(secret);}finally{// Always clean upif(secret!=null){Array.Clear(secret,0,secret.Length);}}}}- Memory: Loads entire file into memory. For very large files (> 100 MB), consider streaming approaches.
- I/O: Single synchronous read operation - very fast for local files, may be slower for network paths.
- Shared Access: Opening with
FileShare.ReadWriteis as fast as exclusive access on modern file systems. - BOM Stripping: Zero-copy slice operation (
bytes[3..]) when BOM is detected - negligible overhead.
FileReader methods are thread-safe. Multiple threads can safely call ReadAllBytes or TryReadAllBytes concurrently, even on the same file path.
| Feature | FileReader.ReadAllBytes | File.ReadAllBytes |
|---|---|---|
| Shared access | ✅ Yes (FileShare.ReadWrite) | ❌ No (exclusive) |
| BOM stripping | ✅ Built-in | ❌ Manual |
| Try-pattern | ✅ TryReadAllBytes | ❌ Must catch exception |
| Validation | ✅ Comprehensive | |
| Error messages | ✅ Detailed | |
| File size limit | ✅ Checked (int.MaxValue) | ✅ Same |
Use FileReader when:
- You need shared read access (file may be open by other processes)
- Reading sensitive data that should be cleared from memory
- Working with text files that may have UTF-8 BOM
- You want try-pattern for optional files
- You need detailed error messages
Use File.ReadAllBytes when:
- You need exclusive access to ensure file doesn't change during read
- File is guaranteed not to be open elsewhere
- You want absolutely minimal dependencies (FileReader is in Cocoar.FileSystem)
- ResilientFileSystemMonitor - Monitor file changes with auto-recovery
- FileSearcher - High-performance file traversal
- Examples - More FileReader examples