使用固定缓冲区MemoryStream读取Blob CSV报不可扩展错误如何解决?
代码问题分析
- 缓冲区大小配置错误:你当前代码中声明的
new byte[4096]是4KB容量,并非你需要的4MB,4MB对应的字节数为4 * 1024 * 1024 = 4194304。 - MemoryStream扩容限制:使用固定大小的字节数组初始化MemoryStream时,流的容量被固定为数组大小,无法自动扩容。
DownloadTo方法默认会尝试将整个Blob的全部内容写入流,远超过你分配的缓冲区大小,因此抛出不可扩容的错误。 - 未实现范围下载:当前逻辑哪怕解决了扩容问题,也会先下载完整的600MB文件,完全无法达到减少下载耗时的需求。
可行实现方案
最优方案是直接向Blob存储服务请求前4MB范围的内容,无需下载整个文件,性能损耗最低,示例代码如下:
using Azure.Storage.Blobs.Models; using System.Diagnostics; using System.Text; private void GetCsv(BlobClient blob) { // 定义4MB对应的字节数 const int targetReadSize = 4 * 1024 * 1024; byte[] buffer = new byte[targetReadSize]; // 配置下载范围,仅拉取文件前4MB var downloadOptions = new BlobDownloadToOptions { Range = new HttpRange(0, targetReadSize) }; // 下载指定范围内容到缓冲区 var downloadResult = blob.DownloadTo(new MemoryStream(buffer), downloadOptions); // 转换为UTF8字符串,实际读取长度取返回的ContentLength避免文件不足4MB的情况 string text = Encoding.UTF8.GetString(buffer, 0, (int)downloadResult.Value.ContentLength); Debug.WriteLine(text); }
如果使用的Azure存储SDK版本较低,不支持BlobDownloadToOptions重载,可改用开流读取的方式实现:
using System.Diagnostics; using System.Text; private void GetCsv(BlobClient blob) { const int targetReadSize = 4 * 1024 * 1024; byte[] buffer = new byte[targetReadSize]; int totalReadBytes = 0; // 打开Blob可读流,默认只会按需拉取数据,不会下载整个文件 using var blobStream = blob.OpenRead(); // 循环读取直到读满4MB或到文件末尾 while (totalReadBytes < targetReadSize) { int currentRead = blobStream.Read(buffer, totalReadBytes, targetReadSize - totalReadBytes); if (currentRead == 0) break; totalReadBytes += currentRead; } string text = Encoding.UTF8.GetString(buffer, 0, totalReadBytes); Debug.WriteLine(text); }
补充注意:如果前4MB刚好截断UTF8多字节字符,会导致末尾出现乱码;如果需要保证CSV行完整性,可适当多读取几KB内容,匹配到最后一个换行符位置后再做字符串截断。
内容的提问来源于stack exchange,提问作者anthino12
相关产品推荐
相关产品推荐

