4

我正在尝试将以下读取 HttpContent 的完整字符串响应的代码转换为字符串,以仅读取特定的最大字符数。现有代码:

private static async Task<string> GetContentStringAsync(HttpContent content)
{
    string responseContent = await content.ReadAsStringAsync().ConfigureAwait(false);
    return responseContent;
}

我现在拥有的代码:

private static async Task<string> GetContentStringAsync(HttpContent content, int ResponseContentMaxLength)
{
    string responseContent;
    Stream responseStream = await content.ReadAsStreamAsync().ConfigureAwait(false);
    using (StreamReader streamReader = new StreamReader(responseStream))
    {
        // responseContent = Data from streamReader until ResponseContentMaxLength
    }

    return responseContent;
}

我是 StreamReader 和 HttpContent 操作的新手。有没有办法做到这一点?

4

2 回答 2

3

有多种方法可以做到这一点。但是,恕我直言,最简单的方法之一是创建一个MemoryStream您已经读取了所需字节数的确切字节,然后StreamReader从该流而不是原始流中读取对象。

例如:

private static async Task<string> GetContentStringAsync(HttpContent content, int ResponseContentMaxLength)
{
    string responseContent;
    Stream responseStream = await content.ReadAsStreamAsync().ConfigureAwait(false);

    int totalBytesRead = 0;
    byte[] buffer = new byte[ResponseContentMaxLength];

    while (totalBytesRead < buffer.Length)
    {
        int bytesRead = await responseStream
            .ReadAsync(buffer, totalBytesRead, buffer.Length - totalBytesRead);

        if (bytesRead == 0)
        {
            // end-of-stream...can't read any more
            break;
        }

        totalBytesRead += bytesRead;
    }

    MemoryStream tempStream = new MemoryStream(buffer, 0, totalBytesRead);

    using (StreamReader streamReader = new StreamReader(tempStream))
    {
        // responseContent = Data from streamReader until ResponseContentMaxLength
    }

    return responseContent;
}

上面当然假设它ResponseContentMaxLength的值足够小,分配一个byte[]足够大的值来临时存储那么多字节是合理的。由于返回的内容将具有相当的规模,这似乎是一个合理的假设。

但是,如果您不想维护那个额外的缓冲区,另一种方法是编写一个Stream从底层流对象读取的类,该类仅从您指定的字节数中读取,然后传递该实例的实例(使用该ResponseContentMaxLength值初始化)到StreamReader对象。与上述相比,这是相当多的额外工作。(不过,我想既然这是一个非常有用的对象,可能已经有一个公开可用的实现......我知道我自己至少已经写过几次类似的东西,我只是碰巧没有方便的代码此时此刻)。

于 2015-06-25T05:07:23.107 回答
1

@Peter Duniho:感谢您的回复。我最终使用了稍微简单的代码:

using(StreamReader streamReader = new StreamReader(responseStream))
{
    char[] responseContentChars = new char[ResponseContentMaxLength];
                    streamReader.Read(responseContentChars, 0, ResponseContentMaxLength);
    string responseContentString = new string(responseContentChars);
    responseContent = responseContentString.Replace("\0", string.Empty);
}

但是,如果在此处阅读后,其他人正在使用流,则上面的代码可能会导致错误。选择的答案将照顾其他阅读原始流的人,因为正在从具有长度 ResponseContentMaxLength 的内容的旧流构造一个新流。

于 2015-06-27T00:16:47.613 回答