C#将档案合并为一个文件



代码:

public void mergeFiles(string dir)
{
for (int i = 0; i < parts; i++)
{
if (!File.Exists(dir))
{
File.Create(dir).Close();
}
var output = File.Open(dir, FileMode.Open);
var input = File.Open(dir + ".part" + (i + 1), FileMode.Open);
input.CopyTo(output);
output.Close();
input.Close();
File.Delete(dir + ".part" + (i + 1));
}
}

dir变量例如为/path/file.txt.gz

我有一个文件打包到.gz档案中。这个档案分为8个部分,我想得到这个文件。

问题是我不知道如何组合这些文件"文件.gz.part1…";以便稍后提取。

当我使用上述功能时,档案已损坏
我已经在网上找了一个星期了,但这是我找到的最好的解决方案,它不起作用。

有人对如何将归档部分合并为一个文件有什么建议吗

您的代码有一些问题。如果您查看System的文档。IO.Stream.Close你会看到以下备注(重点是我的(:

关闭当前流并释放与当前流关联的任何资源(如套接字和文件句柄(与其调用此方法,不如确保正确地处理了流

因此,根据文档,您希望处理您的流,而不是直接调用close(我稍后再谈(。忽略这一点,你的主要问题就在这里:

var output = File.Open(dir, FileMode.Open);

您正在使用FileMode.Open作为输出文件。再次从文档:

指定操作系统应打开现有文件。打开文件的能力取决于FileAccess枚举指定的值。如果文件不存在,则引发FileNotFoundException异常。

这是在文件的开头打开一个流。因此,您要在输出文件的开头重复写入每个部分文件。我相信你注意到了,你的合并文件大小只有最大的部分文件那么大。从另一方面来看FileMode.Append

打开文件(如果存在(并查找文件的末尾,或者创建一个新文件。这需要追加权限。FileMode.Append只能与FileAccess.Write一起使用。试图在文件结尾之前查找某个位置会引发IOException异常,任何读取尝试都会失败并引发NotSupportedException异常。

可以-但备份更进一步,这是:

if (!File.Exists(dir))
{
File.Create(dir).Close();
}
var output = File.Open(dir, FileMode.Open);

是无效的。为什么我们要检查文件存在n次,然后打开/关闭n次?我们可以在第一步创建文件,并保持输出流打开,直到我们将所有数据附加到它

那么,在修复bug的同时,我们如何重构代码以使用IDisposable呢?查看using语句。把所有这些放在一起,你的代码可能看起来像这样:

public void mergeFiles(string dir)
{
using (FileStream combinedFile = File.Create(dir))
{
for (int i = 0; i < parts; i++)
{
// Since this string is referenced more than once, capture as a
// variable to lower risk of copy/paste errors.
var splitFileName = dir + ".part" + (i + 1);
using (FileStream filePart = File.Open(splitFileName, FileMode.Open))
{
filePart.CopyTo(combinedFile);
}
// Note that it's safe to delete the file now, because our filePart
// stream has been disposed as it is out of scope.
File.Delete(splitFileName);
}
}
}

试试看。这里有一个完整的工作程序,其中有一个人为的例子,你可以把它放到一个新的控制台应用程序中运行:

using System.IO;
using System.Text;
namespace temp_test
{
class Program
{
static int parts = 10;
static void Main(string[] args)
{
// First we will generate some dummy files.
generateFiles();
// Next, open files and combine.
combineFiles();
}
/// <summary>
/// A contived example to generate some files.
/// </summary>
static void generateFiles()
{
for (int i = 0; i < parts; i++)
{
using (FileStream newFile = File.Create("splitfile.part" + i))
{
byte[] info = new UTF8Encoding(true).GetBytes($"This is File # ${i.ToString()}");
newFile.Write(info);
}
}
}
/// <summary>
/// A contived example to combine our files.
/// </summary>
static void combineFiles()
{
using (FileStream combinedFile = File.Create("combined"))
{
for (int i = 0; i < parts; i++)
{
var splitFileName = "splitfile.part" + i;
using (FileStream filePart = File.Open(splitFileName, FileMode.Open))
{
filePart.CopyTo(combinedFile);
}
// Note that it's safe to delete the file now, because our filePart
// stream has been disposed as it is out of scope.
File.Delete(splitFileName);
}
}
}
}
}

祝你好运,欢迎来到StackOverflow!

相关内容

最新更新