java 读取hdfs文件,注意事项

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

,这个问题纠结了很长时间(尝试添加core-site.xml,hdfs-site.xml,map-site.xml.等等)都尝试了,还是失败,最终问题原因找到了在于

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

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

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

在函数中使用了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<LocatedFileStatus> 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()) ); } }

经验分享 程序员 微信小程序 职场和发展