如何在Scala中原生读取HDFS文本文件(不使用Spark)?
解决Scala中读取HDFS文本文件的问题
你的问题出在scala.io.Source.fromFile只能处理本地文件系统的路径,它并不支持HDFS的hdfs://协议——Java的FileInputStream(Source底层依赖它)会把hdfs:/...当成本地磁盘上的路径,自然找不到对应的文件。
下面给你两种在Apache Toree环境中读取HDFS文件的可行方案:
方案1:使用Hadoop FileSystem API
因为你已经在Hadoop环境中(能执行hdfs dfs命令),直接用Hadoop的FileSystem类来操作HDFS文件是最直接的方式:
import org.apache.hadoop.fs.{FileSystem, Path} import org.apache.hadoop.conf.Configuration // 初始化Hadoop配置和文件系统实例 val conf = new Configuration() val fs = FileSystem.get(conf) val hdfsPath = new Path("hdfs:/labs/laba01/ml-100k/u.data") // 打开文件流并读取内容 val inputStream = fs.open(hdfsPath) try { // 用Scala Source包装输入流,逐行读取打印 scala.io.Source.fromInputStream(inputStream).getLines().foreach(println) } finally { // 务必关闭流释放资源 inputStream.close() }
方案2:使用Spark API(更适合大数据场景)
既然你在Apache Toree环境中(这是Spark的Scala笔记本内核),直接用Spark的textFile API会更高效,尤其是处理大文件时:
// 用SparkContext读取HDFS文件,返回RDD[String] val hdfsFileRDD = sc.textFile("hdfs:/labs/laba01/ml-100k/u.data") // 逐行打印(注意:如果文件很大,不建议直接foreach,会把数据拉到Driver节点) hdfsFileRDD.foreach(println) // 如果只是测试小文件,可以收集到本地后打印 // hdfsFileRDD.collect().foreach(println)
为什么原代码会报错?
scala.io.Source.fromFile的设计目标是读取本地文件,它依赖Java的File类和FileInputStream,这些类只能识别本地文件系统的路径格式。当你传入hdfs:/...时,它会尝试在本地磁盘上查找这个路径,自然会抛出FileNotFoundException。
内容的提问来源于stack exchange,提问作者Sergey Zakharov
相关产品推荐
相关产品推荐

