有没有一种最有效的方法来读取/写入C#中的10GB二进制文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有一种最有效的方法来读取/写入C#中的10GB二进制文件?相关的知识,希望对你有一定的参考价值。

我们有一个项目,我们需要迁移最多10GB的二进制文件。步骤是1)按消息大小读取文件2)进行一些处理3)将原始消息或处理过的消息写回新的二进制文件。

对于10GB文件,处理后它变为14GB。目前需要近2个小时。

我想知道我是否可以做一些IO技巧来缩短时间。

using (FileStream fsInput =new FileStream(inputfilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (FileStream fsOutput = File.Create(outputfilename))
            {
                long total = fsInput.Length;
                long progress = 0;

                unsafe
                {
                    int hdrSize = sizeof(FullMessageHeader);
                    byte[] headerBuffer = new byte[hdrSize];

                    while (fsInput.Position < fsInput.Length)
                    {                         
                        progress += fsInput.Read(headerBuffer, 0, hdrSize);
                        int msgSize = 0;
                        fixed (byte* hdr = headerBuffer)
                        {
                            msgSize = *(int*)(hdr + MessageHeaderOffsets.Size);
                        }

                        byte[] msg = new byte[msgSize];
                        Buffer.BlockCopy(headerBuffer, 0, msg, 0, headerBuffer.Length);
                        fsInput.Position -= hdrSize;
                        progress += fsInput.Read(msg, 0, msgSize);

                        fixed (byte* ptr = msg)
                        {
                            byte[] ba = ProcessMessage(ptr);
                            if (ba.Length == 0)
                            {
                                fsOutput.Write(msg, 0, msg.Length);
                            }
                            else
                            {
                                fsOutput.Write(ba, 0, ba.Length);
                            }
                        }

                    }
                }
            }
        }
答案

最后,正如Georg所建议的,以及上面代码的一些清理,我能够将时间从2小时减少到10分钟,这不是最佳但可接受的。

        Dictionary<int, byte[]> byteDictionary = new Dictionary<int, byte[]>();
        using (FileStream fsInput =new FileStream(inputfilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (FileStream fsOutput = File.Create(outputfilename))
            {
                long total = fsInput.Length;
                long progress = 0;

                unsafe
                {
                    int hdrSize = sizeof(FullMessageHeader);
                    byte[] headerBuffer = new byte[hdrSize];

                    while (fsInput.Position < fsInput.Length)
                    {                         
                        progress += fsInput.Read(headerBuffer, 0, hdrSize);
                        int msgSize = 0;
                        fixed (byte* hdr = headerBuffer)
                        {
                            msgSize = *(int*)(hdr + MessageHeaderOffsets.Size);
                        }

                        byte[] msg = byteDictionary.ContainsKey(msgSize)
                            ? byteDictionary[msgSize]
                            : new byte[msgSize];
                        if (!byteDictionary.ContainsKey(msgSize))
                        {
                            byteDictionary[msgSize] = msg;
                        }
                        //byte[] msg = new byte[msgSize];
                        //Buffer.BlockCopy(headerBuffer, 0, msg, 0, headerBuffer.Length);
                        fsInput.Position -= hdrSize;
                        progress += fsInput.Read(msg, 0, msgSize);

                        fixed (byte* ptr = msg)
                        {
                            //fsOutput.Write(msg,0,msg.Length);
                            byte[] ba = ProcessMessage(ptr);
                            if (ba.Length == 0)
                            {
                                fsOutput.Write(msg, 0, msg.Length);
                            }
                            else
                            {
                                fsOutput.Write(ba, 0, ba.Length);
                            }
                        }

                    }
                }
            }
        }

以上是关于有没有一种最有效的方法来读取/写入C#中的10GB二进制文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何确保在完成写入文件之前不读取文件

在Java中读取3GB的非常大的csv文件的内存有效方法是什么?

如何并行处理数据但将结果写入 Spark 中的单个文件

C++ 和读取大型文本文件

Python Pandas:标记数据时出错。 C 错误:读取 1GB CSV 文件时字符串中的 EOF 开始

在使用 python 写入时从日志文件中读取