2009-05-21 20 views
45

在我的Java應用程序中,我將文件重命名爲String參數中提供的文件名。有一種方法Java - 如何確定文件名是否有效?

boolean OKtoRename(String oldName, String newName) 

基本上檢查有無了newName是不是已經採取了一些其他的文件,因爲我不想埋葬現有的。

現在發生在我身上,也許了newName字符串不表示一個有效的文件名。所以我想這個檢查添加到方法:

if (new File(newName).isFile()) { 
    return false; 
} 

這顯然是不這樣做的正確的方式,因爲在大多數情況下,NEWFILE尚不存在,因此雖然它 OKtoRename時,函數返回false。

我想知道,有沒有方法(我知道有沒有爲java.io.File對象,)像canExist()?或者我將不得不求助於正則表達式來確保newFile字符串不包含無效字符(例如?,*,「,:)?我想知道是否有一個函數隱藏在JDK的某處,它會告訴我是否一個字符串可能可能表示一個有效的文件名。

+0

please,no more exists()answers,this is no helpful。我試圖檢查文件是否可能存在。 – 2009-05-21 17:15:16

+1

@MasterPeter:嘗試改寫你的問題。它起初看起來好像你想知道文件是否存在,什麼時候你真正需要的是知道文件NAME是否有效。我改變了標題,但沒有觸及問題的措辭。 – OscarRyz 2009-05-21 17:18:32

+0

似乎相關:http://eng-przemelek.blogspot.com/2009/07/how-to-create-valid-file-name.html – greenoldman 2011-11-30 19:20:16

回答

21

使用createNewFile(),只有當它不存在,這將原子創建該文件。

如果創建的文件,名字是有效的,它不是一個重挫您可以打開這些文件,並通過FileChannel.transferXXX操作有效地將數據從一個文件拷貝到另一個文件中。

重要的是要記住,一般來說,檢查和創造應該是原子的。如果您首先檢查某個操作是否安全,則將其作爲單獨的步驟執行,同時條件可能已更改,從而使操作不安全。

深思的其他食品可在此相關的職位:"Move/Copy operations in Java."


更新:

由於這個回答,NIO.2 API已經被引入,這增加與更多的互動文件系統。

假設你有一個互動節目,並希望每個按鍵後驗證文件是否可能有效。例如,您可能只想在條目有效時啓用「保存」按鈕,而不是在按下「保存」後彈出錯誤對話框。創建並確保刪除我上面需要的大量不必要的文件似乎是一團糟。

藉助NIO.2,你不能創建一個包含那些文件系統非法字符Path實例。當您嘗試創建Path時,會立即產生一個InvalidPathException

但是,不驗證由有效字符非法的名字,就像在Windows中「PRN」的API。作爲一種解決方法,實驗表明,使用非法文件名會在嘗試訪問屬性時產生明顯的異常(例如,使用Files.getLastModifiedTime())。

如果指定確實存在的文件合法名稱,你也不例外。

如果您爲不存在的文件指定合法名稱,則會提高NoSuchFileException

如果指定非法名稱,則會引發FileSystemException

但是,這似乎非常kludgey,並可能在其他操作系統上不可靠。

+2

你要刪除您剛剛創建,但該文件,因爲該功能OKtoRename不應該真正改變文件系統,只是回答如果文件名會工作。 – 2009-05-21 17:18:49

+1

@馬特:Ooor,你只需要創建一個文件,如果createNewFile返回false,這意味着該文件名無效(...或無法創建:-S)¬¬ – OscarRyz 2009-05-21 17:20:40

+0

準確,我想我會一起去這個解決方案,但我不喜歡創建一個空文件只是將其刪除隨即... – 2009-05-21 17:21:39

57

基於幾個月前的一些在線研究,我彙集了非法文件名字符(考慮UNIX,Mac OS X和Windows系統)的列表。如果新文件名包含這些文件中的任何一個,則存在其可能無法在所有平臺上有效的風險。

private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' }; 

編輯: 我想強調,這是不是一個完整的解決方案:作爲一個評論者所指出的,儘管它通過測試你的文件名可能仍然是一個Windows特定關鍵字如COM,PRN等。但是,如果您的文件名包含任何這些字符,它肯定會在跨平臺環境中造成麻煩。

2

對我來說,它似乎是一個操作系統相關的問題。您可能只是想檢查文件名中的一些無效字符。 Windows在嘗試重命名文件時執行此操作,它會彈出一條消息,指出文件不能包含以下任何字符:\ /:*? <> | 我不確定你的問題是「是否有一個圖書館爲我工作?」在那種情況下我不知道。

0

使用

String validName = URLEncoder.encode(fileName , "UTF-8"); 

File newFile = new File(validName); 

做的工作。

我今天剛剛找到。我不確定它是否能夠百分之百地工作,但到目前爲止,我已經能夠創建有效的文件名。

4

這是我如何實現這一點:

public boolean isValidFileName(final String aFileName) { 
    final File aFile = new File(aFileName); 
    boolean isValid = true; 
    try { 
     if (aFile.createNewFile()) { 
      aFile.delete(); 
     } 
    } catch (IOException e) { 
     isValid = false; 
    } 
    return isValid; 
} 
16

Here系統特定的方式提出了建議。

public static boolean isFilenameValid(String file) { 
    File f = new File(file); 
    try { 
    f.getCanonicalPath(); 
    return true; 
    } catch (IOException e) { 
    return false; 
    } 
} 
4

如果Eclipse的開發,退房org.eclipse.core.internal.resources.OS

public abstract class OS { 
    private static final String INSTALLED_PLATFORM; 

    public static final char[] INVALID_RESOURCE_CHARACTERS; 
    private static final String[] INVALID_RESOURCE_BASENAMES; 
    private static final String[] INVALID_RESOURCE_FULLNAMES; 

    static { 
     //find out the OS being used 
     //setup the invalid names 
     INSTALLED_PLATFORM = Platform.getOS(); 
     if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) { 
     //valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp 
     INVALID_RESOURCE_CHARACTERS = new char[] {'\\', '/', ':', '*', '?', '"', '<', '>', '|'}; 
     INVALID_RESOURCE_BASENAMES = new String[] {"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ 
       "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ 
       "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ 
     Arrays.sort(INVALID_RESOURCE_BASENAMES); 
     //CLOCK$ may be used if an extension is provided 
     INVALID_RESOURCE_FULLNAMES = new String[] {"clock$"}; //$NON-NLS-1$ 
     } else { 
     //only front slash and null char are invalid on UNIXes 
     //taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html 
     INVALID_RESOURCE_CHARACTERS = new char[] {'/', '\0',}; 
     INVALID_RESOURCE_BASENAMES = null; 
     INVALID_RESOURCE_FULLNAMES = null; 
     } 
    } 

    /** 
    * Returns true if the given name is a valid resource name on this operating system, 
    * and false otherwise. 
    */ 
    public static boolean isNameValid(String name) { 
     //. and .. have special meaning on all platforms 
     if (name.equals(".") || name.equals("..")) //$NON-NLS-1$ //$NON-NLS-2$ 
     return false; 
     if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) { 
     //empty names are not valid 
     final int length = name.length(); 
     if (length == 0) 
      return false; 
     final char lastChar = name.charAt(length-1); 
     // filenames ending in dot are not valid 
     if (lastChar == '.') 
      return false; 
     // file names ending with whitespace are truncated (bug 118997) 
     if (Character.isWhitespace(lastChar)) 
      return false; 
     int dot = name.indexOf('.'); 
     //on windows, filename suffixes are not relevant to name validity 
     String basename = dot == -1 ? name : name.substring(0, dot); 
     if (Arrays.binarySearch(INVALID_RESOURCE_BASENAMES, basename.toLowerCase()) >= 0) 
      return false; 
     return Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) < 0; 
     } 
     return true; 
    } 
} 
2

只是我發現,在Java 7和更高版本,有一個叫做Paths類,有一個叫get方法,它有一個或多個String S和拋出

InvalidPathException - 如果路徑字符串不能被轉換爲一個路徑

相關問題