← 项目列表
课程已完成2026年4月

HDFS 客户端操作

基于 Hadoop 3.3.4 完全分布式集群的 HDFS Java API 实践,覆盖全部常用文件系统操作。

JavaHadoopHDFS大数据JavaHadoop 3.3.4MavenJUnit 4HDFS
📋 项目概览
技术栈
JavaHadoop 3.3.4MavenJUnit 4HDFS
功能特性
  • 11 个 HDFS 操作完整覆盖(mkdir/upload/download/rename/delete)
  • IO 流底层操作:FSDataInputStream / FSDataOutputStream
  • 块信息读取与 DataNode 位置追踪(BlockLocation)
  • 递归目录遍历与文件属性读取(LocatedFileStatus)
  • 参数优先级验证:代码配置 > hdfs-site.xml > 集群默认
  • JUnit 4 测试驱动开发,快速验证 HDFS 连通性
📖 技术分析报告在 GitHub 查看 ↗

HDFS 客户端操作 — Java API 实践

项目概述

基于 Hadoop 3.3.4 完全分布式集群(1主2从),使用 Java API 实现 HDFS 客户端的完整操作。11 个 JUnit 测试用例覆盖了 HDFS 文件系统的全部常用操作。

环境配置

Maven 项目(Java 8),依赖 Hadoop 3.3.4 客户端库:

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>3.3.4</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>3.3.4</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>3.3.4</version>
</dependency>

客户端配置 hdfs-site.xml 指定默认副本数为 1(开发环境),运行时可通过代码配置覆盖。

操作分类

1. 目录管理

  • 创建目录 testMkdirs()FileSystem.mkdirs() 创建多级目录
  • 删除目录 testDelete()FileSystem.delete() 递归删除

2. 文件 CRUD

  • 上传 testUpload()copyFromLocalFile() 从本地拷贝到 HDFS
  • 下载 testDownload()copyToLocalFile() 从 HDFS 拷贝到本地
  • 重命名 testRename()FileSystem.rename() 文件重命名

3. IO 流底层操作

  • 流式上传 testUploadByIO()FileInputStreamFSDataOutputStream
  • 流式下载 testDownloadByIO()FSDataInputStreamFileOutputStream

使用 IOUtils.copyBytes() 完成流拷贝,手动管理流关闭,理解 HDFS 数据流的底层机制。

4. 数据块级操作

  • 按块读取 testReadFileSeek1() / testReadFileSeek2():通过 FSDataInputStream.seek() 定位到指定偏移,验证 HDFS 128MB 块的物理分片特性

5. 元数据查询

  • 文件详情 testListFiles():递归遍历,输出文件名/大小/权限/所有者
  • 根目录状态 testListStatus():判断文件还是目录
  • 块位置追踪 testFileDetailWithBlocks():通过 BlockLocation[] 获取每个数据块的偏移、长度和所在的 DataNode 主机列表

设计决策

参数优先级验证

Hadoop 配置有明确的优先级链:代码中 conf.set() > 资源文件 hdfs-site.xml > 集群默认配置。testUploadWithPriority() 通过设置 dfs.replication=2 验证了这一优先级,可以在 Web UI 上确认副本数变化。

JUnit 驱动开发

每个操作封装为独立的 @Test 方法,可单独运行。这种设计使得:

  • 集群连通性验证只需运行一个测试
  • 每个操作可独立调试
  • 测试即文档,新开发者通过看测试用例就能理解全部功能

关键代码模式

// 标准连接模式
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(
    new URI("hdfs://192.168.88.100:9000"),
    conf, "root"
);
// ... 操作 ...
fs.close();

所有测试用例使用相同的连接创建模式,通过 FileSystem.get() 获取文件系统实例。其中参数优先级验证通过提前 conf.set() 改写配置项,展示了 Hadoop 配置体系的灵活性。

🚀 在线演示新窗口打开 ↗
💻 核心代码Java · Hadoop 3.3.4 · Maven · JUnit 4 · HDFS
xmlMaven 依赖配置pom.xml · 22 行

pom.xml:Hadoop 3.3.4 客户端依赖 + JUnit 4 测试框架。编译目标 Java 8。

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;junit&lt;/groupId&gt;
        &lt;artifactId&gt;junit&lt;/artifactId&gt;
        &lt;version&gt;4.13.2&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
        &lt;artifactId&gt;hadoop-common&lt;/artifactId&gt;
        &lt;version&gt;3.3.4&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
        &lt;artifactId&gt;hadoop-client&lt;/artifactId&gt;
        &lt;version&gt;3.3.4&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.apache.hadoop&lt;/groupId&gt;
        &lt;artifactId&gt;hadoop-hdfs&lt;/artifactId&gt;
        &lt;version&gt;3.3.4&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;
java连接建立与目录管理(mkdir / delete)HdfsClient.java · 25 行

通过 FileSystem.get() 连接 HDFS 集群,创建和删除目录。DFS 配置使用 NameNode URI 直连。

public class HdfsClient {
    // 创建目录
    @Test
    public void testMkdirs() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;),
            conf, &quot;root&quot;
        );
        fs.mkdirs(new Path(&quot;/test/hdfs/demo&quot;));
        fs.close();
    }

    // 删除目录(递归)
    @Test
    public void testDelete() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;),
            conf, &quot;root&quot;
        );
        fs.delete(new Path(&quot;/test/hdfs/demo&quot;), true);
        fs.close();
    }
}
java文件上传(普通 & 参数优先级测试)HdfsClient.java · 28 行

copyFromLocalFile 上传本地文件到 HDFS。参数优先级演示:代码中设置 dfs.replication=2 覆盖 hdfs-site.xml 的默认值 1。

    // 普通上传
    @Test
    public void testUpload() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        fs.copyFromLocalFile(
            new Path(&quot;D:/test.txt&quot;),
            new Path(&quot;/test/hdfs/demo/test.txt&quot;)
        );
        fs.close();
    }

    // 参数优先级测试:代码配置 &gt; 资源文件 &gt; 集群默认
    @Test
    public void testUploadWithPriority() throws Exception {
        Configuration conf = new Configuration();
        conf.set(&quot;dfs.replication&quot;, &quot;2&quot;);
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        fs.copyFromLocalFile(
            new Path(&quot;D:/test.txt&quot;),
            new Path(&quot;/test/hdfs/demo/priority_test.txt&quot;)
        );
        fs.close();
    }
javaIO 流方式:文件上传与下载HdfsClient.java · 33 行

底层流操作:用 FSDataOutputStream 写 HDFS、FSDataInputStream 读 HDFS,通过 IOUtils.copyBytes 完成流拷贝。

    // IO 流方式上传
    @Test
    public void testUploadByIO() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        FileInputStream in = new FileInputStream(&quot;D:/test.txt&quot;);
        FSDataOutputStream out = fs.create(
            new Path(&quot;/test/hdfs/demo/io_upload.txt&quot;)
        );
        IOUtils.copyBytes(in, out, conf);
        IOUtils.closeStream(in);
        IOUtils.closeStream(out);
        fs.close();
    }

    // IO 流方式下载
    @Test
    public void testDownloadByIO() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        FSDataInputStream in = fs.open(
            new Path(&quot;/test/hdfs/demo/io_upload.txt&quot;)
        );
        FileOutputStream out = new FileOutputStream(&quot;D:/io_download.txt&quot;);
        IOUtils.copyBytes(in, out, conf);
        IOUtils.closeStream(in);
        IOUtils.closeStream(out);
        fs.close();
    }
java数据块读取:按块偏移定位(seek)HdfsClient.java · 38 行

演示 HDFS 块的概念。FSDataInputStream 支持 seek() 跳到指定偏移,每块 128MB。testReadFileSeek1 读前 128MB,testReadFileSeek2 从 128MB 位置开始读。

    // 读取第一块(前 128MB)
    @Test
    public void testReadFileSeek1() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        FSDataInputStream fis = fs.open(
            new Path(&quot;/test/hdfs/demo/test.txt&quot;)
        );
        FileOutputStream fos = new FileOutputStream(&quot;D:/test.txt.part1&quot;);
        byte[] buf = new byte[1024];
        for (int i = 0; i &lt; 1024 * 128; i++) {
            fis.read(buf);
            fos.write(buf);
        }
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);
        fs.close();
    }

    // 读取第二块(从 128MB 位置 seek)
    @Test
    public void testReadFileSeek2() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        FSDataInputStream fis = fs.open(
            new Path(&quot;/test/hdfs/demo/test.txt&quot;)
        );
        FileOutputStream fos = new FileOutputStream(&quot;D:/test.txt.part2&quot;);
        fis.seek(1024 * 1024 * 128);
        IOUtils.copyBytes(fis, fos, conf);
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);
        fs.close();
    }
java文件详情与块位置追踪(元数据读取)HdfsClient.java · 26 行

递归遍历目录下所有文件,输出文件名、大小、权限、所有者,以及每个数据块的偏移量、长度和数据节点位置。

    // 递归查看文件详情(含块所在主机)
    @Test
    public void testFileDetailWithBlocks() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(
            new URI(&quot;hdfs://192.168.88.100:9000&quot;), conf, &quot;root&quot;
        );
        RemoteIterator&lt;LocatedFileStatus&gt; listFiles =
            fs.listFiles(new Path(&quot;/test/hdfs/demo&quot;), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus status = listFiles.next();
            System.out.println(&quot;路径:&quot; + status.getPath());
            System.out.println(&quot;大小:&quot; + status.getLen() + &quot; 字节&quot;);
            System.out.println(&quot;权限:&quot; + status.getPermission());
            System.out.println(&quot;所有者:&quot; + status.getOwner());

            BlockLocation[] blocks = status.getBlockLocations();
            for (BlockLocation blk : blocks) {
                System.out.println(&quot;  块偏移:&quot; + blk.getOffset() +
                    &quot;,长度:&quot; + blk.getLength());
                System.out.println(&quot;  DataNode:&quot; +
                    String.join(&quot;,&quot;, blk.getHosts()));
            }
        }
        fs.close();
    }
📁 源文件清单GitHub 仓库 ↗
路径说明行数
pom.xmlMaven 项目配置(Hadoop 3.3.4 + JUnit 4)45
src/main/resources/hdfs-site.xmlHDFS 客户端配置(副本数 = 1)8
src/main/java/com/atguigu/hdfs/HdfsClient.javaHDFS 客户端 11 个操作完整实现262
网站智能助手
💬 和我聊聊
🤖
你好呀 👋 有什么想聊的?