Spark+Scala读取Avro文件报错:Block size无效或过大求助
Spark + Scala读取Avro文件夹报错:Block size invalid or too large for this implementation: -26
问题描述
我使用Spark和Scala,通过com.databricks:spark-avro_2.11读取Avro文件夹时,其余文件夹均读取成功,仅单个文件夹读取失败并抛出如下异常:
Caused by: org.apache.avro.AvroRuntimeException: java.io.IOException: Block size invalid or too large for this implementation: -26 at org.apache.avro.file.DataFileStream.hasNextBlock(DataFileStream.java:275) at org.apache.avro.file.DataFileStream.hasNext(DataFileStream.java:197)
手动检查过该文件夹内的文件,确认其外观正常未损坏,请问可能是什么问题?
可能的原因及解决办法
1. 文件存在隐藏的字节级损坏
虽然你手动检查没发现问题,但Avro文件的块大小字段是固定位置的元数据,一旦磁盘IO错误、网络传输丢包或写入中断,这个字段可能被篡改成为负数(比如你看到的-26),导致解析失败。
- 验证方法:用Avro官方工具
avro-tools检查文件:
如果工具也抛出类似错误,说明文件确实损坏,需要重新生成该文件夹的Avro文件。# 尝试读取文件schema avro-tools getschema /path/to/your/avro/file.avro # 尝试将文件转为JSON avro-tools tojson /path/to/your/avro/file.avro > output.json - 额外检查:对比该文件夹内文件的大小和同批次正常Avro文件,若有文件大小明显异常(过小/过大),大概率是损坏文件。
2. Avro版本兼容性问题
com.databricks:spark-avro_2.11依赖的Avro版本,可能和生成该文件夹Avro文件的Avro版本不兼容。不同版本的Avro在块大小的编码、元数据格式上可能存在差异,导致旧版本解析器无法识别新版本写入的文件。
- 排查步骤:
- 用
sbt dependencyTree或mvn dependency:tree查看spark-avro依赖的Avro版本。 - 确认生成该Avro文件使用的Avro版本。
- 用
- 解决方法:
- 如果版本差异较大,尝试升级/降级
spark-avro的版本,使其依赖的Avro版本和写入版本匹配。 - 或者用对应版本的Avro库重新写入该文件夹的文件。
- 如果版本差异较大,尝试升级/降级
3. 文件夹内混入非Avro文件
虽然你认为是Avro文件夹,但可能存在隐藏的临时文件、日志文件或其他格式文件,Spark读取时会尝试将这些文件当作Avro解析,导致报错。
- 解决方法:
- 手动检查文件夹内的所有文件,删除非
.avro后缀的文件。 - 或者在Spark读取时添加
pathGlobFilter参数,只读取.avro文件:spark.read.format("com.databricks.spark.avro") .option("pathGlobFilter", "*.avro") .load("/path/to/your/target/folder")
- 手动检查文件夹内的所有文件,删除非
4. 文件权限异常
IO异常也可能是Spark运行用户没有该文件夹内文件的读取权限,导致读取时无法正确获取文件内容,解析出错误的块大小。
- 解决方法:
- 检查文件权限:
ls -l /path/to/your/target/folder,确认Spark运行用户有读权限。 - 若权限不足,调整权限:
chmod +r /path/to/your/target/folder/*(根据实际情况调整权限范围)。
- 检查文件权限:
内容的提问来源于stack exchange,提问作者Ben Haim Shani
相关产品推荐
相关产品推荐

