Spark执行RDD操作后自动创建同名文件夹引发路径错误
我之前也碰到过几乎一模一样的问题!让我来帮你拆解下原因和解决办法:
问题场景回顾
你在HDFS中放置了Linecount2.txt文本文件,执行以下Spark代码能正常统计行数:
val lines = sc.textFile("user/root/hdpcd/Linecount2.txt") lines.count()
但后续再次使用相同路径访问该文件时,却收到报错:
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist:
查看对应路径后发现,系统自动创建了名为Linecount.txt的文件夹,导致原文件路径失效。
问题根源分析
这大概率是Spark输出操作的特性导致的:Spark的saveAsTextFile等输出方法,要求目标路径必须是文件夹(它会在该文件夹下生成part-*格式的分片文件)。如果你在后续操作中,不小心将输出路径指定为和原文件路径接近的user/root/hdpcd/Linecount.txt(比如漏写了原文件名的数字2),Spark会自动创建这个文件夹;更糟的情况是,如果误将输出路径设为原文件路径Linecount2.txt,Spark会直接删除原文件并创建同名文件夹,彻底导致原路径失效。
另外HDFS不允许同一目录下存在同名的文件和文件夹,一旦文件夹创建成功,原文件路径自然无法被识别。
具体解决步骤
1. 先确认HDFS的实际文件结构
先执行HDFS命令查看目标目录的内容,搞清楚文件和文件夹的实际状态:
hdfs dfs -ls /user/root/hdpcd/
通过这个命令你能明确:
- 原
Linecount2.txt文件是否还存在 Linecount.txt文件夹内的内容是什么(是否是你误输出的分片文件)
2. 针对不同情况修复
如果原
Linecount2.txt文件已被删除,且Linecount.txt文件夹是误操作生成的:- 若文件夹内的
part-*文件是你需要的数据,可以直接读取这个文件夹(Spark会自动读取文件夹下所有分片文件):val lines = sc.textFile("user/root/hdpcd/Linecount.txt") lines.count() - 若不需要这个文件夹,先删除它再重新上传原文件:
# 删除文件夹 hdfs dfs -rm -r /user/root/hdpcd/Linecount.txt # 重新上传本地的Linecount2.txt到HDFS hdfs dfs -put /本地文件路径/Linecount2.txt /user/root/hdpcd/
- 若文件夹内的
如果原文件还存在,只是后续访问时路径写错(比如漏了数字
2),修正路径即可正常访问。
3. 避免后续再踩坑
- 严格区分输入输出路径:永远不要把Spark的输出路径设置为输入文件的路径,否则Spark会直接删除原文件并创建同名文件夹。
- 操作前先检查路径:执行写入操作前,先用
hdfs dfs -ls确认目标路径不存在,或者在代码中添加路径检查逻辑:import org.apache.hadoop.fs.{FileSystem, Path} val fs = FileSystem.get(sc.hadoopConfiguration) val outputPath = new Path("user/root/hdpcd/Linecount_output") if (fs.exists(outputPath)) { fs.delete(outputPath, true) // 递归删除已有路径 } // 执行输出操作 lines.saveAsTextFile(outputPath.toString) - 注意文件名拼写:像
Linecount2.txt和Linecount.txt这种仅差一个字符的文件名,很容易写错,操作时多核对一遍。
内容的提问来源于stack exchange,提问作者abdul rahim

