在日常spark任务开发中,有时因为数据过程中的需求,需要加载一部分的文件,如csv、properties等。如果从spark提供的API中可以直接通过添加文件路径达到配置文件加载的目的,如下加载csv文件示例:
val spark= SparkSession.builder().appName("demo").master("local[2]").getOrCreate()
spark
.read
.option("header", "true")
.option("delimiter",",")
.load("csv/demo.csv")
.collect()
但报fileNotFound错误,原因为spark原生提供的load接口中只支持分布式存储系统或本地目录的方式读取,使用path的方式读取resource的方式是行不通的,源码如下:
/**
* Loads input in as a `DataFrame`, for data sources that require a path (e.g. data backed by
* a local or distributed file system).
*
* @since 1.4.0
*/
def load(path: String): DataFrame = {
option("path", path).load(Seq.empty: _*) // force invocation of `load(...varargs...)`
}
根据上述原码中的注释描述,确实是只能传一个本地文件路径或分布式文件系统,因此使用spark原生API可能行不通了。
这时可以考虑使用scala自带的Resource类,读取文件后再通过spark广播出去,就可以达到预期的使用效果,如下:
//获取sparkSession对象
val spark= SparkSession.builder().appName("demo").master("local[2]").getOrCreate()
val url = this.getClass.getClassLoader.getResource("csv/demo.csv")
val csvArr = Source.fromURL(url).getLines()
//广播
spark.sparkContext.broadcast(csvArr)
这样就可以很方便地使用resources中的配置文件。