java 读取hdfs文件,注意事项

昨天在写java读取hdfs文件的时候一直报错

java.io.IOException: No FileSystem for scheme: hdfs

,这个问题纠结了很长时间(尝试添加core-site.xml,hdfs-site.xml,map-site.xml.等等)都尝试了,还是失败,最终问题原因找到了在于https://www.cnblogs.com/justinzhang/p/4983673.html

发现与hadoop filesystem相关的包有两个,分别是:hadoop-hdfs-2.7.1.jar和hadoop-common-2.7.1.jar,这两个包的META-INF中的services目录下,都有如下的内容:

 

java 读取hdfs文件,注意事项_第1张图片

java 读取hdfs文件,注意事项_第2张图片

可以看到,这两个包的services目录下都有,org.apache.hadoop.fs.FileSystem这个文件。使用Maven-assembly-plugin的时候,会将所有依赖的包unpack,然后在pack,这样就会出现,同样的文件被覆盖的情况,我们看下打好的包中保留的是啥:

 

java 读取hdfs文件,注意事项_第3张图片

 

可以看到,maven-assembly-plugin(fatjar也是一样的),将hadoop-common.jar中的services内容打进了最终的jar包中,而hadoop-hdfs.jar包中,services的内容被覆盖了。由于我们的函数调用是这样写的

java 读取hdfs文件,注意事项_第4张图片java 读取hdfs文件,注意事项_第5张图片

在函数中使用了hdfs://IP : port的schema,而在生成的最终jar包中,无法找到这个schema的实现。所以就抛出了

java.io.IOException: No FileSystem for scheme: hdfs

解决方案是,在设置hadoop的配置的时候,显示设置这个类:"org.apache.hadoop.hdfs.DistributedFileSystem:

configuration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

然后在重新打包,一切works ok了。

 

 

//读取文件夹,写入出文件
    public void readFileWriteItOnCdh(String hdfsDir,String url) throws  Exception {
        Configuration conf = new Configuration();// 读取配置文件\
        conf.set("fs.defaultFS", "hdfs://hadoop4:8020");
        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");        
        Path outPath = new Path(hdfsDir);
        FileSystem hdfs = outPath.getFileSystem(conf);// 创建输出路径
//        if (hdfs.isDirectory(outPath)) {
//            hdfs.delete(outPath, true);
//        }
           
           RemoteIterator iterator = hdfs.listFiles(new Path(hdfsDir), true);
           while (iterator.hasNext()) {
               LocatedFileStatus status = iterator.next();
               Path filePath = status.getPath();
               String fileName = filePath.getName();
//               System.out.println(fileName);
               String dsf = hdfsDir+fileName;
               
               FileSystem fs = FileSystem.get(URI.create(dsf),conf);
               FSDataInputStream hdfsInStream = fs.open(new Path(dsf));
               
               byte[] bytes = new byte[1024];
               int len = -1;
               ByteArrayOutputStream stream = new ByteArrayOutputStream();
        
               while ((len = hdfsInStream.read(bytes)) != -1) {
                   stream.write(bytes, 0, len);
               }
               hdfsInStream.close();
               stream.close();
               WriteLocal.method1(url,new String(stream.toByteArray()) );
           }
    }

你可能感兴趣的:(java 读取hdfs文件,注意事项)