【问题标题】:stream.read gives corrupted bytesstream.read 给出损坏的字节
【发布时间】:2013-06-21 01:46:46
【问题描述】:
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();

int sizeToRead = (int)response.ContentLength;
int sizeRead = 0;
int buffer = 1;
byte[] bytes = new byte[sizeToRead];
while (sizeToRead > 0)
{
    int rs = sizeToRead > buffer ? buffer : sizeToRead;
    stream.Read(bytes, sizeRead, rs);
    sizeToRead -= rs;
    sizeRead += rs;
}

stream.Close();
System.IO.File.WriteAllBytes("c:\\tmp\\b.mp3", bytes);

我有上面的代码。它的目的是从某个地方下载一个 mp3 文件并将其保存到 c:\tmp\filename。而且效果很好。

但是,如果我将缓冲区大小更改为不是 1 的值,例如 512。下载的 mp3 文件会很粗糙。我将我的程序下载的文件与通过浏览器下载的文件进行了比较,我发现我的程序下载的mp3文件的某些字节设置为0(它们的文件大小相同)。

另外,我在使用上述代码下载mp3文件时,还使用了fiddler来监控流量。我比较了从我的程序和浏览器下载的 mp3,所有的字节都是一样的。

所以,我想问题出在流阅读器或阅读过程中。有谁知道为什么会这样?以及如何在不将缓冲区大小设置为 1 的情况下解决它?

【问题讨论】:

  • 既然已经创建了new byte[sizeToRead],为什么还要使用循环,一次读取 1 (!) 个字节?
  • 为什么不直接使用stream.ReadToEnd(),因为你在两次读取之间并没有真正做任何事情?
  • 仅供参考,您的 WebResponse 和 Stream 需要使用块:using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()){using (Stream stream = response.GetResponseStream()){int sizeToRead = (int)response.ContentLength; // ...}}
  • @HenkHolterman 当我试图将缓冲区设置为 512 或更大时,我懒得重写它
  • @D Stanley 我不认为 Stream 有这种方法

标签: c# stream


【解决方案1】:

Stream.Read 返回一个int,告诉您实际读取了多少字节。如果您正在处理一个流,您最好实际接收该信息并对其采取行动。

换句话说,仅仅因为您要求读取 2 个字节,并不意味着您的缓冲区包含 2 个有效字节。

如果您需要检索特定数量的字节(您知道),那么您应该循环直到获得该数量的字节。

【讨论】:

  • 好点,什么情况下read_byte!=buffer_size除了读取最后一个block?
  • @Alvin - 如此多的情况以至于无法列举它们。枚举它 匹配的情况更容易 - 在这种情况下,操作系统必须有足够的可用数据来填充您调用 Read 的缓冲区。反过来,这取决于流的来源(网络<<< 比内存慢)。 Stream.Read 上唯一的保证合约是(如果它获得任何数据)它获得了至少 1 个字节。没有其他保证。
  • 非常有趣!帮了我很多这是我为了解决我遇到的同样问题所做的: int readBytes = 0; while ((readBytes = stream.Read(buffer, 0, buffer.Length)) > 0) { writer.Write(buffer, 0, readBytes); writer.Flush(); bytesDownloaded += buffer.Length; this.DownloadProgress = (int)((bytesDownloaded * 100) / totalFileBytes); }
【解决方案2】:

stream.Read() 是否返回与 rs 相同的值?试试这个:

byte[] bytes = new byte[sizeToRead];
while (sizeToRead > 0) {
    int rs = sizeToRead > buffer ? buffer : sizeToRead;
    rs = stream.Read(bytes, sizeRead, rs);
    sizeToRead -= rs;
    sizeRead += rs;
}

【讨论】:

    猜你喜欢
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 2021-02-06
    • 1970-01-01
    • 2017-03-20
    • 2014-09-05
    • 1970-01-01
    相关资源
    最近更新 更多