【问题标题】:FileStream read from A after 128 bytes and write to B C#FileStream 在 128 字节后从 A 读取并写入 B C#
【发布时间】:2014-03-12 12:35:52
【问题描述】:

我有一个大文件(大约 400GB),我需要 FileStream 并将前 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();
        }
    }

谢谢。

【问题讨论】:

    标签: c# filestream large-files


    【解决方案1】:

    线

     fw.Write(fByte, 0, fByte.Length - (int)headerToSplit);
    
    在这样的循环中使用

    错误。它将在每个循环周期写入“缓冲​​区大小” 128 个字节。相反,代码应该在复制期间写入 bytesRead 计数。

     fw.Write(fByte, 0, bytesRead);
    

    仅在进入 copy-everything-else 循环之前执行偏移。此外,循环可以替换为FileStream.CopyTo(从 .NET 4 开始),using 可以整理资源管理。

    也就是说,考虑:

    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);
    }
    

    【讨论】:

      【解决方案2】:

      代码有两处错误:

      • 不是跳过第一个块的前 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多