院長のメモ帖
2015年10月 1日 木曜日
FileInfoのIsReadOnlyはRefresh()とともに
ちょっとしたファイルバックアップコードを書いていてハマりました。
private static void CopyFile(FileInfo f, FileInfo bak)
{
if (!bak.Exists)
f.CopyTo(bak.FullName);
bak.IsReadOnly = true;
}
bakファイルが存在しなければfファイルをコピーしてbakを作成し、読み出し専用フラグを設定する、というだけの簡単なコードですが、出来上がったファイルは、readOnlyどころか、Hidden, Systemその他確認できる限りのフラグが立ってしまっていました。確認のため次のコードを実行した所、
private static void check(FileInfo bak)
{
bak.IsReadOnly = true;
}
問題なく、ReadOnly属性のみついていました。
少しデバッグして気が付いたのですが、まず、bak.Existを呼び出した時点で、bakにはファイルが存在していないことが
キャッシュされます。これは、次行のファイルコピーされた後も変化しません。その次にbakに属性をセットるわけですが、この時点でbakのAttribiutesプロパティーは-1になっており、IsReadOnlyは以下のコードのようにファイルAttribiutesのReadOnlyビットを操作しているのでキャッシュされた-1に対する演算になってしまします。そしてこの結果が実ファイルに書き込まれるので、あらゆるファイル属性がonになって隠しシステムファイルが誕生してしまったわけです。
public bool IsReadOnly {
get {
return (Attributes & FileAttributes.ReadOnly) != 0;
}
set {
if (value)
Attributes |= FileAttributes.ReadOnly;
else
Attributes &= ~FileAttributes.ReadOnly;
}
}
ですから、最初のコードは
private static void CopyFile(FileInfo f, FileInfo bak)
{
if (!bak.Exists)
{
f.CopyTo(bak.FullName);
bak.Refresh();
}
bak.IsReadOnly = true;
}
と、RefreshしてからIsReadOnlyする必要がありました。
FileInfoやDirectoryInfoでIO操作するときはキャッシュの存在を頭に入れておかないと、時としてとんでもないことが起こりますね(-_-;)
private static void CopyFile(FileInfo f, FileInfo bak)
{
if (!bak.Exists)
f.CopyTo(bak.FullName);
bak.IsReadOnly = true;
}
bakファイルが存在しなければfファイルをコピーしてbakを作成し、読み出し専用フラグを設定する、というだけの簡単なコードですが、出来上がったファイルは、readOnlyどころか、Hidden, Systemその他確認できる限りのフラグが立ってしまっていました。確認のため次のコードを実行した所、
private static void check(FileInfo bak)
{
bak.IsReadOnly = true;
}
問題なく、ReadOnly属性のみついていました。
少しデバッグして気が付いたのですが、まず、bak.Existを呼び出した時点で、bakにはファイルが存在していないことが
キャッシュされます。これは、次行のファイルコピーされた後も変化しません。その次にbakに属性をセットるわけですが、この時点でbakのAttribiutesプロパティーは-1になっており、IsReadOnlyは以下のコードのようにファイルAttribiutesのReadOnlyビットを操作しているのでキャッシュされた-1に対する演算になってしまします。そしてこの結果が実ファイルに書き込まれるので、あらゆるファイル属性がonになって隠しシステムファイルが誕生してしまったわけです。
public bool IsReadOnly {
get {
return (Attributes & FileAttributes.ReadOnly) != 0;
}
set {
if (value)
Attributes |= FileAttributes.ReadOnly;
else
Attributes &= ~FileAttributes.ReadOnly;
}
}
ですから、最初のコードは
private static void CopyFile(FileInfo f, FileInfo bak)
{
if (!bak.Exists)
{
f.CopyTo(bak.FullName);
bak.Refresh();
}
bak.IsReadOnly = true;
}
と、RefreshしてからIsReadOnlyする必要がありました。
FileInfoやDirectoryInfoでIO操作するときはキャッシュの存在を頭に入れておかないと、時としてとんでもないことが起こりますね(-_-;)
投稿者 美濃加茂市のIT獣医師 近藤 博 | コメント(0)
コメントする