UWP C#硬重启致XML文件损坏,FileStream初始化抛异常求助
Hey there, let's work through this XML corruption issue you're hitting after a hard reboot in your UWP C# app. It's super frustrating when unexpected hardware resets break your data files, so let's break down the problem and fix it step by step.
First, the root cause: when your device hard-resets mid-write to the XML file, the file gets truncated or left with incomplete XML structure. This causes exceptions when you try to open it with FileStream or parse it later.
Step 1: Add Robust Error Handling for File Access
Instead of directly opening the file with FileStream, first validate the file's existence and basic integrity, and handle exceptions gracefully. Also, in UWP, it's better to use the StorageFile/StorageFolder APIs (designed for UWP's security model) instead of raw FileStream where possible.
Here's an improved version of your file check method with error handling:
using System.Xml; using Windows.Storage; using Windows.Storage.Search; public async Task<bool> ValidateAndPrepareSettingsFile(string fileName) { try { var musicLibrary = await KnownFolders.MusicLibrary.GetFolderAsync(); var settingsFile = await musicLibrary.TryGetItemAsync(fileName) as StorageFile; // Case 1: File doesn't exist - create default if (settingsFile == null) { await CreateDefaultSettingsFile(musicLibrary, fileName); return true; } // Case 2: File is empty (definitely corrupted) var fileProps = await settingsFile.GetBasicPropertiesAsync(); if (fileProps.Size == 0) { await RepairCorruptedFile(musicLibrary, fileName); return true; } // Case 3: Validate XML structure using (var stream = await settingsFile.OpenReadAsync()) using (var xmlReader = XmlReader.Create(stream.AsStreamForRead(), new XmlReaderSettings { Async = true })) { try { // Attempt to read the entire XML document while (await xmlReader.ReadAsync()) { } return true; } catch (XmlException) { // XML is malformed - trigger repair await RepairCorruptedFile(musicLibrary, fileName); return true; } } } catch (Exception ex) { // Catch other errors (permission issues, etc.) System.Diagnostics.Debug.WriteLine($"File validation error: {ex.Message}"); await RepairCorruptedFile(await KnownFolders.MusicLibrary.GetFolderAsync(), fileName); return false; } }
Step 2: Implement Backup & Repair Logic
To recover from corrupted files, keep a backup of the last valid XML. Every time you successfully write to the main file, update the backup. If the main file is corrupted, fall back to the backup or create a default file.
private async Task CreateDefaultSettingsFile(StorageFolder folder, string fileName) { // Create a fresh, valid XML file var newFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); var defaultXmlContent = "<AppSettings><LastSessionValue>0</LastSessionValue></AppSettings>"; await FileIO.WriteTextAsync(newFile, defaultXmlContent); // Create initial backup await newFile.CopyAsync(folder, $"{fileName}.bak", NameCollisionOption.ReplaceExisting); } private async Task RepairCorruptedFile(StorageFolder folder, string fileName) { var backupFile = await folder.TryGetItemAsync($"{fileName}.bak") as StorageFile; if (backupFile != null) { // Replace corrupted file with backup await backupFile.CopyAsync(folder, fileName, NameCollisionOption.ReplaceExisting); } else { // No backup exists - create default file await CreateDefaultSettingsFile(folder, fileName); } }
Step 3: Prevent Corruption with Atomic Writes
The best way to avoid this issue long-term is to use atomic writes. Instead of overwriting the original file directly, write to a temporary file first. Only when the write is successful, replace the original file with the temp one. This ensures the original file stays intact if a reboot happens mid-write.
public async Task SaveSettingsToXml(string fileName, string xmlContent) { var musicLibrary = await KnownFolders.MusicLibrary.GetFolderAsync(); var tempFile = await musicLibrary.CreateFileAsync($"{fileName}.tmp", CreationCollisionOption.ReplaceExisting); // Write to temp file first await FileIO.WriteTextAsync(tempFile, xmlContent); // Get the original file (or create if it doesn't exist) var originalFile = await musicLibrary.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists); // Replace original with temp (atomic operation) await tempFile.MoveAndReplaceAsync(originalFile); // Update backup await originalFile.CopyAsync(musicLibrary, $"{fileName}.bak", NameCollisionOption.ReplaceExisting); }
Bonus: Consider Alternate Storage Options
If XML continues to cause issues, consider using more robust storage options built into UWP:
- ApplicationData.LocalSettings: Perfect for small key-value pairs (no XML needed, built-in serialization)
- SQLite: Great for larger, structured data (more resilient to corruption than plain text files)
内容的提问来源于stack exchange,提问作者Jeyson Mg

