在spark java api中递归读取HDFS中的所有文件
我正在使用spark从一个目录及其子目录中的单个RDD中读取HDFS中所有文件的数据。我找不到任何有效的方法来做那件事。因此,我尝试编写一些定制代码,如下所示:在spark java api中递归读取HDFS中的所有文件,java,hadoop,hdfs,apache-spark,Java,Hadoop,Hdfs,Apache Spark,我正在使用spark从一个目录及其子目录中的单个RDD中读取HDFS中所有文件的数据。我找不到任何有效的方法来做那件事。因此,我尝试编写一些定制代码,如下所示: public Object fetch(String source,String sink) { //reading data boolean isDir=new File(source).isDirectory(); System.out.println("isDir="+isDir); JavaRD
public Object fetch(String source,String sink) {
//reading data
boolean isDir=new File(source).isDirectory();
System.out.println("isDir="+isDir);
JavaRDD<String> lines;
if(isDir)
{
lines=readFiles(new File(source).listFiles(), null);
}
else
lines= sc.textFile(source);
lines.saveAsTextFile(sink);
return true;
}
public static JavaRDD<String> readFiles(File[] files,JavaRDD<String> lines) {
for (File file : files) {
if (file.isDirectory()) {
readFiles(file.listFiles(),lines); // Calls same method again.
}
else {
if(lines==null)
lines=sc.textFile(file.getPath());
else
{
JavaRDD<String> r=sc.textFile(file.getPath());
lines.union(r);
}
}
}
return lines;
}
公共对象获取(字符串源、字符串接收器){
//读取数据
布尔值isDir=新文件(源).isDirectory();
System.out.println(“isDir=“+isDir”);
JavaRDD行;
中频(isDir)
{
lines=readFiles(新文件(源).listFiles(),null);
}
其他的
行=sc.textFile(源);
行。saveAsTextFile(接收器);
返回true;
}
公共静态JavaRDD读取文件(文件[]文件,JavaRDD行){
用于(文件:文件){
if(file.isDirectory()){
readFiles(file.listFiles(),line);//再次调用相同的方法。
}
否则{
如果(行==null)
lines=sc.textFile(file.getPath());
其他的
{
javarddr=sc.textFile(file.getPath());
联合(r);
}
}
}
回流线;
}
但这并不是我期望的工作,因为isDir包含错误的信息,告诉我它不是目录。
你能告诉我怎么了吗?有什么有效的方法来做这项工作吗?
非常感谢,所以我终于找到了解决办法。我犯了一个错误,因为我使用了用于从本地文件系统读取文件的文件对象。为了读/写HDFS,我们需要使用org.apache.hadoop.fs* 这就是解决方案
public Object fetch(String source,String sink) {
//reading data
Path src=new Path(source);
try {
if(fs.exists(src))
{
FileStatus[] lists=fs.listStatus(src);
readFiles(lists);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
public void readFiles(FileStatus[] files) {
for(int i=0;i<files.length;i++)
{
if(files[i].isDirectory())
{
try {
readFiles(fs.listStatus(files[i].getPath()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
if(lines==null)
{
Path p=files[i].getPath();
JavaRDD<String> lines=sc.textFile(p.toString());
}
else
{
JavaRDD<String> r=sc.textFile(file.getPath());
lines.union(r);
}
}
}
return lines;
}
公共对象获取(字符串源、字符串接收器){
//读取数据
路径src=新路径(源);
试一试{
如果(fs.存在(src))
{
FileStatus[]lists=fs.listStatus(src);
读取文件(列表);
}
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
返回true;
}
公共void读取文件(FileStatus[]文件){
对于(int i=0;i,因为spark可以基于Hadoop作业配置读取数据,所以可以使用FileInputFormat#setInputDirRecursive
方法
JavaSparkContext context = new JavaSparkContext();
Job job;
try {
job = Job.getInstance();
FileInputFormat.setInputPaths(job, new Path("/path/to/input/directory));
FileInputFormat.setInputDirRecursive(job, true);
} catch (IOException e1) {
e1.printStackTrace();
System.exit(1);
}
JavaRDD<Text> sourceData = context.newAPIHadoopRDD(job.getConfiguration(), TextInputFormat.class, LongWritable.class, Text.class)
.values();
JavaSparkContext上下文=新建JavaSparkContext();
工作;
试一试{
job=job.getInstance();
setInputPaths(作业,新路径(“/Path/to/input/directory”);
setInputDirRecursive(作业,true);
}捕获(IOE1异常){
e1.printStackTrace();
系统出口(1);
}
JavaRDD sourceData=context.newAPIHadoopRDD(job.getConfiguration(),TextInputFormat.class,LongWritable.class,Text.class)
.values();
显然,最终将使用文本数据类型而不是字符串。该“*”字符递归读取文件夹
JavaSparkContext sc = new JavaSparkContext(conf);
sc.textFile("/my/directory/*");
有关更多信息,请阅读此链接:
我不确定,但你应该使用Path
api而不是File
是的,我错了,接受你的答案并感到高兴:-)是的,顺便说一句,谢谢:-)比其他答案简单得多,我不知道为什么这不是被接受的答案。