spark-shell读取本地文件

文章展示了如何使用SparkShell读取本地的TXT和CSV文件,包括在文件路径前添加file://前缀来正确读取本地文件。还提到了一个常见错误——Inputpathdoesnotexist,该错误通常由于文件路径不正确或文件未在指定位置导致,解决方案是确保文件已存在于指定路径或通过数据传输将文件移动到正确的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.读取本地txt文件

读取本地文件时,需要在文件路径前加上  file://  ,如下代码

[WBQ@westgisB068 ~]$ spark-shell
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
23/04/17 11:09:56 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Spark context Web UI available at http://westgisB068:4040
Spark context available as 'sc' (master = local[*], app id = local-1681700998461).
Spark session available as 'spark'.
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 3.3.2
      /_/
         
Using Scala version 2.12.15 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_271)
Type in expressions to have them evaluated.
Type :help for more information.

scala> import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.SparkSession

scala> val df = sc.textFile("/home/WBQ/1.txt")
df: org.apache.spark.rdd.RDD[String] = /home/WBQ/1.txt MapPartitionsRDD[1] at textFile at <console>:24

scala> df.first()
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://westgisB064:8020/home/WBQ/1.txt
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:304)
  at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:244)
  at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:332)
  at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:208)
  at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:292)
  at scala.Option.getOrElse(Option.scala:189)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:288)
  at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
  at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:292)
  at scala.Option.getOrElse(Option.scala:189)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:288)
  at org.apache.spark.rdd.RDD.$anonfun$take$1(RDD.scala:1449)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
  at org.apache.spark.rdd.RDD.withScope(RDD.scala:406)
  at org.apache.spark.rdd.RDD.take(RDD.scala:1443)
  at org.apache.spark.rdd.RDD.$anonfun$first$1(RDD.scala:1484)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
  at org.apache.spark.rdd.RDD.withScope(RDD.scala:406)
  at org.apache.spark.rdd.RDD.first(RDD.scala:1484)
  ... 47 elided
Caused by: java.io.IOException: Input path does not exist: hdfs://westgisB064:8020/home/WBQ/1.txt
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:278)
  ... 67 more

scala> val df = sc.textFile("file:///home/WBQ/1.txt")
df: org.apache.spark.rdd.RDD[String] = file:///home/WBQ/1.txt MapPartitionsRDD[3] at textFile at <console>:24

scala> df.first()
res2: String = 1 2 3 gfv 4 ff1 2 3 gfv 4 ff                                     

scala> 

2.读取本地csv文件

2.1数据传输

将数据传输到当前节点

[WBQ@westgisB064 soft]$ scp -r traffic/ WBQ@10.103.105.68:/home/WBQ/soft/

2.2spark-shell打开终端进行操作

[WBQ@westgisB068 ~]$ spark-shell
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
23/04/17 11:23:45 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Spark context Web UI available at http://westgisB068:4040
Spark context available as 'sc' (master = local[*], app id = local-1681701827307).
Spark session available as 'spark'.
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 3.3.2
      /_/
         
Using Scala version 2.12.15 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_271)
Type in expressions to have them evaluated.
Type :help for more information.

scala> import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.SparkSession

scala> val df = spark.read.format("csv").option("header",value="true").option("encoding","utf-8").load("file:///home/WBQ/soft/data/traffic/part-*")
df: org.apache.spark.sql.DataFrame = [卡号: string, 交易时间: string ... 2 more fields]

scala> df.show(5)
+-------+--------------------+--------+--------+
|   卡号|            交易时间|线路站点|交易类型|
+-------+--------------------+--------+--------+
|3697647|2018-10-01T18:47:...|    大新|地铁出站|
|3697647|2018-10-01T18:35:...|宝安中心|地铁入站|
|3697647|2018-10-01T13:49:...|    大新|地铁入站|
|3697647|2018-10-01T14:03:...|宝安中心|地铁出站|
|5344820|2018-10-17T09:34:...|    罗湖|地铁入站|
+-------+--------------------+--------+--------+
only showing top 5 rows


scala> 

3.读取本地文件失败原因

错误提示:输入路径不存在

检查:确实不存在

解决:将数据从其他节点传输到本地节点

scala> df.first()
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://westgisB064:8020/home/WBQ/1.txt
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:304)
  at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:244)
  at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:332)
  at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:208)
  at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:292)
  at scala.Option.getOrElse(Option.scala:189)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:288)
  at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:49)
  at org.apache.spark.rdd.RDD.$anonfun$partitions$2(RDD.scala:292)
  at scala.Option.getOrElse(Option.scala:189)
  at org.apache.spark.rdd.RDD.partitions(RDD.scala:288)
  at org.apache.spark.rdd.RDD.$anonfun$take$1(RDD.scala:1449)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
  at org.apache.spark.rdd.RDD.withScope(RDD.scala:406)
  at org.apache.spark.rdd.RDD.take(RDD.scala:1443)
  at org.apache.spark.rdd.RDD.$anonfun$first$1(RDD.scala:1484)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
  at org.apache.spark.rdd.RDD.withScope(RDD.scala:406)
  at org.apache.spark.rdd.RDD.first(RDD.scala:1484)
  ... 47 elided
Caused by: java.io.IOException: Input path does not exist: hdfs://westgisB064:8020/home/WBQ/1.txt
  at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:278)
  ... 67 more

scala> 

<think>嗯,用户问的是在运行spark-shell时如何读取HDFS文件并在本地创建文件。我需要先理清楚步骤。首先,用户可能已经熟悉Spark的基本操作,但可能在如何正确读取HDFS上的文件以及将结果保存到本地文件系统上有疑问。 首先,启动spark-shell的时候,需要确保Spark能够连接到HDFS。通常,HDFS的地址需要正确配置,比如core-site.xml和hdfs-site.xml是否在类路径中。不过用户可能已经设置好了,所以这部分可能不需要详细说明,但可能需要提醒检查HDFS的地址是否正确。 接下来,读取HDFS文件。用户需要使用sc.textFile方法,并且路径应该是HDFS的URI,比如hdfs://namenode:port/path/to/file。这里需要注意,如果用户的HDFS配置正确,可能可以直接用路径,但最好还是用完整的URI,避免歧义。 然后,处理数据。这部分用户可能已经有自己的逻辑,但示例中可能需要展示简单的操作,比如map、filter等,以便用户理解流程。 保存到本地的时候,问题来了。因为Spark运行在集群上时,每个executor都会试图将文件写入自己的本地路径,这可能导致结果分散。所以正确的方法应该是先将结果收集到Driver节点,然后用本地文件操作写入。比如使用collect()方法将RDD数据拉取到Driver,然后用Scala的IO库写入本地文件系统。 需要注意的是,collect()会将所有数据加载到Driver内存,如果数据量太大,会导致内存溢出。这时候可能需要提醒用户,如果数据量过大,可以考虑先过滤或采样,或者使用其他方法分块保存。 另外,如果用户是在本地模式下运行spark-shell,那么默认的文件系统可能就是本地,但HDFS路径仍需要明确指定。这时候保存到本地可以直接使用saveAsTextFile("file:///path"),不过要确认是否有权限。 用户可能需要区分集群模式和本地模式的不同处理方式。如果是在集群上运行,Driver可能不在本地机器上,这时候直接保存到本地路径可能指的是Driver所在节点的路径,而不是用户启动spark-shell的客户端机器。这种情况下,用户可能需要将文件从Driver节点传输回本地,或者使用网络路径。 最后,示例代码需要展示完整的流程,从读取HDFS文件,处理数据,收集结果,到写入本地文件。同时要强调正确使用URI格式,以及处理可能出现的异常,比如文件已存在时的错误,可能需要先删除旧文件。 总结一下,步骤应该是:1. 启动spark-shell,确认HDFS配置;2. 用sc.textFile读取HDFS文件;3. 处理数据;4. 收集数据到Driver;5. 使用Scala写文件到本地。同时提醒数据量的问题和路径的正确格式。</think>以下是使用Spark Shell读取HDFS文件并在本地创建文件的完整步骤: --- ### **步骤1:启动Spark Shell** ```bash $ spark-shell --master local[*] ``` 注意:`--master local[*]`表示使用本地模式运行,如果连接集群需改为`yarn` --- ### **步骤2:读取HDFS文件** ```scala // 读取HDFS文件(假设HDFS路径为hdfs:///user/hadoop/input.txt) val hdfsFile = sc.textFile("hdfs://namenode:8020/user/hadoop/input.txt") // 若HDFS配置了默认路径,可简写为: val hdfsFile = sc.textFile("/user/hadoop/input.txt") ``` --- ### **步骤3:处理数据** ```scala // 示例:统计单词数量 val wordCounts = hdfsFile.flatMap(line => line.split(" ")) .map(word => (word, 1)) .reduceByKey(_ + _) ``` --- ### **步骤4:保存到本地文件系统** ```scala // 方法1:直接保存(注意这会生成多个part文件) wordCounts.saveAsTextFile("file:///tmp/output") // 方法2:合并后保存为单个文件(适用于小数据集) import java.io.PrintWriter new PrintWriter("/tmp/output.txt") { write(wordCounts.collect().mkString("\n")) close() } ``` --- ### **关键说明** 1. **路径格式差异**: - HDFS路径:`hdfs://namenode:port/path` 或 `/path` - 本地路径:`file:///absolute/path` 2. **权限问题**: - 确保Spark进程有本地目录的写入权限 - 若在集群模式,`file://`路径指向的是Worker节点的本地文件系统 3. **数据量警告**: - `collect()`会将所有数据加载到Driver内存,大数据集可能引发OOM - 超过1GB数据建议先执行`coalesce(1)`再保存 --- ### **验证操作** ```bash # 检查本地文件 $ cat /tmp/output/part-00000 # 或 $ cat /tmp/output.txt ``` --- ### **完整示例** ```scala // 从HDFS读取,处理后将结果写入本地 val data = sc.textFile("hdfs:///logs/access.log") val filtered = data.filter(_.contains("ERROR")) filtered.coalesce(1).saveAsTextFile("file:///tmp/error_logs") ``` 通过以上步骤即可实现HDFS到本地的数据流转。是否需要进一步说明特定环节的实现细节?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值