【问题标题】:Read a large binary file(5GB) into a byte array in C#?在 C# 中将大型二进制文件(5GB)读入字节数组?
【发布时间】:2017-05-23 14:07:12
【问题描述】:

我有一个超过 5 GB 的录音文件(二进制文件),我必须读取该文件并过滤掉需要发送到服务器的数据。

问题是 byte[] 数组支持直到 2GB 的文件数据。所以如果有人已经处理过这种情况,就需要帮助。

using (FileStream str = File.OpenRead(textBox2.Text))
{
       int itemSectionStart = 0x00000000;
       BinaryReader breader = new BinaryReader(str);
       breader.BaseStream.Position = itemSectionStart;
       int length = (int)breader.BaseStream.Length;
       byte[] itemSection = breader.ReadBytes(length );  //first frame data
}

问题:

1: Length is crossing the range of integer.
2: tried using long and unint but byte[] only supports integer

编辑。

我想尝试的另一种方法,基于帧缓冲区读取数据,假设我的帧缓冲区大小为 24000 。所以字节数组存储那么多帧数据,然后处理帧数据,然后刷新字节数组并存储另外24000帧数据。直到二进制文件结束..

【问题讨论】:

  • 你真的需要一次内存中的所有数据吗?因为听起来您应该实施一种流式方法来过滤数据。
  • 是....因为必须读取文件中的特定模式并且必须对其应用过滤
  • 我建议您尽可能逐位处理文件,而不是将整个文件读入内存。例如读取第一个块,过滤它,然后在读取和处理下一个块之前将其发送到服务器(或写入临时文件)。根据您正在执行的过滤类型,您可能需要多次通过。你能提供更多关于需要什么过滤的细节吗?
  • 您使用的是哪个版本的 .NET 框架?
  • 如果你不能让你的项目以 .NET 4.5 为目标(当然也可以在安装了 .NET 4.5+ 的机器上运行),那么你就不走运了。否则,请参阅:msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

标签: c# visual-studio-2008 c#-3.0


【解决方案1】:

看到你不能一次读取这么大的文件,所以你必须将文件分成小部分然后处理文件。

 OR

使用缓冲区概念读取文件,一旦完成该缓冲区数据,然后刷新该缓冲区。

我遇到了同样的问题,所以我尝试了基于缓冲区的方法,它对我有用。

         FileStream inputTempFile = new FileStream(Path, FileMode.OpenOrCreate, FileAccess.Read);
           Buffer_value = 1024;
            byte[] Array_buffer = new byte[Buffer_value];
            while ((bytesRead = inputTempFile.Read(Array_buffer, 0, Buffer_value)) > 0)
            {
               for (int z = 0; z < Array_buffer.Length; z = z + 4)
               {
                  string temp_id = BitConverter.ToString(Array_buffer, z, 4);
                  string[] temp_strArrayID = temp_id.Split(new char[] { '-' });
                  string temp_ArraydataID = temp_strArrayID[0] + temp_strArrayID[1] + temp_strArrayID[2] + temp_strArrayID[3];
               }
            }

这样你就可以处理你的数据了。

对于我的情况,我试图将缓冲区读取数据存储到一个列表中,它可以正常工作,直到 2GB 数据之后它会引发内存异常。

我遵循的方法,从缓冲区读取数据并应用所需的过滤器并将过滤器数据写入文本文件,然后处理该文件。

//文本文件方法

           FileStream inputTempFile = new FileStream(Path, FileMode.OpenOrCreate, FileAccess.Read);
           Buffer_value = 1024;
            StreamWriter writer = new StreamWriter(Path, true);
            byte[] Array_buffer = new byte[Buffer_value];
            while ((bytesRead = inputTempFile.Read(Array_buffer, 0, Buffer_value)) > 0)
            {
               for (int z = 0; z < Array_buffer.Length; z = z + 4)
               {
                 string temp_id = BitConverter.ToString(Array_buffer, z, 4);
                 string[] temp_strArrayID = temp_id.Split(new char[] { '-' });
                 string temp_ArraydataID = temp_strArrayID[0] + temp_strArrayID[1] + temp_strArrayID[2] + temp_strArrayID[3];
                 if(temp_ArraydataID =="XYZ Condition")
                 { 
                     writer.WriteLine(temp_ArraydataID);
                 }
               }

            }
           writer.Close();

【讨论】:

    【解决方案2】:

    正如 cmets 中所说,我认为您必须使用流读取文件。您可以这样做:

    int nbRead = 0;
    var step = 10000;
    byte[] buffer = new byte[step];
    do
    {
        nbRead = breader.Read(buffer, 0, step);
        hugeArray.Add(buffer);
    
        foreach(var oneByte in hugeArray.SelectMany(part => part))
        {
            // Here you can read byte by byte this subpart
        }
    }
    while (nbRead > 0);
    

    如果我很了解您的需求,您是否正在寻找文件中的特定模式?

    我认为您可以通过逐字节查找模式的开头来做到这一点。一旦你找到它,你就可以开始阅读重要的字节了。如果整个重要数据大于 2GB,如 cmets 中所说,您必须将其分几部分发送到您的服务器。

    【讨论】:

    • 我想稍后将完整的数据存储在字节数组中我想在保存数据中进行过滤
    • @user5794230 好吧... 你不能;您要么需要多个字节数组,要么需要流式传输数据。您也可以考虑一大块非托管内存或内存映射文件,但是……这似乎有点过分了
    • @user5794230 是的,我明白了,但我认为你不能因为 byte[] 大小限制。你真的不能逐个过滤吗?这对我来说是一个巨大的算法挑战:D。正如 Marc Gravell 所说,您也可以查看 msdn.microsoft.com/en-us/library/…,但我从不使用它,所以我无能为力。
    • @user5794230 看看我的编辑。这对你有帮助吗?这只是一个在没有数组的情况下逐字节读取整个数据的示例,但我不知道您的 5GB 是否可以进行枚举
    • @user5794230 你能根据你的需要更新你的问题吗?在 cmets 中很难阅读和理解
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 2016-02-29
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    相关资源
    最近更新 更多