在知道正确的数组长度之前,如何在 C# 中将字节数组初始化为 OUT 参数

发布于 2024-12-02 07:39:03 字数 2716 浏览 0 评论 0原文

我在使用用于将文件下载到调用 HTTPHandler.ashx 文件的 Web 方法时遇到问题。处理程序按如下方式调用 webmethod:

byte[] docContent;
string fileType;
string fileName;
string msgInfo = brokerService.DownloadFile(trimURL, recNumber, out docContent, out fileType, out fileName);

在被调用的 webmethod 中,我必须在使用字节数组之前对其进行初始化,否则我会在所有返回语句上收到编译器错误:

The out parameter 'docContents' must be assigned to before control leaves the current method

我尝试将其设置为空数组,但这会导致 Buffer.BlockCopy 方法失败:

Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
mscorlib
  at System.Buffer.BlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count)

我知道我需要初始化它,但在访问数据库之前我不知道所需数组的长度。通过调试,我已经验证了除 Buffer.BlockCopy 之外的所有代码都有效:

    public string DownloadFile(string trimURL
        , string TrimRecordNumber
        , out byte[] docContents
        , out string returnFiletype
        , out string returnFilename)
    {
        docContents = new byte[0];
        returnFiletype = null; returnFilename = null;
        try
        {
            ConnectToTrim(trimURL);
            if (!db.IsValid)
                return "CRITICAL: Database Is NOT Valid";
            Record myRec = db.GetRecord(TrimRecordNumber);
            if (myRec == null)
                return "CRITICAL: Record not found.";
            uint bufferSize = 10000;
            int documentLength = myRec.DocumentSize;
            byte[] result = new byte[documentLength];
            byte[] buffer = new byte[bufferSize];
            uint bytesRead;
            uint totalBytesRead = 0;
            TRIMSDK.IStream docStream = myRec.GetDocumentStream(string.Empty, false, string.Empty);
            while (totalBytesRead < documentLength)
            {
                docStream.RemoteRead(out buffer[0], 10000, out bytesRead);
                for (int i = 0; i < bytesRead; i++)
                {
                    result[totalBytesRead] = buffer[i];
                    totalBytesRead += 1;
                }
            }
            returnFiletype = myRec.Extension;
            returnFilename = myRec.SuggestedFileName;
            Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
            return string.Format("OK-Document for recordnumber({0}): {1}.{2} - size: {3} bytes",
                TrimRecordNumber, returnFilename, returnFiletype, Convert.ToString(documentLength)); 
        }
        catch (Exception ex)
        {
            return LogException(ex, "CRITICAL: Exception in DownloadFile method has been logged:", trimURL, 100);
        } 
    } 

I'm having trouble with a webmethod used to download a file to a calling HTTPHandler.ashx file. The handler calls the webmethod as follows:

byte[] docContent;
string fileType;
string fileName;
string msgInfo = brokerService.DownloadFile(trimURL, recNumber, out docContent, out fileType, out fileName);

In the called webmethod, I have to initialize the byte array before using it or I get compiler errors on all the return statements:

The out parameter 'docContents' must be assigned to before control leaves the current method

I tried setting it to an empty array but that causes the Buffer.BlockCopy method to fail:

Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
mscorlib
  at System.Buffer.BlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count)

I know I need to initialize it but I don't know the length of the array needed until I access the database. Through debugging I've verified all the code works except for the Buffer.BlockCopy:

    public string DownloadFile(string trimURL
        , string TrimRecordNumber
        , out byte[] docContents
        , out string returnFiletype
        , out string returnFilename)
    {
        docContents = new byte[0];
        returnFiletype = null; returnFilename = null;
        try
        {
            ConnectToTrim(trimURL);
            if (!db.IsValid)
                return "CRITICAL: Database Is NOT Valid";
            Record myRec = db.GetRecord(TrimRecordNumber);
            if (myRec == null)
                return "CRITICAL: Record not found.";
            uint bufferSize = 10000;
            int documentLength = myRec.DocumentSize;
            byte[] result = new byte[documentLength];
            byte[] buffer = new byte[bufferSize];
            uint bytesRead;
            uint totalBytesRead = 0;
            TRIMSDK.IStream docStream = myRec.GetDocumentStream(string.Empty, false, string.Empty);
            while (totalBytesRead < documentLength)
            {
                docStream.RemoteRead(out buffer[0], 10000, out bytesRead);
                for (int i = 0; i < bytesRead; i++)
                {
                    result[totalBytesRead] = buffer[i];
                    totalBytesRead += 1;
                }
            }
            returnFiletype = myRec.Extension;
            returnFilename = myRec.SuggestedFileName;
            Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
            return string.Format("OK-Document for recordnumber({0}): {1}.{2} - size: {3} bytes",
                TrimRecordNumber, returnFilename, returnFiletype, Convert.ToString(documentLength)); 
        }
        catch (Exception ex)
        {
            return LogException(ex, "CRITICAL: Exception in DownloadFile method has been logged:", trimURL, 100);
        } 
    } 

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

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

发布评论

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

评论(1

独守阴晴ぅ圆缺 2024-12-09 07:39:03

您可以首先将其初始化为 null。在调用 Buffer.BlockCopy 之前,将其分配并初始化为正确的长度。

这看起来像:

public string DownloadFile(string trimURL
    , string TrimRecordNumber
    , out byte[] docContents
    , out string returnFiletype
    , out string returnFilename)
{
    docContents = null;

    //...

        returnFiletype = myRec.Extension;
        returnFilename = myRec.SuggestedFileName;
        docContents = new byte[result.Length]; // Allocate appropriately here...
        Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
        return ...

或者,您可以直接分配结果并将其复制到 docContents 中 - 完全消除对 result 的需要。但是,如果您想保留整体流量控制,您仍然需要在开始时初始化为 null

You can start by initializing it to null. Just prior to calling Buffer.BlockCopy, allocate and initialize it to the proper length.

This would look like:

public string DownloadFile(string trimURL
    , string TrimRecordNumber
    , out byte[] docContents
    , out string returnFiletype
    , out string returnFilename)
{
    docContents = null;

    //...

        returnFiletype = myRec.Extension;
        returnFilename = myRec.SuggestedFileName;
        docContents = new byte[result.Length]; // Allocate appropriately here...
        Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
        return ...

Alternatively, you can just directly allocate and copy the results into docContents - eliminating the need for result entirely. You will still need to initailize to null at the start if you want to leave your overall flow control alone, however.

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