java操作hdfs文件和操作系统文件方式差不多,但操作hdfs首先要根据集群地址获取FileSystem,然后再进行文件操作。
FileSystem = FileSystem.get(URI.create(hdfsURI), new Configuration());
或者
FileSystem = FileSystem.newInstance(URI.create(hdfsURI), new Configuration());
我之前喜欢用get,我也没探究为什么,而且每次用完我都调用close
但是多线程下报错异常
java.io.IOException: Failed on local exception: java.nio.channels.ClosedByInterruptException; Host Details : local host is: "localhost.localdomain/127.0.0.1"; destination host is: "hadoopMaster":9000; at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:776) ... Caused by: java.nio.channels.ClosedByInterruptException
所以不得不搞清FileSystem get和newInstance区别
查看get得源码:
public static FileSystem get(URI uri, Configuration conf) throws IOException { String scheme = uri.getScheme(); String authority = uri.getAuthority(); if (scheme == null && authority == null) {// use default FS //根据fs.defaultFS的值获取文件系统,若未设置该参数则根据file:///返回文件系统 return get(conf); } if (scheme != null && authority == null) {// no authority //根据fs.defaultFS的值创建URI,若未设置则使用file:///创建URI URI defaultUri = getDefaultUri(conf); if (scheme.equals(defaultUri.getScheme()) // if scheme matches default && defaultUri.getAuthority() != null) { // & default has authority return get(defaultUri, conf); // return default } } String disableCacheName = String.format("fs.%s.impl.disable.cache", scheme); if (conf.getBoolean(disableCacheName, false)) { //根据uri和conf创建FileSystem return createFileSystem(uri, conf); } //若未设置缓存参数为true,则默认从CACHE中获取文件系统对象 return CACHE.get(uri, conf); }
总结:
从上面的代码可以得知,get方法不是每次都创建FileSystem对象,会从缓存中获取FileSystem对象,而newInstance方法则会每次都创建新对象。所以在使用该对象的API编程时,推荐使用get方法。
注意:用get不能close,否则多线程报错(所以我用static),而用newInstance必须每次close.