我有两个RIFF文件,我将块从一个文件复制到另一个文件。我正在使用的RIFF格式是:
我使用以下代码从源文件复制到目标文件。块被称为帧。
public void CopySegmentTo(VPCaptureSession captureSession, int StartFrame, int EndFrame) {
//captures several frames from this session onto the end of another one.
//binary-styles
Console.WriteLine(" captureSession.captureStream.Position: " + captureSession.captureStream.Position);
long lastCaptureDestPosition = 0;
captureSession.captureStream.Seek(0, SeekOrigin.End);
int chunkLength; long timestamp; char[] charTag;
for (int f = StartFrame; f <= EndFrame; f++)
{
Console.WriteLine("-----");
this.captureStream.Seek(FrameTimes.ElementAt(f).Item3, SeekOrigin.Begin);
Console.WriteLine("FrameIndex in this.captureStream: " + FrameTimes.ElementAt(f).Item3);
BinaryReader reader = new BinaryReader(this.captureStream);
byte[] tag = reader.ReadBytes(Tags.TAG_SIZE);
charTag = TagChunk.encode.GetChars(tag);
chunkLength = reader.ReadInt32();
BinaryWriter writer = new BinaryWriter(captureSession.captureStream);
writer.Write(tag);
writer.Write(chunkLength);
this.captureStream.CopyTo(captureSession.captureStream, chunkLength);
long CaptureDestDelta = captureSession.captureStream.Position - lastCaptureDestPosition;
Console.WriteLine("Loading " + f + " between " + StartFrame + "&" + EndFrame
+ ". chunkLength: " + chunkLength
+ " this.captureStream.Position: " + this.captureStream.Position
+ " captureSession.captureStream.Position: " + captureSession.captureStream.Position
+ " CaptureDestDelta: " + CaptureDestDelta
+ " Delta Factor: " + CaptureDestDelta/chunkLength);
lastCaptureDestPosition = captureSession.captureStream.Position;
}
}
复制速度很慢,结果文件似乎很大。以下是Console
输出的示例:
captureSession.captureStream.Position: 0
-----
FrameIndex in this.captureStream: 0
Loading 0 between 0&5. chunkLength: 266736 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 121225207 CaptureDestDelta: 121225207
Delta Factor: 454
-----
FrameIndex in this.captureStream: 266744
Loading 1 between 0&5. chunkLength: 311398 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 242183670 CaptureDestDelta: 120958463
Delta Factor: 388
-----
FrameIndex in this.captureStream: 578150
Loading 2 between 0&5. chunkLength: 356578 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 362830727 CaptureDestDelta: 120647057
Delta Factor: 338
-----
FrameIndex in this.captureStream: 934736
Loading 3 between 0&5. chunkLength: 430445 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 483121198 CaptureDestDelta: 120290471
Delta Factor: 279
-----
FrameIndex in this.captureStream: 1365189
Loading 4 between 0&5. chunkLength: 437468 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 602981216 CaptureDestDelta: 119860018
Delta Factor: 273
-----
FrameIndex in this.captureStream: 1802665
Loading 5 between 0&5. chunkLength: 439870 this.captureStream.Position: 121225207
captureSession.captureStream.Position: 722403758 CaptureDestDelta: 119422542
Delta Factor: 271
肯定会有一些奇怪的事情发生。这是我看到的主要内容:
captureSession.captureStream.Position
每次都比chunkLength
前进得更远。
this.captureStream.Position
在每次复制后似乎总是相同。
如果还有更多我可以登录,请告诉我。我真的被困在这里了。
答案 0 :(得分:2)
您有几个问题,主要问题是您正在调用的Stream.Copy
方法复制整个流(从当前位置)。第二个参数是缓冲区大小,而不是要复制的字节数。
此外,您为循环的每次迭代创建一个新的BinaryReader
和一个新的BinaryWriter
。这两个类都分配了托管资源,应该在完成后处理。不幸的是,处理也会关闭底层流。但是留下这些对象只是在某些时候乞求资源匮乏问题,特别是如果你开始复制文件的大部分内容。
我建议您放弃BinaryReader
和BinaryWriter
并直接转到溪流。
您可以使用Stream.Read来读取数据,唯一的困难是读取int
会要求您读取4个字节,然后调用BitConverter.ToInt32转换为整数。您也可以使用该方法从源复制数据(即读入大字节[]缓冲区),然后使用Stream.Write
写入输出文件。
如果您使用的是.NET 4.5,则还有其他选择。在开始循环之前,您可以在输入上打开BinaryReader
,在输出上打开BinaryWriter
。 .NET 4.5引入了一个新的构造函数,可以让您说明在处理读取器/写入器后是否要保持底层流的打开。在您的代码中,它看起来像这样:
using (var reader = new BinaryReader(this.CaptureStream, Encoding.Default, true))
{
using (var writer = new BinaryWriter(captureSession.captureStream, Encoding.Default, true))
{
for (int f = StartFrame; f <= EndFrame; f++)
{
}
}
}
您仍然可以对输入流进行搜索,读者也会做正确的事情。虽然您可能想写reader.BaseStream.Seek(...)
。
然后,您可以使用BinaryReader.ReadInt32
阅读现有代码,BinaryReader.Read(byte[], int, int)和BinaryWriter.Write(byte[], int32, int32)复制块数据。
(直到刚才我才意识到.NET 4.5最终解决了BinaryReader
和BinaryWriter
关闭流的问题。)
答案 1 :(得分:0)
我误解了Stream.CopyTo(Stream destination, int bufferSize)
中bufferSize的含义。我认为这是要复制的总字节数,而不仅仅是复制时要使用的缓冲区。 Stream
对象中没有任何功能只能复制特定数量的字节。我通过替换
this.captureStream.CopyTo(captureSession.captureStream, chunkLength);
与
writer.Write(reader.ReadBytes(chunkLength));