HDFS 05 - HDFS 常用的 Java API 操作
0 - 配置 Hadoop 环境(Windows系统)
下述步骤适用于 Windows 系统,其他系统可忽略。
在 Windows 系统直接运行 Hadoop 相关代码,会提示缺少 winutils.exe
和 hadoop.dll
文件:
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
原因:通过代码访问 Hadoop 集群,本地开发环境相当于 Hadoop 客户端,需要有 Hadoop 相关软件才可正常运行。
配置步骤:
1)到 https://github.com/cdarlint/winutils 下载与集群版本相匹配的文件夹,然后将此文件夹拷贝到没有中文和空格的路径下,比如 D:\software\hadoop-3.2.1
;
2)在 Windows 的环境变量中添加 HADOOP_HOME
,值为上面的路径,并将 %HADOOP_HOME%\bin
添加到 path
中;
3)把上述文件夹 bin目录下的 hadoop.dll
文件拷贝到系统盘 C:\Windows\System32
目录;
4)重启 Windows 电脑。
1 - 导入 Maven 依赖
鉴于篇幅有限,相关 Maven 依赖请参见:《https://github.com/healchow/bigdata-study/blob/main/pom.xml》
2 - 常用类介绍
通过 Java API 操作 HDFS,主要涉及以下 class:
1)Configuration
主要用来封装客户端 / 服务端的配置。
2)FileSystem
这个类的对象是一个文件系统对象,可以用该对象的一些方法来对文件进行操作。
可通过静态方法获得该对象:
// 通过 conf 中的 “fs.defaultFS” 参数的值来确定文件系统的具体类型
FileSystem fs = FileSystem.get(conf);
如果代码中没有指定 fs.defaultFS
,并且工程的 ClassPath 下也没有相应的配置,此参数的默认值就由 Hadoop Jar 包中的 core-default.xml
文件来确定:
默认值是 file:///
,获取的不是 DistributedFileSystem 的实例,而是一个本地文件系统的客户端对象。
3 - 常见 API 操作
3.1 获取文件系统(重要)
方式1:FileSystem.get(conf)
/**
* 获取 FileSystem - FileSystem.get()
*/
@Test
public void testGetFileSystem1() throws IOException {
// 创建 Configuration 对象
Configuration conf = new Configuration();
// 指定文件系统类型
conf.set("fs.defaultFS", "hdfs://hadoop:9000");
// 获取指定的文件系统
FileSystem fileSystem = FileSystem.get(conf);
// FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration());
// 结果:DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1219793882_1, ugi=healchow (auth:SIMPLE)]]
System.out.println(fileSystem);
// 关闭文件系统
fileSystem.close();
}
方式2:FileSystem.newInstance(conf)
/**
* 获取 FileSystem - FileSystem.newInstance()
*/
@Test
public void testGetFileSystem2() throws IOException {
// 创建 Configuration 对象
Configuration conf = new Configuration();
// 指定文件系统类型
conf.set("fs.defaultFS", "hdfs://hadoop:9000");
// 获取指定的文件系统
FileSystem fileSystem = FileSystem.newInstance(conf);
// FileSystem fileSystem = FileSystem.newInstance(new URI("hdfs://hadoop:9000"), new Configuration());
System.out.println(fileSystem);
fileSystem.close();
}
3.2 创建目录、写入文件
/**
* 通过 HDFS URL 创建目录、写入文件
*/
@Test
public void testPutFile() throws IOException, URISyntaxException {
// 创建测试目录(可创建多级目录)
FileSystem fileSystem = FileSystem.newInstance(new URI("hdfs://hadoop:9000"), new Configuration());
boolean result = fileSystem.mkdirs(new Path("/test/input"));
System.out.println("mkdir result: " + result);
// 创建文件,若存在则覆盖,返回的是写入文件的输出流
FSDataOutputStream outputStream = fileSystem.create(new Path("/test/input/hello.txt"), true);
String content = "hello,hadoop\nhello,hdfs";
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
// 关闭流(不抛出异常)
IOUtils.closeQuietly(outputStream);
}
3.3 上传文件
/**
* 向 HDFS 上传文件 - copyFromLocalFile()
*/
@Test
public void testUploadFile() throws URISyntaxException, IOException {
// 获取 FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration());
// 从本地上传文件,两个参数都要指定到具体的文件
fileSystem.copyFromLocalFile(new Path("/Users/healchow/bigdata/core-site.xml"),
new Path("/test/upload/core-site.xml"));
// 关闭FileSystem
fileSystem.close();
}
3.4 下载文件
HDFS URL 打开 InputStream 的方式:
/**
* 通过 HDFS URL 获取文件并下载 - IOUtils.copy() 方法
*/
@Test
public void testDownFileByUrl() throws IOException {
// 注册 HDFS URL
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
// 获取 HDFS 文件的输入流
InputStream inputStream = new URL("hdfs://hadoop:9000/test/input/hello.txt").openStream();
// 获取本地文件的输出流(绝对路径,文件夹必须存在)
FileOutputStream outputStream = new FileOutputStream("/Users/healchow/bigdata/test/hello.txt");
// 拷贝文件
IOUtils.copy(inputStream, outputStream);
// 关闭流(不抛出异常)
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
FileSystem 打开 InputStream 的方式:
/**
* 通过 FileSystem 获取文件并下载 - IOUtils.copy() 方法
*/
@Test
public void testDownloadFile() throws URISyntaxException, IOException {
// 获取 FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration());
// 获取 HDFS 文件的输入流
FSDataInputStream inputStream = fileSystem.open(new Path("/test/input/hello.txt"));
// 获取本地文件的输出流
FileOutputStream outputStream = new FileOutputStream("/Users/healchow/bigdata/test/hello1.txt");
// 拷贝文件
IOUtils.copy(inputStream, outputStream);
// 关闭流
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
fileSystem.close();
}
FileSystem#copyToLocalFile() 的方式:
/**
* 通过 FileSystem 获取文件并下载 - copyToLocalFile() 方法
*/
@Test
public void testDownloadFileByCopyTo() throws URISyntaxException, IOException, InterruptedException {
// 获取 FileSystem
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration(), "root");
// copyToLocalFile 拷贝文件到本地,会下载 CRC 校验文件
fileSystem.copyToLocalFile(new Path("/test/input/hello.txt"),
new Path("/Users/healchow/bigdata/test/hello2.txt"));
// 关闭 FileSystem
fileSystem.close();
}
3.5 遍历 HDFS 的文件
/**
* 遍历 HDFS 文件
*/
@Test
public void testListFiles() throws URISyntaxException, IOException {
// 获取FileSystem实例
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration());
// 递归获取 /test 目录下所有的文件信息
RemoteIterator<LocatedFileStatus> iterator = fileSystem.listFiles(new Path("/test"), true);
// 遍历文件
while (iterator.hasNext()) {
LocatedFileStatus fileStatus = iterator.next();
// 获取文件的绝对路径:hdfs://hadoop:9000/xxx
System.out.println("filePath: " + fileStatus.getPath());
// 文件的 block 信息
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
String[] hosts = blockLocation.getHosts();
for (String host : hosts) {
System.out.println("blockHost: " + host);
}
}
System.out.println("blockSize: " + blockLocations.length);
}
}
4 - HDFS 的访问权限控制
从上面的 API 练习,不难发现:只要得到了 HDFS 的 URL(即 fs.defaultFS
)配置项,能访问到集群的任何人都能读写 HDFS 上的数据,这会导致数据的安全性完全无法得到保障。
为了解决这个问题,HDFS 有 访问权限控制的方法,只有通过认证的用户,按照其所拥有的权限,读取或写入某些目录下的文件。
开启 HDFS 访问权限控制的方法如下:
1)停止 HDFS 集群:
cd ~/bigdata/hadoop-3.2.1
sbin/stop-dfs.sh
2)修改 ~/bigdata/hadoop-3.2.1/etc/hadoop/hdfs-site.xml
中的配置,添加如下内容:
<property>
<name>dfs.permissions.enabled</name>
<value>true</value>
</property>
4)重启 HDFS 集群:
cd ~/bigdata/hadoop-3.2.1
sbin/start-dfs.sh
5)上传测试文件到 HDFS 集群,这里将上传后的一个文件的权限修改为 600
,即只能所有者读写:
cd ~/bigdata/hadoop-3.2.1/etc/hadoop
hdfs dfs -mkdir /test/config
hdfs dfs -put *.xml /test/config
hdfs dfs -chmod 600 /test/config/core-site.xml
6)通过代码下载文件:
/**
* 通过下载文件,测试访问权限控制
*/
@Test
public void testAccessControl() throws Exception {
// 开启权限控制后,当前用户(启动 NameNode 的用户)应当能成功访问
// FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration());
// 伪造其他用户访问,应当访问失败
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop:9000"), new Configuration(), "testuser");
fileSystem.copyToLocalFile(new Path("/test/config/core-site.xml"),
new Path("file:/Users/healchow/bigdata/core-site.xml"));
fileSystem.close();
}
说明:本地测试失败。无论用哪个用户,访问都成功。
查了很多资料,没有说得通的。劳烦有了解的大佬,留言告知我呀
版权声明
出处:博客园-瘦风的南墙(https://www.cnblogs.com/shoufeng)
感谢阅读,公众号 「瘦风的南墙」 ,手机端阅读更佳,还有其他福利和心得输出,欢迎扫码关注
本文版权归博主所有,欢迎转载,但 [必须在页面明显位置标明原文链接],否则博主保留追究相关人士法律责任的权利。
HDFS 05 - HDFS 常用的 Java API 操作的更多相关文章
- HBase常用的JAVA API操作
为了方便以后查看,总结了一些常用的java操作hbase的代码: package com.mcq; import static org.hamcrest.CoreMatchers.describedA ...
- 使用Java API操作HDFS文件系统
使用Junit封装HFDS import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org ...
- Hadoop之HDFS(三)HDFS的JAVA API操作
HDFS的JAVA API操作 HDFS 在生产应用中主要是客户端的开发,其核心步骤是从 HDFS 提供的 api中构造一个 HDFS 的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS ...
- 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\
1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...
- hive-通过Java API操作
通过Java API操作hive,算是测试hive第三种对外接口 测试hive 服务启动 package org.admln.hive; import java.sql.SQLException; i ...
- hadoop2-HBase的Java API操作
Hbase提供了丰富的Java API,以及线程池操作,下面我用线程池来展示一下使用Java API操作Hbase. 项目结构如下: 我使用的Hbase的版本是 hbase-0.98.9-hadoop ...
- Kafka系列三 java API操作
使用java API操作kafka 1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xs ...
- MongoDB Java API操作很全的整理
MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写,一般生产上建议以共享分片的形式来部署. 但是MongoDB官方也提供了其它语言的客户端操作API.如下图所示: 提供了C.C++ ...
- zookeeper的java api操作
zookeeper的java api操作 创建会话: Zookeeper(String connectString,int sessionTimeout,Watcher watcher) Zookee ...
随机推荐
- Linux防火墙放行端口
添加放行端口 firewall-cmd --zone=public --add-port=端口号/tcp --permanent 重启防火墙 systemctl restart firewalld.s ...
- 一句 Task.Result 就死锁, 这代码还怎么写?
一:背景 1. 讲故事 前些天把 .NET 高级调试 方面的文章索引到 github 的过程中,发现了一个有意思的评论,详见 文章,截图如下: 大概就是说在 Winform 的主线程下执行 Task. ...
- hdu 2072 1106学一波字符串分割,C语言与C++两种方法
hdu2072:题意:输出给定字符串中的单词数(一个句子中可能有两个相同的单词),这里的思想是把每个单词取出来,放入set(这个集合容器中不允许有相同的元素)中,最后输出该集合的大小即可. 现在的问题 ...
- 安装MySQL后,需要调整的10个性能配置项
本文翻译自 Percona 官方博客,适用于 MySQL 5.6 及 5.7 版本. 作者:Stephane Combaudon 原文: https://www.percona.com/blog/20 ...
- MySQL分区表最佳实践
前言: 分区是一种表的设计模式,通俗地讲表分区是将一大表,根据条件分割成若干个小表.但是对于应用程序来讲,分区的表和没有分区的表是一样的.换句话来讲,分区对于应用是透明的,只是数据库对于数据的重新整理 ...
- 【近取 Key】Alpha - v1.0 测试报告
Bug 前端 主页.登录.注册.导航 bug说明 修复方法 修复结果 导航栏有时不显示用户姓名 修改用户信息的获取逻辑与存储方式 成功 展示词图界面导航栏居右失败 在组件中增加自适应相关设置 成功 用 ...
- 1. Java概述
1.1 Java语言背景介绍(了解) 语言:人与人交流沟通的表达方式. 计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言. Java语言是美国Sun公司(Stanford University ...
- sed -i 's/Search_String/Replacement_String/g' Input_File sed详细手册
本文列出的十五个例子可以帮助你掌握 sed 命令.如果要使用 sed 命令删除文件中的行,去下面的文章.注意:由于这是一篇演示文章,我们使用不带 -i 选项的 sed 命令,该选项会在 Linux 终 ...
- JavaEE 三层架构模式
什么是架构模式 要理解三层架构模式,我们得先搞清楚什么是架构模式.(这里说的架构模式是针对后端开发) 所谓架构就是系统最高级别的设计,一个系统特别复杂时才需要架构设计,如果只是开发一个很小程序,就谈不 ...
- 9.2-3 pstree & pgrep
9.2 pstree:显示进程状态树 pstree命令以树形结构显示进程和进程之间的关系. 如果不指定进程的PID号,或者不指定用户名称,则会以init进程为根进程,显示系统的所有进程 ...