使用Parquet.Net读取Parquet文件时遇‘Destination is too short’错误求助
C#读取Parquet转JSON时出现"Destination is too short"错误的排查与解决
问题描述
我正在开发一个C# API项目,需实现读取Parquet文件并转换为JSON格式的功能。平时常用Python,读取Parquet仅需一行代码,但作为C#新手遇到了问题:程序先下载S3上的Parquet文件到临时文件,后续在DataColumn column = await groupReader.ReadColumnAsync(dataFields[c]);行报错。
用Python的pd.read_parquet(filename)读取同文件显示正常,文件含90000行、30列,所有列均为float64类型。
错误信息
System.ArgumentException HResult=0x80070057 Message=Destination is too short. (Parameter 'destination') Source=System.Private.CoreLib StackTrace: at System.ThrowHelper.ThrowArgumentException_DestinationTooShort() at Parquet.Encodings.ParquetPlainEncoder.Decode(Span`1 source, Span`1 data) at Parquet.Encodings.ParquetPlainEncoder.Decode(Array data, Int32 offset, Int32 count, SchemaElement tse, Span`1 source, Int32& elementsRead) at Parquet.File.DataColumnReader.ReadColumn(Span`1 src, Encoding encoding, Int64 totalValuesInChunk, Int32 totalValuesInPage, PackedColumn pc) at Parquet.File.DataColumnReader.<ReadDataPageV1Async>d__13.MoveNext() at Parquet.File.DataColumnReader.<ReadAsync>d__8.MoveNext() at ConvertController.<ConvertToJSON>d__2.MoveNext() in C:\Users\myuser\Desktop\repos\frontend\project\Controllers\WebAPI_ParquetController.cs:line 78 This exception was originally thrown at this call stack: [External Code] ConvertController.ConvertToJSON(string) in WebAPI_ParquetController.cs
相关代码片段
// Open the parquet file stream using (Stream fileStream = System.IO.File.OpenRead(tempFilePath)) { // Open parquet file reader using (ParquetReader parquetReader = await ParquetReader.CreateAsync(fileStream)) { // Get file schema DataField[] dataFields = parquetReader.Schema.GetDataFields(); var result = new List<Dictionary<string, object>>(); // Enumerate through row groups in this file for (int i = 0; i < parquetReader.RowGroupCount; i++) { // Create row group reader using (ParquetRowGroupReader groupReader = parquetReader.OpenRowGroupReader(i)) { var rowGroupResult = new Dictionary<string, object>(); // Read all columns inside each row group for (int c = 0; c < dataFields.Length; c++) { DataColumn column = await groupReader.ReadColumnAsync(dataFields[c]); ///ERROR // Cast column data to the appropriate type var columnData = column.Data; var decodedData = new object[columnData.Length]; // Decode the column data for (int idx = 0; idx < columnData.Length; idx++) { decodedData[idx] = column.Data.GetValue(idx); } string columnName = dataFields[c].Name; rowGroupResult[columnName] = decodedData; } result.Add(rowGroupResult); } } // Convert the result to JSON var jsonResult = JsonConvert.SerializeObject(result); return Ok(jsonResult); } }
错误原因分析
这个错误是Parquet解码过程中,分配的目标缓冲区长度不足以容纳解码后的数据导致的,常见触发场景:
- 库版本问题:旧版本Parquet.Net库在处理特定编码或大数量级列时,存在缓冲区计算逻辑缺陷
- Schema解析偏差:虽然Python识别为float64,但C#端自动解析的Schema可能和文件实际元数据存在细微差异(比如空值标识、精度定义)
- 行组数据量过大:单个行组的数据量超出了库默认的缓冲区处理上限
解决方法
- 升级Parquet.Net库:该问题在较新版本中已被修复,通过NuGet将
Parquet.Net包更新到最新稳定版 - 显式指定数据类型:已知所有列都是float64,手动指定读取类型避免Schema解析偏差,修改代码如下:
// 替换原Schema获取代码 var dataFields = parquetReader.Schema.GetDataFields() .Select(df => new DataField<double>(df.Name)) .ToArray(); - 验证临时文件完整性:确认从S3下载的临时文件未损坏,可通过对比文件哈希值验证
- 调整读取逻辑:若行组数据量过大,可尝试分批次读取列数据,或查看库文档调整缓冲区配置参数
内容的提问来源于stack exchange,提问作者pyeR_biz
相关产品推荐
相关产品推荐

