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

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

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

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

像是很常用的 [System.IO.Path 類別](http://msdn.microsoft.com/zh-tw/library/system.io.path.aspx)就定義了兩個非常實用的方法(method)，分別是以下兩個：

-   [Path.GetInvalidFileNameChars 方法](http://msdn.microsoft.com/zh-tw/library/system.io.path.getinvalidfilenamechars.aspx)
-   [Path.GetInvalidPathChars 方法](http://msdn.microsoft.com/zh-tw/library/system.io.path.getinvalidpathchars.aspx)

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

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

最後，我總結出以下程式：

```csharp
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 就對目錄名與檔名的限制更多，相關資訊可參考以下相關連結。

**相關連結**

-   [Path.GetInvalidFileNameChars 方法](http://msdn.microsoft.com/zh-tw/library/system.io.path.getinvalidfilenamechars.aspx)
-   [Path.GetInvalidPathChars 方法](http://msdn.microsoft.com/zh-tw/library/system.io.path.getinvalidpathchars.aspx)
-   [Invalid Filename Characters](https://web.archive.org/web/20151017050126/http://www.devtrends.com:80/index.php/invalid-filename-characters/) (SharePoint)
-   [您無法在網站、 資料夾和 SharePoint 入口 Server 2003 中，或在 SharePoint Server 2007 檔案中使用的字元的相關資訊](http://support.microsoft.com/?scid=kb;zh-tw;905231&x=10&y=12)
-   [File Name Characters to Avoid](https://web.archive.org/web/20101205032917/http://www.worldstart.com:80/tips/tips.php/738)
-   [Regex expression to replace invalid filename characters.](http://bytes.com/topic/c-sharp/answers/239679-regex-expression-replace-invalid-filename-characters)
