.net には、ローカル ファイル システムで大文字と小文字が区別されるかどうかを判断する方法がありますか?
10 に答える
一時フォルダーにファイルを作成し (小文字のファイル名を使用)、ファイルが存在するかどうかを確認できます (大文字のファイル名を使用)。
string file = Path.GetTempPath() + Guid.NewGuid().ToString().ToLower();
File.CreateText(file).Close();
bool isCaseInsensitive = File.Exists(file.ToUpper());
File.Delete(file);
大文字と小文字の規則が異なる複数のファイル システムが存在する可能性があることに注意してください。たとえば、ルート ファイルシステムは大文字と小文字を区別することができますが、大文字と小文字を区別しないファイル システム (たとえば、FAT ファイル システムを含む USB スティック) をどこかにマウントすることができます。したがって、そのようなチェックを行う場合は、アクセスしようとしているディレクトリで行うようにしてください。
また、ユーザーが大文字と小文字を区別するファイル システムから大文字と小文字を区別しないファイル システムにデータをコピーするとどうなるでしょうか。大文字と小文字のみが異なるファイルがある場合、一方が他方を上書きし、データが失われます。逆方向にコピーする場合、たとえば、ファイル A にファイル "b" への参照が含まれているが、ファイルの名前が実際には "B" である場合など、問題が発生する可能性があります。これは、大文字と小文字を区別しない元のファイル システムでは機能しますが、大文字と小文字を区別するシステムでは機能しません。
したがって、可能であれば、ファイル システムで大文字と小文字が区別されるかどうかに依存することは避けることをお勧めします。大文字と小文字だけが異なるファイル名を生成しない、標準のファイル ピッカー ダイアログを使用する、大文字と小文字が変わる可能性があることなどに備えてください。
.NET クラス ライブラリにはそのような関数はありません。
ただし、独自のファイルを展開することはできます。小文字の名前でファイルを作成してから、その名前の大文字バージョンで開いてみてください。おそらくこの方法を改善することは可能ですが、アイデアは得られます。
編集:実際には、ルートディレクトリの最初のファイルを取得して、 filename.ToLower() と filename.ToUpper() の両方が存在するかどうかを確認できます。残念ながら、同じファイルに大文字と小文字の両方のバリアントが存在する可能性は十分にあるため、小文字と大文字の両方のバリアントの FileInfo.Name プロパティを比較して、実際に同じかどうかを確認する必要があります。これは、ディスクへの書き込みを必要としません。
明らかに、ボリュームにファイルがまったくない場合、これは失敗します。この場合、最初のオプションにフォールバックします (実装については Martin の回答を参照してください)。
これは.NET関数ではありませんが、Windows APIのGetVolumeInformation関数とGetVolumeInformationByHandleW関数は、必要な処理を実行します(yjelpFileSystemFlagsパラメーターを参照)。
一時ファイルを使用しないアプローチは次のとおりです。
using System;
using System.Runtime.InteropServices;
static bool IsCaseSensitive()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ||
RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) // HFS+ (the Mac file-system) is usually configured to be case insensitive.
{
return false;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return true;
}
else if (Environment.OSVersion.Platform == PlatformID.Unix)
{
return true;
}
else
{
// A default.
return false;
}
}
代わりに、動作環境に関する根深い知識が含まれています。
NuGet パッケージとしてすぐに利用でき、すべての .NET 4.0+ で動作し、定期的に更新されます: https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.IO#iscasesensitive
すべて小文字で一時ファイルを作成してから、大文字を使用して存在するかどうかを確認してください。
/// <summary>
/// Check whether the operating system is case-sensitive.
/// For instance on Linux you can have two files/folders called
//// "test" and "TEST", but on Windows the two can not coexist.
/// This method does not extend to mounted filesystems, which might have different properties.
/// </summary>
/// <returns>true if the operating system is case-sensitive</returns>
public static bool IsFileSystemCaseSensitive()
{
// Actually try.
string file = Path.GetTempPath() + Guid.NewGuid().ToString().ToLower() + "test";
File.CreateText(file).Close();
bool result = ! File.Exists(file.ToUpper());
File.Delete(file);
return result;
}
M4N の回答に基づいて、次の変更を行います。
- 数字だけでなく文字が含まれていることを確認するための静的な名前。
- 多分もっと読みやすい?
- メソッドにラップされます。
- ドキュメンテーション。
より良い戦略は、パスを引数として取り、同じファイルシステムにファイルを作成することですが、そこに書き込むと予期しない結果が生じる可能性があります。
私はチートを呼び出します:
Path.DirectorySeparatorChar == '\\' ? "I'm insensitive" : "I'm probably sensitive"