我有一个Spark程序(在Scala中)和一个SparkContext
。我正在撰写一些RDD
的{{1}}文件。在我的本地计算机上,我可以使用本地文件路径,它可以与本地文件系统一起使用。在我的群集上,它适用于HDFS。
我还想编写其他任意文件作为处理结果。我在本地计算机上将它们写为常规文件,但希望它们在群集上进入HDFS。
saveAsTextFile
似乎有一些与文件相关的方法,但它们似乎都是输入而不是输出。
我该怎么做?
答案 0 :(得分:10)
感谢marios和kostya,但是从Spark中将文本文件写入HDFS的步骤很少。
// Hadoop Config is accessible from SparkContext
val fs = FileSystem.get(sparkContext.hadoopConfiguration);
// Output file can be created from file system.
val output = fs.create(new Path(filename));
// But BufferedOutputStream must be used to output an actual text file.
val os = BufferedOutputStream(output)
os.write("Hello World".getBytes("UTF-8"))
os.close()
请注意,已建议的FSDataOutputStream
是Java序列化对象输出流,而不是文本输出流。 writeUTF
方法似乎写了plaint文本,但它实际上是一个包含额外字节的二进制序列化格式。
答案 1 :(得分:4)
这对我来说最有效(使用Spark 2.0):
val path = new Path("hdfs://namenode:8020/some/folder/myfile.txt")
val conf = new Configuration(spark.sparkContext.hadoopConfiguration)
conf.setInt("dfs.blocksize", 16 * 1024 * 1024) // 16MB HDFS Block Size
val fs = path.getFileSystem(conf)
if (fs.exists(path))
fs.delete(path, true)
val out = new BufferedOutputStream(fs.create(path)))
val txt = "Some text to output"
out.write(txt.getBytes("UTF-8"))
out.flush()
out.close()
fs.close()
答案 2 :(得分:2)
使用HDFS API(hadoop-hdfs.jar),您可以为HDFS路径创建InputStream / OutputStream,并使用常规java.io类读取/写入文件。例如:
URI uri = URI.create (“hdfs://host:port/file path”);
Configuration conf = new Configuration();
FileSystem file = FileSystem.get(uri, conf);
FSDataInputStream in = file.open(new Path(uri));
此代码也适用于本地文件(将hdfs://
更改为file://
)。
答案 3 :(得分:2)
将文件写入HDFS的一种简单方法是使用SequenceFiles。在这里,您使用本机Hadoop API和不 Spark提供的API。
这是一个简单的代码段(在Scala中):
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs._
import org.apache.hadoop.io._
val conf = new Configuration() // Hadoop configuration
val sfwriter = SequenceFile.createWriter(conf,
SequenceFile.Writer.file(new Path("hdfs://nn1.example.com/file1")),
SequenceFile.Writer.keyClass(LongWritable.class),
SequenceFile.Writer.valueClass(Text.class))
val lw = new LongWritable()
val txt = new Text()
lw.set(12)
text.set("hello")
sfwriter.append(lw, txt)
sfwriter.close()
...
如果您没有密钥,可以在其位置使用NullWritable.class
:
SequenceFile.Writer.keyClass(NullWritable.class)
sfwriter.append(NullWritable.get(), new Text("12345"));