2. Hadoop:编程操作 HDFS 文件系统

一、Maven 安装配置

我使用 Eclipse 及 Maven 作为编程环境,Eclipse 的安装比较简单,只需要下载解压即可,现在来安装 Maven。

1. 下载解压:

我在这里选择3.3.9版本,解压到 /opt/maven 目录下,此时 Maven 的主目录就是 /opt/maven/apache-maven-3.3.9

2. Maven 下载配置

Maven 默认下载库使用的是国外的镜像,速度比较慢,因此需要选择在配置文件中改为国内的镜像。
打开 /opt/maven/apache-maven-3.3.9/conf 目录下的 settings.xml 文件,在 <mirrors> 标签中添加如下镜像:

        <!-- 阿里云仓库 -->
        <mirror>
            <id>alimaven</id>
            <mirrorOf>central</mirrorOf>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
        </mirror>
    
        <!-- 中央仓库1 -->
        <mirror>
            <id>repo1</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo1.maven.org/maven2/</url>
        </mirror>
    
        <!-- 中央仓库2 -->
        <mirror>
            <id>repo2</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo2.maven.org/maven2/</url>
        </mirror>
3. 系统配置

使用 vi 或者 gedit 修改系统的配置文件,我这里使用 gedit:

$ sudo gedit /etc/profile

在该文件最后添加:

# Maven
export MAVEN_HOME=/opt/maven/apache-maven-3.3.9
export PATH=$PATH:$MAVEN_HOME/bin

使用 source 命令使配置文件的修改生效:

$ source /etc/profile

此时可以使用 Maven 命令检查是否安装成功:

$ mvn -v

安装成功结果如下:

《2. Hadoop:编程操作 HDFS 文件系统》 Maven 安装成功.png

4. Eclipse 中配置 Maven

Eclipse 中选择 Window->Preferences 中的 Maven
首先在 Installations 中将 Maven 的目录改为刚刚手动安装的 Maven3.3.9:

《2. Hadoop:编程操作 HDFS 文件系统》 Installations.png

之后在 User Settings 中修改配置文件的目录为我们自己安装的 Maven 的配置文件,将两处的配置文件目录都修改为 /opt/maven/apache-maven-3.3.9/conf/settings.xml, Loacl Repository 为 Maven 下载的库的目录,这里使用默认目录。

《2. Hadoop:编程操作 HDFS 文件系统》 User Settings.png

5. 新建 Maven 项目并添加 Hadoop 依赖

在 Eclipse 中 File->new->Maven Project,点击两次 next,填写包名及项目名:

《2. Hadoop:编程操作 HDFS 文件系统》 新建 Maven 项目.png

选择项目中的 pom.xml,在 <dependencies> 中添加如下标签,此时 Maven 会自动去下载标签中的库,也就是 Hadoop2.5.0 对应的 Java 库。

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
     <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.5.0</version>
        <scope>compile</scope>
     </dependency>

二、Java 操作 HDFS

简介

本地访问 HDFS 最主要的方式是 HDFS 提供的 Java 应用程序接口,其他的访问方式都是建立在这些应用程序接口之上。为了访问 HDFS,HDFS 客户端必须拥有一份 HDFS 的配置文件 hfds-site.xml 来获取 NameNode 的相关信息。

Java程序

1. 读取 HDFS 中的文件

创建类 HDFSCat 用于读取 HDFS 文件系统中的文件内容并打印在控制台。

代码中使用 static 静态代码块执行 URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()),该段代码的作用是让 Java 程序可以识别 Hadoop 的 HDFS url。静态代码块会随着类的加载而执行并只执行一次,它的执行优于主函数。
在主函数中,代码使用 InputStream 读取文件流,并使用 IOUtils 中的 copyBytes 函数将文件内容打印到控制台,false 表示操作结束后不关闭文件流。
完整代码如下:

public class HDFSCat {

    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    
    public static void main(String[] args) {
        InputStream inputStream = null;
        try {
            String url = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
            inputStream = new URL(url).openStream();
            IOUtils.copyBytes(inputStream, System.out, 4096, false);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeStream(inputStream);
        }
    }

}
2. 使用 FileSystem 读取文件内容

Hadoop 库中的 Configuration 和 FileSystem 这两个类可以用来操作 HDFS 文件系统,Configuration 会从项目的 Resources 文件中读取 HDFS 的配置。因此我们需要将 Hadoop 的配置文件放入到项目中。

在项目上右击 new->source folder,在 src/main 下新建一个存放配置文件的文件夹 resources,如下所示:

《2. Hadoop:编程操作 HDFS 文件系统》 新建 resources 文件夹.png

之后将 core-site.xml 以及 hdfs-site.xml 拷贝到该文件夹内,最后的项目结构如下:

《2. Hadoop:编程操作 HDFS 文件系统》 Maven 项目结构.png

配置完成之后就可以使用 FileSystem 来读取文件了,只不过这次是通过 FileSystem 的对象来获取文件流,该类的 open() 方法返回 Hadoop 独有的 FSDataInputStream 对象。

public class FSCat {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        InputStream in = null;
        try {
            String uri = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
            in = fs.open(new Path(uri));
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }

}
3. 使用 FileSystem 向 HDFS 中写入文件

这里使用 InputStream 读取 Linux 文件流并输出到 HDFS 文件中,在读取文件的时候使用 BufferedInputStream 而不是 FileInputStream,因为使用 FileInputStream 时会频繁地访问磁盘,读取时效率较低。而是用 BufferedInputStream 时,该类会创建一个内部缓冲数组,在读取流中的字节时,可以根据需要从包含的输入流中填充内部缓冲区,一次填充多个字节。

public class CopyFileToHDFS {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        String source = "/opt/source";
        String destination = "hdfs://localhost:9000/user/destination";
        InputStream inputStream = new BufferedInputStream(
                new FileInputStream(source));
        OutputStream outputStream = fs.create(new Path(destination));
        // 将 Linux 中的 source 文件拷贝到 HDFS 的 destination
        // true 表示操作结束后自动关闭文件流,因此不需要手动关闭
        IOUtils.copyBytes(inputStream, outputStream, 4096, true);
    }

}

运行成功后去 HDFS 下查看 /user 目录,会发现多了 destination 文件。

4. 创建目录
public class CreateFolder {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path path = new Path("hdfs://localhost:9000/datas/new_folder");
        fs.mkdirs(path);
    }

}
5. 删除文件或目录

delete() 方法中如果传入 false 表示删除一个文件,如果传入 true 表示递归删除文件夹及文件。

public class DeleteFile {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path deletePath = new Path("/user/destination");
        boolean isDeleted = fs.delete(deletePath, false);
        System.out.println("result: " + isDeleted);
    }

}
6. 列出目录下的文件或目录名
public class ListeFiles {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        String uri = "hdfs://localhost:9000/datas/test/mapred";
        Path path = new Path(uri);
        FileStatus[] status = fs.listStatus(path);
        for (FileStatus fileStatus : status) {
            System.out.println(fileStatus.getPath().toString());
        }
        fs.close();
    }

}
    原文作者:东方未曦
    原文地址: https://www.jianshu.com/p/8b8526805d9e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞