public static boolean isValidName(String text)
{
Pattern pattern = Pattern.compile("^[^/./\\:*?\"<>|]+$");
Matcher matcher = pattern.matcher(text);
boolean isMatch = matcher.matches();
return isMatch;
}
この方法は、Windowsで有効なファイル名を保証しますか?
以前に 引用されたMSDNドキュメント で指定された要件を考えると、次の正規表現はかなり良い仕事をするはずです:
public static boolean isValidName(String text)
{
Pattern pattern = Pattern.compile(
"# Match a valid Windows filename (unspecified file system). \n" +
"^ # Anchor to start of string. \n" +
"(?! # Assert filename is not: CON, PRN, \n" +
" (?: # AUX, NUL, COM1, COM2, COM3, COM4, \n" +
" CON|PRN|AUX|NUL| # COM5, COM6, COM7, COM8, COM9, \n" +
" COM[1-9]|LPT[1-9] # LPT1, LPT2, LPT3, LPT4, LPT5, \n" +
" ) # LPT6, LPT7, LPT8, and LPT9... \n" +
" (?:\\.[^.]*)? # followed by optional extension \n" +
" $ # and end of string \n" +
") # End negative lookahead assertion. \n" +
"[^<>:\"/\\\\|?*\\x00-\\x1F]* # Zero or more valid filename chars.\n" +
"[^<>:\"/\\\\|?*\\x00-\\x1F\\ .] # Last char is not a space or dot. \n" +
"$ # Anchor to end of string. ",
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.COMMENTS);
Matcher matcher = pattern.matcher(text);
boolean isMatch = matcher.matches();
return isMatch;
}
この正規表現では、ファイル名の長さに制限はありませんが、実際のファイル名はプラットフォームに応じて260文字または32767文字に制限される場合があります。
十分ではありません。WindowsとDOSでは、一部の単語は予約されている場合があり、ファイル名として使用できません。
CON, PRN, AUX, CLOCK$, NUL
COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
参照〜
http://en.wikipedia.org/wiki/Filename
編集:
Windowsは通常、ファイル名を260文字に制限します。しかし、完全なパス(C:\ Program Files\filename.txtなど)がこの文字カウントに含まれているため、ファイル名は実際にはそれより短くなければなりません。
これが、非常に長いファイル名のファイルを現在の場所よりも長いパスを持つ場所にコピーするときに、時々エラーが発生する理由です。
さて、次の方法で有効なファイル名が保証されると思います。
public static boolean isValidName(String text)
{
try
{
File file = new File(text);
file.createNewFile();
if(file.exists()) file.delete();
return true;
}
catch(Exception ex){}
return false;
}
どう思いますか?
一般に、Windowsファイル名が有効であること、つまりその名前のファイルを作成することが合法であることを保証する方法を実装することは不可能です。
Windowsファイル名がinvalidであることを保証するのは比較的簡単です。他の正規表現のいくつかはこれを試みます。ただし、元の質問はより強力なアサーションを要求します。ファイル名がguaranteesWindowsで有効な方法です。
MSDNリファレンス は、Windowsファイル名に「ターゲットファイルシステムが許可しないその他の文字」を含めることができないことを示しています。たとえば、NULを含むファイルは一部のファイルシステムでは無効になり、一部の古いファイルシステムではUnicode文字が拡張されます。したがって、☃.txtというファイルは有効な場合もありますが、そうでない場合もあります。したがって、架空のisValidName(\"☃\")
がtrueを返すかどうかは、基礎となるファイルシステムに依存します。
ただし、このような関数は保守的であり、印刷可能なASCII文字。任意のファイルシステム用のドライバをインストールでき、たとえば「n」という文字を許可しないファイルシステムを自由に作成できます。したがって、「snowman.txt」のような単純なファイルでさえ「保証」することはできません。有効である.
しかし、極端な場合は別としても、他の合併症があります。たとえば、「$ LogFile」という名前のファイルはNTFSボリュームのルートには存在できませんが、ボリューム上の他の場所に存在できます。したがって、ディレクトリを知らないと、「$ LogFile」が有効な名前であるかどうかを知ることができません。ただし、「C:\ data \」が別のNTFSボリュームルートへのシンボリックリンクである場合、「C:\ data\$ LogFile」でさえ無効になる可能性があります。 (同様に、D:がNTFSボリュームのサブディレクトリのエイリアスである場合、「D:\ $ LogFile」は有効です。)
さらに複雑な問題があります。たとえば、ファイルの代替データストリームはNTFSボリュームで有効であるため、「snowman.txt:☃」が有効な場合があります。 3つの主要なWindowsファイルシステムすべてにパスの長さの制限があるため、ファイル名の有効性はパスの関数でもあります。ただし、パスがボリューム上の物理パスではなく仮想エイリアス、マップされたネットワークドライブ、またはシンボリックリンクである場合、物理パスの長さはisValidName
で使用できない場合があります。
提案された名前でファイルを作成し、それを削除し、作成が成功した場合にのみtrueを返します。このアプローチには、いくつかの実用的および理論的な問題があります。前述のとおり、有効性はファイル名とパスの両方の関数であるため、c:\ test \☃.txtの有効性はc:\ test2 \☃.txtの有効性と異なる場合があります。また、関数は、ディレクトリへの書き込み権限がないなど、ファイルの有効性に関係しないさまざまな理由でファイルの書き込みに失敗します。 3番目の欠陥は、ファイル名の有効性が非決定的である必要がないことです:仮のファイルシステムは、たとえば、削除されたファイルの置き換えを許可しないか、(理論上)ファイル名が有効かどうかをランダムに決定することさえできます。
別の方法として、ファイルがWindowsでnotであることが保証されている場合にtrueを返すメソッドisInvalidFileName(String text)
を作成するのはかなり簡単です; 「aux」、「*」、「abc.txt」などのファイル名trueを返します。ファイル作成操作では、最初にファイル名が無効であることが保証されていることを確認し、falseが返された場合は停止します。そうしないと、ファイル名が無効であるためにファイルを作成できないEdgeの場合に備えて、メソッドはファイルを作成しようとする可能性があります。
Eng.Fouadのコードにコメントするための担当者のしきい値がないため、新しい回答を投稿する
public static boolean isValidName(String text)
{
try
{
File file = new File(text);
if(file.createNewFile()) file.delete();
return true;
}
catch(Exception ex){}
return false;
}
既存のファイルを削除できないようにする回答への小さな変更。ファイルは、このメソッドの呼び出し中に作成された場合にのみ削除されますが、戻り値は同じです。
ここ 許可されているファイル名を見つけることができます。
次の文字は使用できません。
(より大きい)
*(アスタリスク)
整数値ゼロ。ASCII NUL文字と呼ばれることもあります。
いいね。少なくともこのリソースを信じている場合: http://msdn.Microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx
しかし、コードの使用を簡素化します。名前が無効であると言うには、これらの文字の1つを探すだけで十分です。
public static boolean isValidName(String text)
{
Pattern pattern = Pattern.compile("[^/./\\:*?\"<>|]");
return !pattern.matcher(text).find();
}
この正規表現はよりシンプルで、より高速に動作します。
このソリューションは、ファイルを作成せずに、指定されたファイル名がOSルールに従って有効かどうかのみをチェックします。
実際にファイルを作成するときは、他の障害(たとえば、アクセス許可の不足、ドライブ領域の不足、セキュリティ制限など)を処理する必要があります。
import Java.io.File;
import Java.io.IOException;
public class FileUtils {
public static boolean isFilenameValid(String file) {
File f = new File(file);
try {
f.getCanonicalPath();
return true;
}
catch (IOException e) {
return false;
}
}
public static void main(String args[]) throws Exception {
// true
System.out.println(FileUtils.isFilenameValid("well.txt"));
System.out.println(FileUtils.isFilenameValid("well well.txt"));
System.out.println(FileUtils.isFilenameValid(""));
//false
System.out.println(FileUtils.isFilenameValid("test.T*T"));
System.out.println(FileUtils.isFilenameValid("test|.TXT"));
System.out.println(FileUtils.isFilenameValid("te?st.TXT"));
System.out.println(FileUtils.isFilenameValid("con.TXT")); // windows
System.out.println(FileUtils.isFilenameValid("prn.TXT")); // windows
}
}
Java(正規表現または独自のメソッドのいずれか)での実装方法がわかりません。ただし、Windows OSには、ファイルシステムにファイル/ディレクトリを作成するための次のルールがあります。
そのため、プログラムはこれらの規則に従う必要があります。質問の検証規則が網羅されていることを願っています。
すべての予約名(AUX、CONなど)を確認してから、次のコードを使用できます。
bool invalidName = GetFileAttributes(name) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_INVALID_NAME;
追加の制限を確認します。ただし、存在しないディレクトリで名前を確認すると、その名前が本当に有効かどうかに関係なくERROR_PATH_NOT_FOUNDを取得することに注意してください。
とにかく、古いことわざを覚えておく必要があります。
許可を得るよりも許しを求める方が簡単です。