尝试读取大文件时出现System.OutOfMemory异常

时间:2014-06-28 07:48:54

标签: c#

public static byte[] ReadMemoryMappedFile(string fileName)
    {
        long length = new FileInfo(fileName).Length;
        using (var stream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite))
        {
            using (var mmf = MemoryMappedFile.CreateFromFile(stream, null, length, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false))
            {
                using (var viewStream = mmf.CreateViewStream(0, length, MemoryMappedFileAccess.Read))
                {
                    using (BinaryReader binReader = new BinaryReader(viewStream))
                    {
                        var result = binReader.ReadBytes((int)length);
                        return result;
                    }
                }
            }
        }
    }

OpenFileDialog openfile = new OpenFileDialog();
        openfile.Filter = "All Files (*.*)|*.*";
        openfile.ShowDialog();
        byte[] buff = ReadMemoryMappedFile(openfile.FileName);
        texteditor.Text = BitConverter.ToString(buff).Replace("-"," "); <----A first chance exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll

尝试读取大文件时出现System.OutOfMemory异常。 我已经在整个网络上阅读了4周了很多...并且尝试了很多!!!但是,我似乎无法找到解决问题的好方法。 请帮帮我..

更新

public byte[] FileToByteArray(string fileName)
    {
        byte[] buff = null;
        FileStream fs = new FileStream(fileName,
                                       FileMode.Open,
                                       FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);
        long numBytes = new FileInfo(fileName).Length;
        buff = br.ReadBytes((int)numBytes);
        //return buff;
        return File.ReadAllBytes(fileName);
    }

OR

public static byte[] FileToByteArray(FileStream stream, int initialLength)
    {
        // If we've been passed an unhelpful initial length, just
        // use 32K.
        if (initialLength < 1)
        {
            initialLength = 32768;
        }
        BinaryReader br = new BinaryReader(stream);
        byte[] buffer = new byte[initialLength];
        int read = 0;

        int chunk;
        while ((chunk = br.Read(buffer, read, buffer.Length - read)) > 0)
        {
            read += chunk;

            // If we've reached the end of our buffer, check to see if there's
            // any more information
            if (read == buffer.Length)
            {
                int nextByte = br.ReadByte();

                // End of stream? If so, we're done
                if (nextByte == -1)
                {
                    return buffer;
                }

                // Nope. Resize the buffer, put in the byte we've just
                // read, and continue
                byte[] newBuffer = new byte[buffer.Length * 2];
                Array.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[read] = (byte)nextByte;
                buffer = newBuffer;
                read++;
            }
        }
        // Buffer is now too big. Shrink it.
        byte[] ret = new byte[read];
        Array.Copy(buffer, ret, read);
        return ret;
    }

尝试读取大文件时,我仍然收到System.OutOfMemory异常。

3 个答案:

答案 0 :(得分:1)

您需要以块的形式读取文件,跟踪文件的位置,在屏幕上分页内容并使用搜索和位置在文件流中上下移动。

答案 1 :(得分:1)

如果你的文件是4GB,那么BitConverter会把每个字节变成XX字符串,字符串中的每个字符串都是2字节*每字节3个字符* 4 294 967 295字节= 25 769 803 770.你需要+ 25Gb的免费内存以适应整个字符串,另外你已经将你的文件作为字节数组存储在内存中。

此外,.Net程序中没有单个对象可能超过2GB。字符串长度的理论限制为1,073,741,823个字符,但您还需要64位进程。

在您的情况下解决方案 - 打开FileStream。首先读取16384个字节(或者可以在屏幕上显示多少),转换为十六进制并显示,并记住文件偏移量。当用户想要导航到下一页或上一页时 - 在磁盘上的文件中寻找该位置,再次阅读和显示等。

答案 2 :(得分:0)

您无法通过任何方法首先在内存中显示所有内容的4Gb文件。

方法是虚拟化数据,在用户滚动时仅读取可见行。如果你需要做一个只读的文本查看器,那么你可以使用WPF ItemsControl与虚拟化堆栈面板并绑定到自定义IList集合,它将从文件计算文件的偏移量中为行索引延迟提取行。