算术运算导致溢出错误 - 对于 c# 中的 byte[] 数组

发布于 2024-12-14 17:22:50 字数 4205 浏览 0 评论 0原文

我在 c# 中有这一行:

    byte[] bytes = new byte[streamReader.BaseStream.Length];

该长度返回大于 4 GB 的文件大小。

在该行我有以下错误:

Arithmetic operation resulted in an overflow. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.OverflowException: Arithmetic operation resulted in an overflow.

Source Error: 


Line 41:             System.IO.BinaryReader br = new System.IO.BinaryReader(streamReader.BaseStream);
Line 42: 
Line 43:             byte[] bytes = new byte[streamReader.BaseStream.Length];
Line 44: 
Line 45:             br.Read(bytes, 0, (int)streamReader.BaseStream.Length);

我该如何修复此错误?

编辑
我正在使用 .net 4
该代码是下载文件处理程序的一部分,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using WindowsServer.Classes;

namespace WindowsServer
{
    /// <summary>
    /// Summary description for HandlerForMyFE
    /// </summary>
    public class Handler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {

        private HttpContext _context;
        private HttpContext Context
        {
            get
            {
                return _context;
            }
            set
            {
                _context = value;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            Context = context;
            string filePath = context.Request.QueryString["Downloadpath"];
            filePath = context.Server.MapPath(filePath);

            if (filePath == null)
            {
                return;
            }

            System.IO.StreamReader streamReader = new System.IO.StreamReader(filePath);
            System.IO.BinaryReader br = new System.IO.BinaryReader(streamReader.BaseStream);

            byte[] bytes = new byte[streamReader.BaseStream.Length];

            br.Read(bytes, 0, (int)streamReader.BaseStream.Length);

            if (bytes == null)
            {
                return;
            }

            streamReader.Close();
            br.Close();
            string fileName = System.IO.Path.GetFileName(filePath);
            string MimeType = GetMimeType(fileName);
            string extension = System.IO.Path.GetExtension(filePath);
            char[] extension_ar = extension.ToCharArray();
            string extension_Without_dot = string.Empty;
            for (int i = 1; i < extension_ar.Length; i++)
            {
                extension_Without_dot += extension_ar[i];
            }

            string filesize = string.Empty;
            FileInfo f = new FileInfo(filePath);
            filesize = f.Length.ToString();

            //DownloadFile.DownloadFileMethod_2(Context, filePath, 5242880);
              WriteFile(bytes, fileName, filesize, MimeType + " " + extension_Without_dot, context.Response);
        }

       private void WriteFile(byte[] content, string fileName, string filesize, string contentType, HttpResponse response)
    {
        response.Buffer = true;
        response.Clear();

        response.ContentType = contentType;

        response.AddHeader("content-disposition", "attachment; filename=" + fileName);

        response.AddHeader("Content-Length", filesize);

        response.BinaryWrite(content);
        response.Flush();
        response.End();
    }

        private string GetMimeType(string fileName)
        {
            string mimeType = "application/unknown";
            string ext = System.IO.Path.GetExtension(fileName).ToLower();
            Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
            if (regKey != null && regKey.GetValue("Content Type") != null)
                mimeType = regKey.GetValue("Content Type").ToString();
            return mimeType;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

提前致谢

i have this line in c# :

    byte[] bytes = new byte[streamReader.BaseStream.Length];

That Length returns a file size bigger than 4 GB.

at that line i have the Error below :

Arithmetic operation resulted in an overflow. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.OverflowException: Arithmetic operation resulted in an overflow.

Source Error: 


Line 41:             System.IO.BinaryReader br = new System.IO.BinaryReader(streamReader.BaseStream);
Line 42: 
Line 43:             byte[] bytes = new byte[streamReader.BaseStream.Length];
Line 44: 
Line 45:             br.Read(bytes, 0, (int)streamReader.BaseStream.Length);

how can i fix this error ?

edit
i am using .net 4
that code was part of a handler for download files like below :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using WindowsServer.Classes;

namespace WindowsServer
{
    /// <summary>
    /// Summary description for HandlerForMyFE
    /// </summary>
    public class Handler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {

        private HttpContext _context;
        private HttpContext Context
        {
            get
            {
                return _context;
            }
            set
            {
                _context = value;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            Context = context;
            string filePath = context.Request.QueryString["Downloadpath"];
            filePath = context.Server.MapPath(filePath);

            if (filePath == null)
            {
                return;
            }

            System.IO.StreamReader streamReader = new System.IO.StreamReader(filePath);
            System.IO.BinaryReader br = new System.IO.BinaryReader(streamReader.BaseStream);

            byte[] bytes = new byte[streamReader.BaseStream.Length];

            br.Read(bytes, 0, (int)streamReader.BaseStream.Length);

            if (bytes == null)
            {
                return;
            }

            streamReader.Close();
            br.Close();
            string fileName = System.IO.Path.GetFileName(filePath);
            string MimeType = GetMimeType(fileName);
            string extension = System.IO.Path.GetExtension(filePath);
            char[] extension_ar = extension.ToCharArray();
            string extension_Without_dot = string.Empty;
            for (int i = 1; i < extension_ar.Length; i++)
            {
                extension_Without_dot += extension_ar[i];
            }

            string filesize = string.Empty;
            FileInfo f = new FileInfo(filePath);
            filesize = f.Length.ToString();

            //DownloadFile.DownloadFileMethod_2(Context, filePath, 5242880);
              WriteFile(bytes, fileName, filesize, MimeType + " " + extension_Without_dot, context.Response);
        }

       private void WriteFile(byte[] content, string fileName, string filesize, string contentType, HttpResponse response)
    {
        response.Buffer = true;
        response.Clear();

        response.ContentType = contentType;

        response.AddHeader("content-disposition", "attachment; filename=" + fileName);

        response.AddHeader("Content-Length", filesize);

        response.BinaryWrite(content);
        response.Flush();
        response.End();
    }

        private string GetMimeType(string fileName)
        {
            string mimeType = "application/unknown";
            string ext = System.IO.Path.GetExtension(fileName).ToLower();
            Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
            if (regKey != null && regKey.GetValue("Content Type") != null)
                mimeType = regKey.GetValue("Content Type").ToString();
            return mimeType;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ぇ气 2024-12-21 17:22:59

您将不得不使用较小的缓冲区并逐段读取流。我认为您无法创建大于 4 GB 的字节数组。

如果您使用的是 .NET 4,则可以使用新的 Stream.CopyTo(Stream) 实例方法将输入流复制到输出流。

You're going to have to use a smaller buffer and read the stream piecemeal. I don't think you're going to be able to create a byte array that's bigger than 4 GB.

If you're using .NET 4, you can use the new Stream.CopyTo(Stream) instance method to copy the input stream to an output stream.

少女净妖师 2024-12-21 17:22:57

在 .NET 中,您可以分配的最大对象约为 2GB。引自文档

与 32 位 Windows 操作系统一样,内存大小有 2GB 限制
运行 64 位托管时可以创建的对象的大小
64 位 Windows 操作系统上的应用程序。

还有一篇来自 CLR 的博客文章团队。

当然2GB是理论极限。实际限制较低。所以你必须分块阅读:

const int ChunkSize = 1024 * 1024 * 4; // process in chunks of 4MB:
using (var br = new BinaryReader(streamReader.BaseStream))
{
    var buffer = new byte[ChunkSize];
    int bytesRead;
    while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
    {
        // TODO: process the chunk which is the buffer array from 0 to bytesRead
    }
}

而且你的代码看起来有点奇怪。您有一个处理编码字符串的 StreamReader,但您正在使用字节数组和 BinaryReader。看起来有点奇怪。

In .NET the largest object you could allocate is around 2GB. Quote from the documentation:

As with 32-bit Windows operating systems, there is a 2GB limit on the
size of an object you can create while running a 64-bit managed
application on a 64-bit Windows operating system.

There is also a blog post from the CLR team.

Of course 2GB is the theoretical limit. The practical limit is lower. So you will have to read this in chunks:

const int ChunkSize = 1024 * 1024 * 4; // process in chunks of 4MB:
using (var br = new BinaryReader(streamReader.BaseStream))
{
    var buffer = new byte[ChunkSize];
    int bytesRead;
    while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
    {
        // TODO: process the chunk which is the buffer array from 0 to bytesRead
    }
}

Also your code seems a bit strange. You have a StreamReader which processes encoded strings and yet you are working with byte arrays and BinaryReaders. Seems kinda strange.

笑叹一世浮沉 2024-12-21 17:22:56

.NET 中的数组不能容纳超过 2^31 个元素 (System.Int32.MaxValue) 或 最大大小为 2 GB,大致相当于 2 GB 字节数组。

有关解决方法,请参阅 http://blogs.msdn.com /b/joshwil/archive/2005/08/10/450202.aspx

另一种选择是使用 MemoryMappedFileStreams - 这将允许访问以下文件任何大小...

要使下载代码工作,您可以读取一个块,发送它,读取下一个块等。或者使用 Stream 读取和写入 OutputStream 没有任何中间缓冲区...

另一种选择是使用 TransmitFile 其中可以处理文件> 4GB。

编辑 - 根据评论:

您可以将后面的代码替换

if (filePath == null)
{
return;
}

response.Clear();

response.ContentType = GetMimeType (System.IO.Path.GetFileName(filePath));

response.AddHeader("content-disposition", "attachment; filename=" + System.IO.Path.GetFileName(filePath));

response.TransmitFile (filePath);    

OR

long FileL = (new FileInfo(filePath)).Length;
byte[] bytes = new byte[1024*1024];

response.Clear();

response.ContentType = GetMimeType (System.IO.Path.GetFileName(filePath));

response.AddHeader("content-disposition", "attachment; filename=" + System.IO.Path.GetFileName(filePath));

response.AddHeader("Content-Length", FileL.ToString());

using (FileStream FS = File.OpenRead(filePath))
{
int bytesRead = 0;
while ((bytesRead = FS.Read (bytes, 0, bytes.Length)) > 0 )
{
response.OutputStream.Write(bytes, 0, bytesRead);
response.Flush();
};

response.Close();
}

No array in .NET can hold more than 2^31 element (System.Int32.MaxValue) or a max size of 2 GB which roughly would make for a 2 GB byte array.

For a workaround see http://blogs.msdn.com/b/joshwil/archive/2005/08/10/450202.aspx

Another option is to use MemoryMappedFile and Streams on those - this will alow to access a file of any size...

To make that download code work you could either read a chunk, send it, read the next chunk etc. OR use a Stream for reading and write to the OutputStream without any intermediate buffer...

Another option is to use TransmitFile which can handle files > 4 GB.

EDIT - as per comment:

You could just replace the code after

if (filePath == null)
{
return;
}

with

response.Clear();

response.ContentType = GetMimeType (System.IO.Path.GetFileName(filePath));

response.AddHeader("content-disposition", "attachment; filename=" + System.IO.Path.GetFileName(filePath));

response.TransmitFile (filePath);    

OR with

long FileL = (new FileInfo(filePath)).Length;
byte[] bytes = new byte[1024*1024];

response.Clear();

response.ContentType = GetMimeType (System.IO.Path.GetFileName(filePath));

response.AddHeader("content-disposition", "attachment; filename=" + System.IO.Path.GetFileName(filePath));

response.AddHeader("Content-Length", FileL.ToString());

using (FileStream FS = File.OpenRead(filePath))
{
int bytesRead = 0;
while ((bytesRead = FS.Read (bytes, 0, bytes.Length)) > 0 )
{
response.OutputStream.Write(bytes, 0, bytesRead);
response.Flush();
};

response.Close();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文