簡體   English   中英

創建文件,遞歸創建目錄

[英]creating files, recursively creating directories

我正在閱讀 C# 的一些文件 IO 教程並設法寫出一些文件,但是如果我給出的路徑包含目錄怎么辦?

例如,我想創建名為data/my_file的文件,但data文件夾不存在。

這條線,

BinaryWriter outFile = new BinaryWriter(File.OpenWrite(path));

其中path是上面的字符串,崩潰並顯示部分路徑不存在的消息,這意味着 C# 沒有按要求創建它們。

我希望 C# 為我處理所有混亂的目錄創建和檢查,而不是我必須解析路徑並創建所有必要的目錄。 這可能嗎? 否則,是否有一段代碼我可以復制到我的項目中來處理我可能忽略的任何事情(因為我對文件管理知之甚少)。

System.IO.Directory.CreateDirectory()將在指定路徑中創建所有目錄和子目錄,如果它們不存在的話。

您可以調用它,傳遞路徑,以確保在寫入文件之前創建文件夾結構。

雖然System.IO.Directory.CreateDirectory()確實會遞歸地為你創建目錄,但我遇到了一種情況,我不得不想出我自己的方法。 基本上, System.IO不支持超過 260 個字符的路徑,這迫使我使用Delimon.Win32.IO庫,該庫適用於長路徑,但不會遞歸創建目錄。

這是我用於遞歸創建目錄的代碼:

void CreateDirectoryRecursively(string path)
{
    string[] pathParts = path.Split('\\');

    for (int i = 0; i < pathParts.Length; i++)
    {
        if (i > 0)
            pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]);

        if (!Directory.Exists(pathParts[i]))
            Directory.CreateDirectory(pathParts[i]);
    }
}

這是我通常的做法

Directory.CreateDirectory(Path.GetDirectoryName(filePath));

^ 這應該確保在您的文件之前創建所有必需的文件夾(無論其中一些文件夾是否已經存在)。 例如,如果你傳遞它“c:/a/b/c/data/my file.txt”,它應該確保“c:/a/b/c/data”路徑被創建。

因此,對於基本目錄創建,上述內容對我來說效果不佳。 我對此做了一些修改,以處理驅動器號和末尾帶有文件資源的路徑的常見情況。

    public bool CreateDirectoryRecursively(string path)
    {
        try
        {
            string[] pathParts = path.Split('\\');
            for (var i = 0; i < pathParts.Length; i++)
            {
                // Correct part for drive letters
                if (i == 0 && pathParts[i].Contains(":"))
                {
                    pathParts[i] = pathParts[i] + "\\";
                } // Do not try to create last part if it has a period (is probably the file name)
                else if (i == pathParts.Length-1 && pathParts[i].Contains("."))
                {
                    return true;
                }
                if (i > 0) { 
                    pathParts[i] = Path.Combine(pathParts[i - 1], pathParts[i]);
                }
                if (!Directory.Exists(pathParts[i]))
                {
                    Directory.CreateDirectory(pathParts[i]);
                }
            }
            return true;
        }
        catch (Exception ex)
        {
            var recipients = _emailErrorDefaultRecipients;
            var subject = "ERROR: Failed To Create Directories in " + this.ToString() + " path: " + path;
            var errorMessage = Error.BuildErrorMessage(ex, subject);
            Email.SendMail(recipients, subject, errorMessage);
            Console.WriteLine(errorMessage);
            return false;

        }

    }

對於帶有可空檢查的 .Net 6:

var dstFilePath = Path.Combine(Path.GetTempPath(), "foo", "bar.txt");
var dstDirPath = Path.GetDirectoryName(dstFilePath) ??
                         throw new InvalidOperationException("Dst dir is invalid");
Directory.CreateDirectory(dstDirPath);

以前的答案沒有處理網絡路徑。 附加的代碼也處理這個問題。

/// <summary>
/// tests (and creates missing) directories in path containing many 
subDirectories which might not exist.
    /// </summary>
    /// <param name="FN"></param>
    public static string VerifyPath(string FN, out bool AllOK)
    {
        AllOK = true;
        var dir = FolderUtils.GetParent(FN);
        if (!Directory.Exists(dir))//todo - move to folderUtils.TestFullDirectory
        {
            const char DIR = '\\';
            //string dirDel = "" + DIR;

            string[] subDirs = FN.Split(DIR);
            string dir2Check = "";
            int startFrom = 1;//skip "c:\"
            FN = CleanPathFromDoubleSlashes(FN);
            if (FN.StartsWith("" + DIR + DIR))//netPath
                startFrom = 3;//FN.IndexOf(DIR, 2);//skip first two slashes..
            for (int i = 0; i < startFrom; i++)
                dir2Check += subDirs[i] + DIR;//fill in begining

            for (int i = startFrom; i < subDirs.Length - 1; i++)//-1 for the file name..
            {
                dir2Check += subDirs[i] + DIR;
                if (!Directory.Exists(dir2Check))
                    try
                    {
                        Directory.CreateDirectory(dir2Check);
                    }
                    catch { AllOK = false; }
            }
        }
        if (File.Exists(FN))
            FN = FolderUtils.getFirstNonExistingPath(FN);
        if (FN.EndsWith("\\") && !Directory.Exists(FN))
            try { Directory.CreateDirectory(FN); }
            catch
            {
                HLogger.HandleMesssage("couldn't create dir:" + FN, TypeOfExceptions.error, PartsOfSW.FileStructure);
                AllOK = false;
            }

        return FN;

    }

以及“CleanDoubleSlashes 函數”:

  public static string CleanPathFromDoubleSlashes(string basePath)
    {
        if (string.IsNullOrEmpty(basePath) || basePath.Length < 2)//don't clean first \\ of LAN address
            return basePath;
        for (int i = basePath.Length - 1; i > 1; i--)
        {
            if ((basePath[i] == '\\' && basePath[i - 1] == '\\') || (basePath[i] == '/' && basePath[i - 1] == '/'))
            {
                basePath = basePath.Remove(i, 1);//Substring(0, i - 2) + basePath.Substring(i, basePath.Length - 1 - i);
            }
        }
        return basePath;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM