これは難しい質問です。答えるには、ファイル システムに関する高度な知識が必要になると思います。
.NET Framework 4.0 をターゲットとする WPF アプリケーション「App1」があります。このアプリケーションには、既定の設定が保存されるSettings.settings
標準ファイルを生成するファイルがあります。ユーザーが設定を変更すると、変更内容が に反映されます。これはすべて標準的な .NET の動作です。ただし、場合によっては、顧客のマシン上のファイルが想定どおりでなく、アプリケーションがクラッシュすることが判明しました。App1.exe.config
AppData\Roaming\MyCompany\App1\X.X.0.0\user.config
user.config
問題は次のようになります: は、user.config
XML で埋められた場合のサイズとほぼ同じですが、XML ではなく、一連の NUL 文字になっています。文字 0 が何度も繰り返されています。このファイルの変更に至るまでに何が起こったかについては、情報がありません。
削除するだけで、Common Language Runtime が新しいものを生成するため、顧客のデバイスでこの問題を解決できますuser.config
。設定に加えた変更は失われますが、再度変更を加えることができます。
しかし、別の WPF アプリケーション「App2」で別の XML ファイルを使用してこの問題に遭遇しましたinfo.xml
。今回は、ファイルが CLR ではなく独自のコードによって生成されたため、状況が異なります。共通点は、どちらも C# WPF アプリケーションであり、どちらも XML ファイルであり、どちらの場合もテストで問題を完全に再現できないことです。これは、C# アプリケーションが XML ファイルまたは一般的なファイルと対話する方法に関係しているのでしょうか。
現在のアプリケーションでは問題を再現できないだけでなく、意図的にエラーを生成するカスタム コードを記述しても問題を再現できません。ファイルが null で埋められる原因となる XML シリアル化エラーやファイル アクセス エラーは 1 つも見つかりません。一体何が起こっているのでしょうか。
App1 は、およびをuser.config
呼び出して、プロパティを取得および設定することでアクセスします。例:Upgrade()
Save()
if (Settings.Default.UpgradeRequired)
{
Settings.Default.Upgrade();
Settings.Default.UpgradeRequired = false;
Settings.Default.Save();
}
App2 はinfo.xml
XML をシリアル化および逆シリアル化してアクセスします。
public Info Deserialize(string xmlFile)
{
if (File.Exists(xmlFile) == false)
{
return null;
}
XmlSerializer xmlReadSerializer = new XmlSerializer(typeof(Info));
Info overview = null;
using (StreamReader file = new StreamReader(xmlFile))
{
overview = (Info)xmlReadSerializer.Deserialize(file);
file.Close();
}
return overview;
}
public void Serialize(Info infoObject, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(Info));
using (StreamWriter fileWrite = new StreamWriter(fileName))
{
writer.Serialize(fileWrite, infoObject);
fileWrite.Close();
}
}
この問題は Windows 7 と Windows 10 の両方で発生しました。この問題を調査していたところ、Windows 8.1 でも同じ XML 問題が発生したという次の投稿を見つけました。保存されたファイルにはNUL文字のみが含まれる場合があります
これを防ぐためにコードを変更できる部分はありますか、それとも問題は .NET の動作に深く関わっているのでしょうか?
私には3つの可能性があるように思えます:
- CLR は XML ファイルに null 文字を書き込みます。
- ファイルの内容を移動せずに、ファイルのメモリ アドレス ポインターが別の場所に切り替えられます。
- ファイル システムはファイルを別のメモリ アドレスに移動しようとし、ファイルの内容は移動されますが、ポインターは更新されません。
2 と 3 の方が 1 よりも可能性が高いように感じます。これが、ファイル システムに関する高度な知識が必要になる可能性があると述べた理由です。
問題を再現、修正、または回避するのに役立つ情報があれば、ぜひお知らせください。ありがとうございます!
ベストアンサー1
電源が失われた場合にこれが発生する可能性があることはよく知られています。これは、ファイル (新規ファイルまたは既存ファイル) を拡張するキャッシュ書き込みの後に発生し、その後すぐに電源が失われます。このシナリオでは、マシンが復旧したときに、ファイルには 3 つの状態が予想されます。
1) 書き込みが行われなかったかのように、ファイルがまったく存在しないか、元の長さのままです。
2) 書き込みが行われたかのようにファイルの長さは予想どおりですが、データはゼロです。
3) ファイルには予想通りの長さがあり、正しいデータが書き込まれています。
状態 2 は、あなたが説明しているものです。これは、キャッシュ書き込みを行うと、NTFS が最初にファイル サイズをそれに応じて拡張するだけで、VDL (有効なデータ長) はそのまま残すために発生します。VDL を超えるデータは常にゼロとして読み戻されます。書き込む予定だったデータは、ファイル キャッシュ内のメモリ内にあります。通常は数秒以内に、最終的にはディスクに書き込まれ、その後、書き込まれたデータを反映するためにディスク上の VDL が進められます。データが書き込まれる前、または VDL が増加する前に電源が失われると、状態 2 になります。
これは、たとえばファイルをコピーし (コピー エンジンはキャッシュされた書き込みを使用します)、すぐにコンピューターの電源プラグを抜くことで、簡単に再現できます。