如何在sc.textFile中代替HDFS加载本地文件


100

我正在关注很棒的Spark教程

所以我试图在46m:00s加载,README.md但是失败了,我正在做的是:

$ sudo docker run -i -t -h sandbox sequenceiq/spark:1.1.0 /etc/bootstrap.sh -bash
bash-4.1# cd /usr/local/spark-1.1.0-bin-hadoop2.4
bash-4.1# ls README.md
README.md
bash-4.1# ./bin/spark-shell
scala> val f = sc.textFile("README.md")
14/12/04 12:11:14 INFO storage.MemoryStore: ensureFreeSpace(164073) called with curMem=0, maxMem=278302556
14/12/04 12:11:14 INFO storage.MemoryStore: Block broadcast_0 stored as values in memory (estimated size 160.2 KB, free 265.3 MB)
f: org.apache.spark.rdd.RDD[String] = README.md MappedRDD[1] at textFile at <console>:12
scala> val wc = f.flatMap(l => l.split(" ")).map(word => (word, 1)).reduceByKey(_ + _)
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://sandbox:9000/user/root/README.md
    at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:285)

我该如何加载README.md呢?

Answers:


177

尝试明确指定sc.textFile("file:///path to the file/")。设置Hadoop环境时会发生此错误。

SparkContext.textFile内部调用org.apache.hadoop.mapred.FileInputFormat.getSplitsorg.apache.hadoop.fs.getDefaultUri如果不存在架构,则反过来使用。此方法读取Hadoop conf的“ fs.defaultFS”参数。如果设置HADOOP_CONF_DIR环境变量,则该参数通常设置为“ hdfs:// ...”; 否则为“ file://”。


您是否知道如何使用Java做到这一点?我看不到方法。非常令人沮丧的是,没有一种简单的方法可以提供从简单文件系统加载文件的路径。
布拉德·埃利斯

回答自己。您随spark-submit传递了一个--file开关。因此,文件路径可以是硬编码的,也可以是您为应用程序设置的配置,但是您也要指出该路径。当您提交以便执行者可以看到路径时。
布拉德·埃利斯

24

贡贝的答案非常好。但我仍然想提file:///= = ~/../../,不是$SPARK_HOME。希望这可以为像我这样的新手节省一些时间。


4
file:///是执行JVM所看到的文件系统的根文件夹,而不是主文件夹上方的两个级别。如在指定的URI格式RFC 8089file://hostname/absolute/path。在本地情况下,hostname(权限)组件为空。
赫里斯托·伊利耶夫

17

尽管Spark支持从本地文件系统加载文件,但它要求文件在群集中所有节点上的同一路径上可用。

一些网络文件系统(例如NFS,AFS和MapR的NFS层)作为常规文件系统向用户公开。

如果您的数据已经在这些系统之一中,则只需指定file://路径就可以将其用作输入。只要文件系统安装在每个节点的相同路径上,Spark就会处理它。每个节点都必须具有相同的路径

 rdd = sc.textFile("file:///path/to/file")

如果您的文件尚未在集群中的所有节点上,则可以在不通过Spark的情况下将其本地加载到驱动程序中,然后调用parallelize将内容分发给worker

请注意将file://放在前面,并根据操作系统使用“ /”或“ \”。


1
有没有一种方法可以使Spark自动将数据从其$ SPARK_HOME目录复制到所有计算节点。还是您需要手动执行此操作?
马赛厄斯'18

spark源代码在哪里处理不同的文件系统格式?
Saher Ahwal '18


12

注意:

从local(sc.textFile("file:///path to the file/"))加载数据时,请确保在本地模式下运行spark,否则会收到类似这样的错误Caused by: java.io.FileNotFoundException: File file:/data/sparkjob/config2.properties does not exist。因为在不同工作程序上运行的执行程序不会在本地路径中找到此文件。


11

如果文件位于您的Spark主节点中(例如,在使用AWS EMR的情况下),则首先以本地模式启动spark-shell。

$ spark-shell --master=local
scala> val df = spark.read.json("file:///usr/lib/spark/examples/src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> df.show()
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

或者,您可以先将文件从本地文件系统复制到HDFS,然后以默认模式启动Spark(例如,在使用AWS EMR的情况下为YARN)以直接读取文件。

$ hdfs dfs -mkdir -p /hdfs/spark/examples
$ hadoop fs -put /usr/lib/spark/examples/src/main/resources/people.json /hdfs/spark/examples
$ hadoop fs -ls /hdfs/spark/examples
Found 1 items
-rw-r--r--   1 hadoop hadoop         73 2017-05-01 00:49 /hdfs/spark/examples/people.json

$ spark-shell
scala> val df = spark.read.json("/hdfs/spark/examples/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> df.show()
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

9

我的桌面上有一个名为NewsArticle.txt的文件。

在Spark中,我输入:

val textFile= sc.textFile(“file:///C:/Users/582767/Desktop/NewsArticle.txt”)

我需要将文件路径的所有\更改为/字符。

为了测试它是否有效,我输入了:

textFile.foreach(println)

我正在运行Windows 7,但未安装Hadoop。


5

这已经在spark邮件列表中讨论过了,请参阅此邮件

您应该使用hadoop fs -put <localsrc> ... <dst>将文件复制到hdfs

${HADOOP_COMMON_HOME}/bin/hadoop fs -put /path/to/README.md README.md

5

对于Spark 2.3来说,这已经发生了,并且Hadoop也安装在公用的“ hadoop”用户主目录下。由于Spark和Hadoop都安装在同一公用目录下,因此Spark默认将方案视为hdfs,并开始查找输入文件。fs.defaultFS在Hadoop的中指定的hdfs下core-site.xml。在这种情况下,我们需要将方案明确指定为file:///<absoloute path to file>


0

这是针对我在Windows群集上的Azure中托管的Spark群集上遇到的此错误的解决方案:

加载原始的HVAC.csv文件,使用函数进行解析

data = sc.textFile("wasb:///HdiSamples/SensorSampleData/hvac/HVAC.csv")

我们使用(wasb:///)允许Hadoop访问azure博客存储文件,三个斜杠是对正在运行的节点容器文件夹的相对引用。

例如:如果您在Spark群集仪表板的“文件资源管理器”中文件的路径为:

sflcc1 \ sflccspark1 \ HdiSamples \ SensorSampleData \ hvac

因此要描述的路径如下:sflcc1:是存储帐户的名称。sflccspark:是集群节点名称。

因此,我们用相对的三个斜杠来引用当前的群集节点名称。

希望这可以帮助。


0

如果您尝试读取HDFS文件格式。尝试在SparkConf中设置路径

 val conf = new SparkConf().setMaster("local[*]").setAppName("HDFSFileReader")
 conf.set("fs.defaultFS", "hdfs://hostname:9000")

请在代码中添加4个空格/制表符缩进,以便将其格式化为代码。最好的问候
YakovL

0

您不必使用sc.textFile(...)将本地文件转换为数据帧。选项之一是,逐行读取本地文件,然后将其转换为Spark Dataset。这是Java中Windows机器的示例:

StructType schemata = DataTypes.createStructType(
            new StructField[]{
                    createStructField("COL1", StringType, false),
                    createStructField("COL2", StringType, false),
                    ...
            }
    );

String separator = ";";
String filePath = "C:\\work\\myProj\\myFile.csv";
SparkContext sparkContext = new SparkContext(new SparkConf().setAppName("MyApp").setMaster("local"));
JavaSparkContext jsc = new JavaSparkContext (sparkContext );
SQLContext sqlContext = SQLContext.getOrCreate(sparkContext );

List<String[]> result = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
    String line;
    while ((line = br.readLine()) != null) {
      String[] vals = line.split(separator);
      result.add(vals);
    }
 } catch (Exception ex) {
       System.out.println(ex.getMessage());
       throw new RuntimeException(ex);
  }
  JavaRDD<String[]> jRdd = jsc.parallelize(result);
  JavaRDD<Row> jRowRdd = jRdd .map(RowFactory::create);
  Dataset<Row> data = sqlContext.createDataFrame(jRowRdd, schemata);

现在,您可以data在代码中使用数据框。


0

我尝试了以下操作,并且它可以从本地文件系统运行。基本上,spark可以从本地,HDFS和AWS S3路径读取

listrdd=sc.textFile("file:////home/cloudera/Downloads/master-data/retail_db/products")

-6

尝试

val f = sc.textFile("./README.md")

scala> val f = sc.textFile("./README.md") 14/12/04 12:54:33 INFO storage.MemoryStore: ensureFreeSpace(81443) called with curMem=164073, maxMem=278302556 14/12/04 12:54:33 INFO storage.MemoryStore: Block broadcast_1 stored as values in memory (estimated size 79.5 KB, free 265.2 MB) f: org.apache.spark.rdd.RDD[String] = ./README.md MappedRDD[5] at textFile at <console>:12 scala> val wc = f.flatMap(l => l.split(" ")).map(word => (word, 1)).reduceByKey(_ + _) org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://sandbox:9000/user/root/README.md at
2014年

你能pwd在bash shell上做一个吗bash-4.1#
Soumya Simanta 2014年

bash-4.1#pwd /usr/local/spark-1.1.0-bin-hadoop2.4
Jas 2014年

这在没有hadoop / hdfs的情况下对我有效。但是,它似乎不适用于OP,因为它给了他们一个错误转储。
Paul
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.