c# - 大文件处理 - 读取算法中断 - C#

标签 c# .net large-files

所以我有一个算法可以从一个(非常大,~155+ MB)二进制文件中读取,根据规范解析它并写出必要的信息(到 CSV,纯文本)。它完美地处理前 1550 万行输出,生成约 0.99-1.03 GB 的 CSV 文件。这几乎不超过二进制文件的 20%。在此之后它中断了,因为突然打印的数据根本不是二进制文件中显示的内容。我检查了二进制文件,相同的模式继续(数据分成“数据包” - 请参见下面的代码)。由于其处理方式,内存使用量从未真正增加(稳定约 15K)。下面列出了功能代码。这是我的算法吗(如果是这样,为什么它会在 1550 万行之后中断?!)...由于文件很大,我没有考虑其他影响吗?有什么想法吗?

(仅供引用:每个“数据包”的长度为 77 个字节,以 3 字节的“开始代码”开始,以 5 字节的“结束代码”结束 - 您将看到下面的模式)

edit 代码已根据以下建议更新...谢谢!

private void readBin(string theFile)
{
    List<int> il = new List<int>();
    bool readyForProcessing = false;

    byte[] packet = new byte[77];

    try
    {
        FileStream fs_bin = new FileStream(theFile, FileMode.Open);
        BinaryReader br = new BinaryReader(fs_bin);

        while (br.BaseStream.Position < br.BaseStream.Length && working)
        {
            // Find the first startcode
            while (!readyForProcessing)
            {
                // If last byte of endcode adjacent to first byte of startcod...
                // This never occurs outside of ending/starting so it's safe
                if (br.ReadByte() == 0x0a && br.PeekChar() == (char)0x16)
                    readyForProcessing = true;
            }

            // Read a full packet of 77 bytes
            br.Read(packet, 0, packet.Length);

            // Unnecessary I guess now, but ensures packet begins
            // with startcode and ends with endcode
            if (packet.Take(3).SequenceEqual(STARTCODE) &&
                packet.Skip(packet.Length - ENDCODE.Length).SequenceEqual(ENDCODE))
            {
                il.Add(BitConverter.ToUInt16(packet, 3)); //il.ElementAt(0) == 2byte id
                il.Add(BitConverter.ToUInt16(packet, 5)); //il.ElementAt(1) == 2byte semistable
                il.Add(packet[7]); //il.ElementAt(2) == 1byte constant

                for(int i = 8; i < 72; i += 2) //start at 8th byte, get 64 bytes
                    il.Add(BitConverter.ToUInt16(packet, i));

                for (int i = 3; i < 35; i++)
                {
                    sw.WriteLine(il.ElementAt(0) + "," + il.ElementAt(1) +
                        "," + il.ElementAt(2) + "," + il.ElementAt(i));
                }

                il.Clear();
            }
            else
            {
                // Handle "bad" packets
            }
        } // while

        fs_bin.Flush();
        br.Close();                
        fs_bin.Close();
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

最佳答案

您的代码会静静地捕获 while 循环中发生的任何异常并将其吞下。

这是一种不好的做法,因为它掩盖了您遇到的问题。

最有可能的是,您在循环内调用的方法之一(例如 int.Parse())抛出异常,因为它在数据格式(或您的假设)中遇到了一些问题关于那种格式)。

一旦发生异常,读取数据的循环就会失去平衡,因为它不再位于记录边界

您应该做几件事来使这段代码更具弹性:

  1. 不要在运行循环中悄悄吞下异常。 对付他们。
  2. 不要在循环中逐字节或逐字段读取数据。由于您的记录是固定大小(77 个字节)- 将整个记录读入 byte[],然后从那里进行处理。这将有助于确保您始终在记录范围内阅读。

关于c# - 大文件处理 - 读取算法中断 - C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1608903/

相关文章:

C#:使用 FileSystemWatcher 监视文件的更改

.net - 如何在Vista下使用WIA 1进行开发?

c# - 每个 CPU 线程的实际限制是多少?

.net - 我可以在 XPath 表达式中使用 Regex 吗?

python - 是否可以将 mmap 文件视为字节对象?

ruby-on-rails - Nginx 代理重定向到另一个 URI

c# - 为什么我的类型 List<Point> 的变量被更改,即使我没有使用引用?

c# - 错误 : Could not download silverlight application. 检查 Web 服务器设置

python - 读取h5数据集python的一部分

c# - 函数Int32.TryParse(“23.0”)返回false-C#MVC4