2012-01-05 8 views
2

と私は、ユーザーがからファイルを取り出すアプリケーションを作っています、ファイルの大文字と小文字を区別名を取得します。この方法で大文字と小文字を区別しないスペル

、それはに変換されます:

File file = new File(filename);

と何もそれと間違っているではありません。次に、私は、

if(file.exists()){ 
    System.out.println(file.getName()); 
} 
else{ 
    System.out.println("Fail."); 
} 

ここで問題が始まるところです。ファイルの名前、例えば "HELLO.txt"を取得したいのですが、filenameが "hello.txt"の場合、それでもfile.exists()のチェックを受け取り、file.getName()は "HELLO.txt"ではなく "hello.txt" 。方法はありますか?file.getName()は "HELLO.txt?"と大文字と小文字を区別するバージョンとして返します。ありがとう!

例:

HELLO.txt is the real file

FilePicker.PickFile("hello.txt");

OUTPUT:

hello.txt

+0

私はWindowsを使用しますか? – fge

+0

はい、私はLinuxが好きですが、私のGPUはカーネルで動作しません:( –

+0

NTFSは大文字と小文字を区別しない大文字小文字を区別しません... – fge

答えて

7

あなたはケースpreseでのWindowsを使用していますrving(FAT32/NTFS/..)では、file.getCanonicalFile().getName()を使用して、選択したファイルの標準名を取得できます。

あなたは、LinuxやAndroidを使用していて、必ずしも、ケースに一致するファイルのディレクトリ内のすべてのファイル(file.getParent())を反復処理し、filename.equalsIgnoreCaseものを選択しないファイル名に基づいてファイルを選択します。または参照してくださいCase-insensitive File.equals on case-sensitive file system

+1

誰かが確認できますこれはWindowsシステム上で動作しますか? –

+0

私はこの解決策に1つの問題があることを知っています。ドキュメントに応じてgetCanonicalFileがシンボリックリンクを解決するので、シンボリックリンクではうまくいきません! – user11171

+0

この回答のも​​う1つの問題は、Androidではうまくいきません。したがって、取り消し線のバージョンがおそらく行く方法です。 –

-1

Windows上でJava 7以上のように見えますが、Path#toRealPath(NOFOLLOW_LINKS)を使用できますが、シンボリックリンクがある場合はgetCanonicalFile()よりも正しいでしょう。

+0

の回答を更新しましたこれ以上説明できますか? –

+0

上記のリンク先のPath#toRealPath()のAPI Docsは、「このパスから、このパスと同じファイルを検索する絶対パスですが、実際のディレクトリ名とファイル名を表す要素は " 。 これは元の送信者が望んだものとまったく同じです。オプションNOFOLLOW_LINKSは、シンボリックリンクの解決を抑制します。つまり、user11171が批判されないgetCanonicalPath()の副作用です。 – mober

+0

これはうまくいきますが、toRealPathは、異なる時刻に同じファイルに対して異なる結果を返すことがあります。例えば。ディスク上のファイルの名前を変更した直後にも、古い値が返されることがあります。私はWindowsでそれを経験しました。 – Bananeweizen

1
/** 
* Maps lower case strings to their case insensitive File 
*/ 
private static final Map<String, File> insensitiveFileHandlerCache = new HashMap<String, File>(); 

/** 
* Case insensitive file handler. Cannot return <code>null</code> 
*/ 
public static File newFile(String path) { 
    if (path == null) 
     return new File(path); 
    path = path.toLowerCase(); 
    // First see if it is cached 
    if (insensitiveFileHandlerCache.containsKey(path)) { 
     return insensitiveFileHandlerCache.get(path); 
    } else { 
     // If it is not cached, cache it (the path is lower case) 
     File file = new File(path); 
     insensitiveFileHandlerCache.put(path, file); 

     // If the file does not exist, look for the real path 
     if (!file.exists()) { 

      // get the directory 
      String parentPath = file.getParent(); 
      if (parentPath == null) { 
       // No parent directory? -> Just return the file since we can't find the real path 
       return file; 
      } 

      // Find the real path of the parent directory recursively 
      File dir = Util.newFile(parentPath); 

      File[] files = dir.listFiles(); 
      if (files == null) { 
       // If it is not a directory 
       insensitiveFileHandlerCache.put(path, file); 
       return file; 
      } 

      // Loop through the directory and put everything you find into the cache 
      for (File otherFile : files) { 
       // the path of our file will be updated at this point 
       insensitiveFileHandlerCache.put(otherFile.getPath().toLowerCase(), otherFile); 
      } 

      // if you found what was needed, return it 
      if (insensitiveFileHandlerCache.containsKey(path)) { 
       return insensitiveFileHandlerCache.get(path); 
      } 
     } 
     // Did not find it? Return the file with the original path 
     return file; 
    } 
} 

使用

File file = newFile(path); 

代わりの

File file = new File(path); 

、それは遅すぎてはならないので、それがキャッシュに裏打ちされています。いくつかのテストを実行し、それは動作するようです。再帰的に親ディレクトリをチェックして、正しい文字の大文字小文字を持っているかどうかを確認します。次に、各ディレクトリごとにすべてのファイルをリストし、正しい文字ケーシングをキャッシュします。最後に、パスを持つファイルが見つかったかどうかをチェックし、大文字と小文字を区別したパスでファイルを返します。

関連する問題