昨天在写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目录下,都有如下的内容:
可以看到,这两个包的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()) );
}
}