客户端环境准备
下载Windows环境所需的bin
将下载好的文件复制到没有中文的目录下
配置HADOOP_HOME环境变量
注意:如果环境变量不起作用,可以重启电脑试试。
验证 Hadoop 环境变量是否正常。双击 winutils.exe,如果报如下错误。说明缺少微软运行库(正版系统往往有这个问题)。将对应的微软运行库安装包安装即可。
通常,一闪而过说明是正常的
在 IDEA 中创建一个 Maven 工程 HdfsClientDemo,并导入相应的依赖坐标+日志添加
<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 类
客户端代码常用套路
- 获取一个客户端对象
- 执行相关的操作命令
- 关闭资源
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();
}
}
但是,这里报错了!
这个错误信息 org.apache.hadoop.security.AccessControlException: Permission denied 表明用户 Administrator 在尝试对 Hadoop 分布式文件系统(HDFS)的根目录 / 进行写操作时,因为权限不足而被拒绝。
添加用户名即可解决这个问题
//设置用户名
String user = "muyi";
// 获取客户端对象
FileSystem fs = FileSystem.get(uri, configuration, user);
创建成功
封装连接客户端和关闭客户端的代码
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"));
}
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>
参数优先级排序:(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));
}
}
文件和文件夹判断
//文件和文件夹判断
@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()+"这是一个目录");
}
}
}