HDFS的API操作

142 阅读3分钟

客户端环境准备

下载Windows环境所需的bin

github.com/s911415/apa…

将下载好的文件复制到没有中文的目录下

图片.png

配置HADOOP_HOME环境变量

图片.png

图片.png

注意:如果环境变量不起作用,可以重启电脑试试。

验证 Hadoop 环境变量是否正常。双击 winutils.exe,如果报如下错误。说明缺少微软运行库(正版系统往往有这个问题)。将对应的微软运行库安装包安装即可。

图片.png

通常,一闪而过说明是正常的

在 IDEA 中创建一个 Maven 工程 HdfsClientDemo,并导入相应的依赖坐标+日志添加

图片.png

<dependencies>  
    <dependency>  
        <groupId>org.apache.hadoop</groupId>  
        <artifactId>hadoop-client</artifactId>  
        <version>3.1.3</version>  
    </dependency>  

    <dependency>  
        <groupId>junit</groupId>  
        <artifactId>junit</artifactId>  
        <version>4.12</version>  
    </dependency>  

    <dependency>  
        <groupId>org.slf4j</groupId>  
        <artifactId>slf4j-log4j12</artifactId>  
        <version>1.7.30</version>  
    </dependency>  
</dependencies>

在项目的 src/main/resources 目录下,新建一个文件,命名为“log4j.properties”,在文件中填入

创建 HdfsClient 类

客户端代码常用套路

  1. 获取一个客户端对象
  2. 执行相关的操作命令
  3. 关闭资源
package com.muyi.hdfs;

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

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;


/**
 * Created with IntelliJ IDEA.
 *
 * @author: 慕逸
 * @date: 2024-11-15 10:11
 * @description: HDFS API测试
 * @version: 1.0
 */
public class HdfsClient {
    @Test
    public void testMkdir() throws URISyntaxException, IOException {
        //连接的集群nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        //创建一个配置文件
        Configuration configuration = new Configuration();
        // 获取客户端对象
        FileSystem fs = FileSystem.get(uri, configuration);

        //创建一个文件夹
        boolean mkdirs = fs.mkdirs(new Path("/xiyou/huaguoshan"));
        System.out.println(mkdirs);


        //关闭资源
        fs.close();
    }
}

但是,这里报错了!

图片.png

这个错误信息 org.apache.hadoop.security.AccessControlException: Permission denied 表明用户 Administrator 在尝试对 Hadoop 分布式文件系统(HDFS)的根目录 / 进行写操作时,因为权限不足而被拒绝。

添加用户名即可解决这个问题

//设置用户名  
String user = "muyi";  
// 获取客户端对象  
FileSystem fs = FileSystem.get(uri, configuration, user);

图片.png

图片.png

创建成功

封装连接客户端和关闭客户端的代码

Ctrl+Alt+F可以在idea中将变量升级为全局变量

 private FileSystem fs;
    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        //连接的集群nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        //创建一个配置文件
        Configuration configuration = new Configuration();
        //设置用户名
        String user = "muyi";
        // 获取客户端对象
        fs = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        fs.close();
    }

    @Test
    public void testMkdir() throws URISyntaxException, IOException, InterruptedException {


        //创建一个文件夹
        boolean mkdirs = fs.mkdirs(new Path("/xiyou/huaguoshan"));
        System.out.println(mkdirs);


        //关闭资源
        fs.close();
    }

创建目录

/**  
* 创建目录  
* @throws URISyntaxException  
* @throws IOException  
* @throws InterruptedException  
*/  
@Test  
public void testMkdir() throws URISyntaxException, IOException, InterruptedException {  
    //创建一个文件夹  
    boolean mkdirs = fs.mkdirs(new Path("/xiyou/huaguoshan1"));  
    System.out.println(mkdirs);  
}

上传

// 上传文件到HDFS  
@Test  
public void testPut() throws IOException {  
    /*  
    * 参数1:表示删除原始数据  
    * 参数2:是否覆盖原始数据  
    * 参数3:原数据路径  
    * 参数4:目标路径  
    */  
    fs.copyFromLocalFile(false, false, new Path("E:\\Study\\code\\hadoop\\sunwukong.txt"), new Path("/xiyou/huaguoshan"));  
}

图片.png

HDFS参数的优先级

<?xml version="1.0" encoding="UTF-8"?>  
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>  
<configuration>  
    <property>  
        <name>dfs.replication</name>  
        <value>1</value>  
    </property>  
</configuration>

图片.png

图片.png 参数优先级排序:(1)客户端代码中设置的值 >(2)ClassPath 下的用户自定义配置文 件 >(3)然后是服务器的自定义配置(xxx-site.xml)>(4)服务器的默认配置(xxx-default.xml)

文件下载

//文件下载  
@Test  
public void testGet() throws IOException {  
    /**  
    * 参数1: 原文件是否删除  
    * 参数2: 原文件路径HDFS  
    * 参数3: 目标地址路径Win  
    * 参数4: 是否开启本地校验  
    */  
    fs.copyToLocalFile(false,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("E:\\Study"),true);  
}

文件删除

// 文件删除  
@Test  
public void testRM() throws IOException {  
    /**  
    * 参数1: 要删除的文件路径  
    * 参数2: 是否递归删除  
    */  
    fs.delete(new Path("/jdk-8u212-linux-x64.tar.gz"), false); 
    
    // 删除空目录  
    fs.delete(new Path("/output2"), false);  
    // 删除非空目录  
    fs.delete(new Path("/output"), true);
}

文件的更名和移动

//文件的更名和移动  
@Test  
public void testmv() throws IOException {  
    fs.rename(new Path("/wcinput/word.txt"),new Path("/wcinput/test.txt"));  
    // 文件的移动和更名  
    fs.rename(new Path("/wcinput/test.txt"),new Path("/word.txt")); 
    
    // 目录更名  
    fs.rename(new Path("/wcinput"),new Path("/input"));
}

文件详情查看

查看文件名称、权限、长度、块信息

//文件详情查看  
@Test  
public void fileDetail() throws IOException {  
    RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);  
    while (listFiles.hasNext()) {  
        LocatedFileStatus fileStatus = listFiles.next();  
        System.out.println("============"+fileStatus.getPath()+"============");  
        System.out.println(fileStatus.getPermission()); // 权限  
        System.out.println(fileStatus.getOwner()); // 所属者  
        System.out.println(fileStatus.getGroup()); // 所属组  
        System.out.println(fileStatus.getLen()); // 文件大小  
        System.out.println(fileStatus.getModificationTime()); // 修改时间  
        System.out.println(fileStatus.getReplication()); // 副本数  
        System.out.println(fileStatus.getBlockSize()); // 块大小  
        System.out.println(fileStatus.getPath().getName()); // 文件名 
        
        // 获取文件块信息  
        BlockLocation[] blockLocations = fileStatus.getBlockLocations();  
        System.out.println(Arrays.toString(blockLocations));
    }  
}

图片.png

文件和文件夹判断

//文件和文件夹判断  
@Test  
public void testFile() throws IOException {  
    FileStatus[] listStatus = fs.listStatus(new Path("/"));  

    for (FileStatus status : listStatus) {  
        if (status.isFile()) {  
            System.out.println(status.getPath().getName()+"这是一个文件");  
        }else {  
            System.out.println(status.getPath().getName()+"这是一个目录");  
        }  
    }  
}