文件流在128字节后从A读取并写入B C#

文件流在128字节后从A读取并写入B C#,c#,filestream,large-files,C#,Filestream,Large Files,我有一个大文件(大约400GB),我需要对其进行文件流处理,并将前128个字节跳过到另一个文件中。我有下面的代码,但它工作不正常,因为当我在流结束后检查文件大小时,文件B丢失了超过128个字节。我做错了什么 private void SplitUnwantedHeader(string file1, string file2) { FileStream fr = new FileStream(file1, FileMode.Open, FileAccess.Read);

我有一个大文件(大约400GB),我需要对其进行文件流处理,并将前128个字节跳过到另一个文件中。我有下面的代码,但它工作不正常,因为当我在流结束后检查文件大小时,文件B丢失了超过128个字节。我做错了什么

private void SplitUnwantedHeader(string file1, string file2)
    {
        FileStream fr = new FileStream(file1, FileMode.Open, FileAccess.Read);
        FileStream fw = new FileStream(file2, FileMode.Create, FileAccess.Write);

        byte[] fByte = new byte[65534];
        long headerToSplit = 128;
        int bytesRead = 0;

        try
        {
            fr.Position = headerToSplit;
            do
            {
                bytesRead = fr.Read(fByte, 0, fByte.Length);
                fw.Write(fByte, 0, fByte.Length - (int)headerToSplit);
            } while (bytesRead != 0);
        }
        catch (Exception ex)
        {
            UpdateStatusBarMessage.ShowStatusMessage(ex.Message);
        }
        finally
        {
            fw.Close();
            fr.Close();
        }
    }
谢谢。

电话线

 fw.Write(fByte, 0, fByte.Length - (int)headerToSplit);
在这样的循环中使用时是错误的。它将在每个循环周期写入“缓冲区大小”减去128字节。相反,代码应该在复制期间写入
bytesRead
count

 fw.Write(fByte, 0, bytesRead);
仅在进入“复制所有其他内容”循环之前执行偏移。此外,循环可以替换为(从.NET4开始),并且可以整理资源管理

也就是说,考虑一下:

using (var fr = new FileStream(file1, FileMode.Open, FileAccess.Read))
using (var fw = new FileStream(file2, FileMode.Create, FileAccess.Write)) {
    fr.Position = 128; // or fr.Seek(128, SeekOrigin.Begin);
    fr.CopyTo(fw, 65534);
}
线路

 fw.Write(fByte, 0, fByte.Length - (int)headerToSplit);
在这样的循环中使用时是错误的。它将在每个循环周期写入“缓冲区大小”减去128字节。相反,代码应该在复制期间写入
bytesRead
count

 fw.Write(fByte, 0, bytesRead);
仅在进入“复制所有其他内容”循环之前执行偏移。此外,循环可以替换为(从.NET4开始),并且可以整理资源管理

也就是说,考虑一下:

using (var fr = new FileStream(file1, FileMode.Open, FileAccess.Read))
using (var fw = new FileStream(file2, FileMode.Create, FileAccess.Write)) {
    fr.Position = 128; // or fr.Seek(128, SeekOrigin.Begin);
    fr.CopyTo(fw, 65534);
}

代码有两个问题:

  • 它不是跳过第一个块的前128字节,而是跳过每个块的最后128字节
  • 写入时忽略
    bytesRead
    值,因此可能是从缓冲区写入从未读取到缓冲区的数据。读取的字节数可以小于请求的字节数,即使您不在文件末尾
该代码是在循环之前跳过头和在循环内部跳过头的混合代码。你应该做一个,而不是两个都做

您可以检查缓冲区中的数据量与应跳过的数据量,并更新要跳过的字节数,以便在超出标头后为零:

do {
  bytesRead = fr.Read(fByte, 0, fByte.Length);
  if (bytesRead > headerToSplit) {
    fw.Write(fByte, (int)headerToSplit, bytesRead - (int)headerToSplit);
    headerToSplit = 0;
  } else {
    headerToSplit -= bytesRead;
  }
} while (bytesRead != 0);
或者,如果在循环之前跳过标头,只需将所有数据写入缓冲区:

fr.Position = headerToSplit;
do {
  bytesRead = fr.Read(fByte, 0, fByte.Length);
  fw.Write(fByte, 0, bytesRead);
} while (bytesRead != 0);

代码有两个问题:

  • 它不是跳过第一个块的前128字节,而是跳过每个块的最后128字节
  • 写入时忽略
    bytesRead
    值,因此可能是从缓冲区写入从未读取到缓冲区的数据。读取的字节数可以小于请求的字节数,即使您不在文件末尾
该代码是在循环之前跳过头和在循环内部跳过头的混合代码。你应该做一个,而不是两个都做

您可以检查缓冲区中的数据量与应跳过的数据量,并更新要跳过的字节数,以便在超出标头后为零:

do {
  bytesRead = fr.Read(fByte, 0, fByte.Length);
  if (bytesRead > headerToSplit) {
    fw.Write(fByte, (int)headerToSplit, bytesRead - (int)headerToSplit);
    headerToSplit = 0;
  } else {
    headerToSplit -= bytesRead;
  }
} while (bytesRead != 0);
或者,如果在循环之前跳过标头,只需将所有数据写入缓冲区:

fr.Position = headerToSplit;
do {
  bytesRead = fr.Read(fByte, 0, fByte.Length);
  fw.Write(fByte, 0, bytesRead);
} while (bytesRead != 0);