Apache Hadoop 使用Java API操作HDFS之获取FileSystem对象

maven依赖

<dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

为了便于测试这里使用单元测试

Part One

如何获得HDFS文件系统?

可以使用URI/Path配合Configuration来获取。

需要导包如下

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
Configuration conf=new Configuration();
URI uri=new URI("hdfs://192.168.183.81:9000");
FileSystem fs = FileSystem.get(uri,conf,"用户名");   // 第三个参数可省
System.out.println(fs); 
// 输出结果为:DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1963527693_1, ugi=mycat (auth:SIMPLE)]]

输出结果中,mycat是我的NameNode节点IP映射的主机名,此时获得是HDFS文件系统,如果将上面第三行改为:

FileSystem fs = FileSystem.get(conf);

即不传递uri,则控制台输出的是:

org.apache.hadoop.fs.LocalFileSystem@57a3af25

此时就编程本地文件系统了(默认)。

不过需要注意的是:上面获得HDFS文件系统实例的方式还有其他写法,如:

Configuration conf=new Configuration();
conf.set("fs.defaultFS", "hdfs://192.168.183.81:9000");
FileSystem fs = FileSystem.get(conf);
System.out.println(fs);

输出结果同样是:

DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1930027030_1, ugi=mycat (auth:SIMPLE)]]

第一种方式的URI传参和这种conf配置的形式都传递了相同的信息,就是传递了namenode的节点路径信息。但是为什么不设置就输出为本地文件系统呢?很显然在Configuration实例对象conf中存有默认值

代码如下:

@Test
public void printConf(){
   	Configuration config = new Configuration();
    for (Map.Entry<String, String> entry : config) {
        System.out.println(entry.getKey()+"=>" +entry.getValue());
    }
}

输出结果蛮多的,下面仅抽选部分:

...
fs.defaultFS=>file:///
fs.s3a.multipart.size=>104857600
fs.s3a.connection.establish.timeout=>5000
...

不难看出结果显示:fs.defaultFS=>file:///表示默认使用的是本地文件系统。

Part Two

上面我们仅仅创建一个Configuration对象,但是默认加载了namenode的相关配置,name这些配置在哪里呢?

hdfsjavaapidefaultxml

可以看出,默认配置其实在hadoop-hdfs的jar包hdfs-default里面,其实这个就类似与我们在hadoop的etc/hadoop目录下配置的hdfs-site.xml等文件。

而且经过实验测试,只要我们在项目的src目录下按照hdfs-default.xml形式创建文件名为core-site.xml,core-default.xml的自定义配置文件,按照对应的key来设置默认值就可以实现自动加载。

core-default.xml中

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
  <name>fs.defaultFS</name>
  <value>hdfs://192.168.183.81:9000</value>
</property>
</configuration>

java测试代码

@Test
    public void testM() throws IOException, URISyntaxException {
        Configuration conf=new Configuration();
        FileSystem fs = FileSystem.get(conf);
        System.out.println(fs);
    }

输出结果

DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1778937579_1, ugi=mycat (auth:SIMPLE)]]

假如说要使用其他的名称的xml,那么需要使用Configuration对象的addResource方法:

自定义名称的xml:(user-default.xml

文件内容同上面core-default.xml一样。

测试代码

@Test
public void testCustom() throws IOException {
    Configuration conf=new Configuration();
    conf.addResource("user-default.xml");
    FileSystem fs = FileSystem.get(conf);
    System.out.println(fs);
}

结果如下

DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1745930730_1, ugi=mycat (auth:SIMPLE)]]

猜你喜欢

转载自blog.csdn.net/qq_33713328/article/details/88317514