我有一堆非常大的视频文件(.ts),从3GB到10GB不等。其中很多都有特定的错误,我的解决方案是简单地去掉包含错误的部分。我已经知道了我想要保留的部分的开始和结束偏移,我希望只需读入主文件,并将从start_offset到end_offset复制到同一文件夹中的新文件中。
例如,我有主视频main.ts,它是5.5GB。假设它有两个这样的错误。我想保留偏移量(十进制,而不是十六进制)0到1174698823(错误开始前的字节),并将其保存到一个新文件中,PART1.ts。然后,我想保留偏移1257553244(错误结束后的字节)到偏移4126897791(第二个错误开始),并将其保存为PART2.ts。之后,我需要将文件结束时的偏移4207333028保存为PART3.ts。基本上,我只截取了大约155MB的文件,并将它分为三部分。如果我真的可以在不创建多个新文件的情况下执行剪切,而是在执行时将它们彼此附加,然后写入整个新文件,那将是一个额外的好处(或者我稍后可以使用copy /b
)。
我一直在研究文件流和字节阵列,我知道2GB的限制。我该如何绕过这个问题,然后如果我试图保留的块的长度大于2GB,我该如何编写它?我不知道如何使用有限长度的缓冲区来做到这一点。如果可能的话,我也想有一个进度条来显示写了多少。
如有任何帮助,我们将不胜感激。
您绝对不需要创建新文件。您只需打开一次输出文件和一次输入文件,然后通过在输入文件中查找来附加块,然后在进入下一个部分之前将输入流中的一个部分复制到输出流中。
using (var output = File.Create("output.ts"))
using (var input = File.OpenRead("input.ts"))
{
AppendChunk(output, input, 0, 1174698823L);
AppendChunk(output, input, 1257553244L, 4126897791L);
}
...
private static void AppendChunk(Stream output, Stream input,
long start, long end)
{
// TODO: Argument validation
long size = end - start;
byte[] buffer = new byte[32 * 1024]; // Copy 32K at a time
input.Position = start;
while (size > 0)
{
int bytesRead = input.Read(buffer, 0, Math.Min(size, buffer.Length));
if (bytesRead <= 0)
{
throw new EndOfStreamException("Not enough data");
}
output.Write(buffer, 0, bytesRead);
size -= bytesRead;
}
}
要集成进度条,您需要事先计算出要复制的总大小,然后在循环中,增加到目前为止复制的总规模,并以这种方式更新进度条。不要忘记,如果这是在WinForms或WPF中,则不应该在UI线程上执行任何IO工作。