在spark java api中递归读取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

我正在使用spark从一个目录及其子目录中的单个RDD中读取HDFS中所有文件的数据。我找不到任何有效的方法来做那件事。因此,我尝试编写一些定制代码,如下所示:

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
是的,我错了,接受你的答案并感到高兴:-)是的,顺便说一句,谢谢:-)比其他答案简单得多,我不知道为什么这不是被接受的答案。