【问题标题】:File.OpenRead() Directories , Sub Directories , Files, and then Write Folders and files to another directoryFile.OpenRead() 目录、子目录、文件,然后将文件夹和文件写入另一个目录
【发布时间】:2018-01-20 02:22:18
【问题描述】:

我希望从这样的目录结构中读取文件夹和文件.. 例如

C:\RootFolder
            SubFolder1
               SubFolder2
                   File1
                   File2
                         SubFolder3
                                 File3
 Files....
 Files....

我想同时读取文件和文件夹并写入另一个我不能使用 copy 的目录,因为我要写入的目录是远程的而不是本地的。

我在这里阅读了文件....我希望能够读取文件夹和文件并将两者都写入另一个目录。

 public static IEnumerable<FileInfo> GetFiles(string dir)
        {
            return Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories)
                .Select(path =>
                {                    
                    var stream = File.OpenRead(path);
                    return new FileInfo(Path.GetFileName(path), stream);
                })
                .DisposeEach(c => c.Content);
        }

此函数将文件写入远程 sftp 站点。

 public Task Write(IEnumerable<FileInfo> files)
        {
            return Task.Run(() =>
            {
                using (var sftp = new SftpClient(this.sshInfo))
                {
                    sftp.Connect();
                    sftp.ChangeDirectory(this.remoteDirectory);

                    foreach (var file in files)
                    {
                      sftp.UploadFile(file.Content, file.RelativePath);
                    }
                }
            });
        }

在这个函数中,我从上面的函数中写入读取的文件。

    private async static Task SendBatch(Config config, Batch batch, IRemoteFileWriter writer)
    {
        var sendingDir = GetClientSendingDirectory(config, batch.ClientName);
        Directory.CreateDirectory(Path.GetDirectoryName(sendingDir));
        Directory.Move(batch.LocalDirectory, sendingDir);
        Directory.CreateDirectory(batch.LocalDirectory);
        //Use RemoteFileWriter...
        var files = GetFiles(sendingDir);

        await writer.Write(files).ContinueWith(t =>
        {
            if(t.IsCompleted)
            {
                var zipArchivePath = GetArchiveDirectory(config, batch);
                ZipFile.CreateFromDirectory(
                    sendingDir,
                    zipArchivePath + " " +
                    DateTime.Now.ToString("yyyy-MM-dd hh mm ss.Zip")
                    );
            }
        });



    }

谢谢!

【问题讨论】:

  • 为什么有人会拒绝这个问题?这不是一个合法的问题还是这个问题有什么问题......我想知道以供将来参考。谢谢
  • 英语不是您的主要语言吗?你的措辞很尴尬。 “在我成功读取文件后,除非我特别选择,否则我无法做到”什么?
  • 我的意思是,你的英语很难懂。我怀疑这就是你被否决的原因。我会尝试澄清我引用的那句话。
  • 我认为后面解释的句子选择“读取没有文件夹的文件或仅当我结合我得到“未经授权的异常”时才从文件夹中读取这是否解释了我的选择......?
  • 你的编辑好多了。

标签: c# filestream


【解决方案1】:

您收到UnauthorizedAccessException: Access to the path 'C:\temp' is denied. 是因为您无法从文件夹打开流,因为它不包含字节。

据我了解,您希望将文件从一个文件夹复制到另一个文件夹。

这个答案似乎涵盖了你在做什么。 https://stackoverflow.com/a/3822913/3634581

复制目录后,您可以创建 zip 文件。

如果您不需要复制文件而只需创建 Zip,我建议您这样做,因为它会减少磁盘 IO 并加快进程。

ZipArchive (https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx) 可用于将 zip 文件直接创建到流中。

【讨论】:

  • 谢谢你的回答,但我需要写而不是复制。我需要将文件写入 sftp 远程站点,这就是为什么我需要以它们所在的确切格式或结构读取文件的原因。我将添加 Write 函数来帮助澄清这个过程。
  • 我运行了 Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories) 函数,它只是为我返回了文件。您需要创建空文件夹吗?如果是这样,我会说您将需要两种方法,一种是创建文件夹,另一种是上传文件。
  • 是的,这正是我想要做的,但障碍是如何关联文件和文件夹。例子;如果我创建文件夹 A,如何确保文件 A 在里面,它会变得更加复杂,因为我在子文件夹中的子文件夹中有文件夹。我确实找到了一种有用的方法 Path.GetRelativePath(string relative to, string path) 希望我能尽快找到它,我会分享答案:) 再次感谢!!
  • 如果您查看我链接到的问题的第二个答案,您可以看到如何递归地遍历路径。我认为这就是确保您可以按照您正在寻找的方式复制目录和文件所需的全部内容。 stackoverflow.com/a/58779/3634581 不用调用file.CopyTo,你可以上传文件,然后在函数顶部创建目录。
  • 再次感谢,这确实给了我一个想法,但是 sftp 库没有像 .Net I.O 库中那样的方法。
【解决方案2】:

我发现这是解决方案

 public Task Write(IEnumerable<FileInfo> files)
    {
        return Task.Run(() =>
        {
            using (var sftp = new SftpClient(this.sshInfo))
            {
                sftp.Connect();
                sftp.ChangeDirectory(this.remoteDirectory);

                foreach (var file in files)
                {
                    var parts = Path.GetDirectoryName(file.RelativePath)
                        .Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);

                    sftp.ChangeDirectory(this.remoteDirectory);

                    foreach (var p in parts)
                    {
                        try
                        {
                            sftp.ChangeDirectory(p);
                        }
                        catch (SftpPathNotFoundException)
                        {
                            sftp.CreateDirectory(p);
                            sftp.ChangeDirectory(p);
                        }
                    }

                    sftp.UploadFile(file.Content, Path.GetFileName(file.RelativePath));
                }
            }
        });
    }

****解决方案的关键点是 这个

var parts = Path.GetDirectoryName(file.RelativePath)
                            .Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);

我们调用 *Path.GetDirectoryName 在文件本身上以获取与文件相关的目录。 我们拆分文件目录得到文件夹名,最后创建我们拆分得到的文件夹名并上传文件。

我希望这对可能遇到此类问题的其他人有所帮助。

【讨论】:

    猜你喜欢
    • 2013-07-02
    • 2011-07-07
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 2013-01-19
    • 2021-09-23
    相关资源
    最近更新 更多