The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何確保寫入檔案時「檔案名稱」與「目錄名稱」正確無誤

當要在檔案系統 (Filesystem) 寫入檔案時必須指定完整的路徑與檔名,但有時「檔案名稱」需透過程式指定時就有可能發生「檔案名稱無效」的錯誤,這時就需要透過程式過濾掉一些無效字元,才能讓成功建立檔案。

網路上資料雜亂,使用錯誤的方法也很多,所以我通常在網路上搜尋資料時通常不敢亂用,一般都會多方資料蒐集並且自行測試驗證過後才敢放心使用。

我覺得用 .NET Framework 寫程式最忌諱 重新發明輪子 (Reinventing the wheel),正確的觀念應該是能用 .NET Framework 做出來的功能,千萬不要自行實做,這樣才能確保你的 .NET 程式在未來更有可攜性(portability) [ 例如日後程式需要移到 Linux 平台實做 ]。

像是很常用的 System.IO.Path 類別就定義了兩個非常實用的方法(method),分別是以下兩個:

透過這兩個方法就可以得知在目前平台下 [如: Windows] 對於「目錄名」與「檔名」的被限制一定不能使用的字元有哪些,除此之外的字元都可以當作檔名或目錄名,例如中文或其他 Unicode 字元。

除了被限制的字元外,在檔名最後面不能出現小數點,也就是你可以沒有副檔名,但你不能用「空白」的副檔名,因此這類情況也必須將結尾的小數點全部刪除才行。

最後,我總結出以下程式:

static string MakeFilenameValid(string filename)
{
    if (filename == null)
        throw new ArgumentNullException();

    if (filename.EndsWith("."))
        filename = Regex.Replace(filename, @"\.+$", "");

    if (filename.Length == 0)
        throw new ArgumentException();

    if (filename.Length > 245)
        throw new PathTooLongException();

    foreach (char c in System.IO.Path.GetInvalidFileNameChars())
    {   
        filename = filename.Replace(c, '_');
    }
        
    return filename;
}

static string MakeFoldernameValid(string foldername)
{
    if (foldername == null)
        throw new ArgumentNullException();

    if (foldername.EndsWith("."))
        foldername = Regex.Replace(foldername, @"\.+$", "");

    if (foldername.Length == 0)
        throw new ArgumentException();
    
    if (foldername.Length > 245)
        throw new PathTooLongException();
    
    foreach (char c in System.IO.Path.GetInvalidPathChars())
    {
        foldername = foldername.Replace(c, '_');
    }

    return foldername;
}

除了檔案系統外,在各種不同的應用系統或平台對於目錄與檔名的限制也不一定一樣,例如 SharePoint 就對目錄名與檔名的限制更多,相關資訊可參考以下相關連結。

相關連結