Spark通过--files加载本地CSV文件失败,如何正确读取?
解决Spark通过--files上传文件后读取失败的问题
核心原因
使用--files上传的文件会被Spark分发到每个Executor节点的本地缓存目录,但直接用file://前缀读取时,Spark SQL会尝试在所有Executor节点的本地路径查找该文件,若路径不一致或文件未正确分发,就会触发"路径不存在"的错误。
解决方案
方案1:直接使用文件名读取(推荐)
通过--files上传的文件,Spark会自动识别资源路径,无需添加file://前缀,直接用文件名即可读取:
spark.read.format(format) // 根据CSV是否包含表头添加对应配置 .option("header", "true") .load(file) // file 传入 "countries.csv" 或 "gdpr.csv" .createTempView(name)
方案2:在Driver端读取后广播(适合小型文件)
如果需要确认文件存在性,可先在Driver端读取文件,再将DataFrame广播给所有Executor(小型CSV文件适合此方式,避免重复读取):
import org.apache.spark.SparkFiles import java.io.File val localPath = SparkFiles.get(file) val localFile = new File(localPath) // 先检查Driver端文件是否存在 if (localFile.exists()) { // 读取文件为DataFrame val df = spark.read.format(format) .option("header", "true") .load(localPath) // 广播DataFrame供Executor使用 val broadcastDf = spark.sparkContext.broadcast(df) // 将广播后的DataFrame转为临时视图 broadcastDf.value.createTempView(name) } else { throw new RuntimeException(s"File $file not found on driver node") }
方案3:直接从HDFS staging路径读取(仅调试用)
从日志中可获取文件上传到HDFS的具体路径(如hdfs://hdfs/user/user1/.sparkStaging/application_1718353091108_5460/countries.csv),可直接通过该路径读取:
spark.read.format(format) .option("header", "true") .load("hdfs://hdfs/user/user1/.sparkStaging/application_1718353091108_5460/countries.csv") .createTempView(name)
注意:此方式依赖具体的application路径,不适合通用生产场景,仅用于临时调试。
内容的提问来源于stack exchange,提问作者Vladimir Shadrin
相关产品推荐
相关产品推荐

