1、通过Java实现HDFS操作及访问
接下来使用Java进行HDFS客户端的操作。
①要用Java操作分布式文件系统,首先找到操作文档。
②在hadoop官网Apache Hadoop 上找到版本列表
③进入Apache Hadoop 找到对应的版本。
④进入 Apache Hadoop 找到操作文档
⑤进入 Hadoop – Apache Hadoop 3.1.2 拖到最后,找到Java API docs
⑥进入 Apache Hadoop Main 3.1.2 API
这里提供Java操作HDFS的客户端。可以通过Java面向对象的方式,使用类创建对象对分布式文件系统进行操作。
2、IntelliJ IDEA
安装ideaIU-2018.3.exe、ideaIC-2021.1.exe安装过程略。
如果需要激活码,可以关注公众号“Java团长”。回复激活码,即可获取。
注意:如果在激活时intellij IDEA激活码出现"this licensee K03CHKJCFT has been cancelled",则需要:
第一步:修改hosts文件
路径为:C:\Windows\System32\drivers\etc\hosts
并将“0**.0.0.0 account.jetbrains.com**”加至最后一行
第二步,打开IDEA,将激活码填入Activation code处即可激活成功。
3、maven软件安装与配置
①新建项目前,要先做一些准备,比如安装好Java所需的软件。
②确保在cmd输入 javac -version时能出现Java的版本信息。
③另外,需要安装maven软件。
其中 apache-maven-3.5.2.zip是maven安装包;maven_repository.zip是jar包仓库。
考虑放到不带中文的路径下,直接解压。比如解压到:
D:\software\hdfs\apache-maven-3.5.2 D:\software\hdfs\maven_repository
编辑 D:\software\hdfs\apache-maven-3.5.2\conf\settings.xml 文件,并修改jar包仓库的路径为前面对应的路径。
|
这样就完成了maven的配置。
另外,还要设置环境变量。在系统环境变量中配置MAVEN_HOME为D:\software\hdfs\apache-maven-3.5.2。并把 %MAVEN_HOME%\bin 添加到 PATH 路径中。
并通过cmd命令行进行测试
mvn -v |
出现上面的内容,说明maven环境在Windows上已经配置好了。
创建子目录 D:\android\ideaProject_bigData 用于存放工程。
4、新建maven项目并关联maven插件
点击Create New Project
左边选择Maven,使用本地的JDK1.8(必须1.8),注意不要勾上Create from archetype。然后点击Next
设置在哪个路径下安装hdfs_api。比如说放到刚才创建的D:\android\ideaProject_bigData目录。项目名跟文件夹名称最好一致。
GroupId是域名的倒写。比如域名是www.baidu.com,则GroupId就要写com.baidu.www。
比如这里就写com.zhang。
ArtifactId是项目的名称。比如hdfs_api,然后点击Finish
打开界面后,jar包会自动导入。留意External Libraries目录。现在maven项目就构建完成了。
这里一般需要:
配置Maven。打开File——Settings,找到Build, Execution, Deployment——Build Tools——Maven,设置maven的依赖目录,注意修改settings file后,Local repository会自动检测到修改过的本地仓库路径的。
接下来导入项目所需要的依赖。
5、导入项目所需要的依赖
把下面的内容拷贝到 pom.xml 文件中。(通常只需要替换properties部分)
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
这些是创建项目时设定的内容。
配置好这些以后,在2020.1之前的版本会自动导入相关的jar包。但在2020.1后的版本,为防止pom更新时,MAVEN自动导包时卡死的问题,取消了自动导包机制。而是增加了导入按钮的快捷键。
当修改了maven依赖后,当前pom文件右上角会出现一个maven小图标;点一下该图标即可更新依赖。生成的依赖包;这些jar包就是从jar包仓库maven_repository中来的。如果发现依赖坐标的地方出现红色,或者导入不完整,可以检查一下配置的路径,看是否正确。其中,jar包是人家给你写好的一些代码,并打包给你。有了这些jar包,就可以进行调用,比如junit测试。
6、编写Java代码——向HDFS文件系统创建文件夹
在src/main/java 目录下新建 package,目的为了让代码更好的分类。假设package名称为com.zhang。
创建类HdfsClientAppTest。
话说写个psvm,然后按一下Tab键,就可以生成
public static void main(String[] args) { |
src/main/java/com/zhang/HdfsClientAppTest.java
package com.zhang; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org.junit.Test; import java.io.IOException; import java.net.URI; |
/** * */ public class HdfsClientAppTest { public static void main(String[] args) throws IOException { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); configuration.set("fs.defaultFS","hdfs://192.168.110.101:8020"); //2.获取FileSystem对象 FileSystem fileSystem = FileSystem.get(configuration); fileSystem.mkdirs(new Path("/100_3")); //3.关闭资源 fileSystem.close(); } |
注意使用的类,Configuration和FileSystem都有多个选择。这里选择的是:
另外,100_3是在分布式文件系统中创建的文件夹。
启动分布式文件系统。使用上面的java代码往分布式文件系统中创建文件夹100_3。
另外,拷贝 log4j.properties文件到src/main/resources目录下。
在IDEA上运行该程序。执行完毕后可以在 http://192.168.110.101:50070/explorer.html 中看到100_3的目录了。
注意:运行Java程序时,如果出现
参考:maven hadoop 3.x HADOOP_HOME and hadoop.home.dir are unset Not implemented by the WebHdfsFileSystem FileSystem implementation - tele - 博客园
如果下载的过程中出现了 HADOOP_HOME and hadoop.home.dir are unset,那么就说明你没有配置windows本地的hadoop环境变量.你可能会想我是远程调用linux下的hadoop,与我本地的hadoop有什么关系?如果你的操作只对远程的hadoop生效,如上传,创建目录,文件改名(写)等那么你是不需要在windows本地配置hadoop的,可一旦涉及到下载(读),hadoop内部的缓存机制要求本地也必须有hadoop,于是也会出现HADOOP_HOME and hadoop.home.dir are unset,解决办法配置HADOOP_HOME并加入%HADOOP_HOME%\bin到PATH中,之后测试下hadoop version命令,有效的话重启你的eclipse/myeclipse,但这还不够,windows下的hadoop还需要winutils.exe,否则会报Could not locate Hadoop executable: xxxx\winutils.exe
可以在GitHub - steveloughran/winutils: Windows binaries for Hadoop versions (built from the git commit ID used for the ASF relase) 下载winutils,找hadoop-3.0.0的。
先把原来的hadoop-3.1.2.tar.gz在Windows上解压,得到 D:\software\hdfs\hadoop-3.1.2 目录。并把该路径设置到环境变量HADOOP_HOME中。
再把 %HADOOP_HOME%\bin 添加到环境变量 PATH 中。
然后拷贝 winutils\hadoop-3.0.0\bin\winutils.exe 文件到这个bin目录下。
另外,也可以通过如下代码往HDFS文件系统中创建文件夹
@Test public void getHdfsClient2() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "root" ); fileSystem.mkdirs(new Path("/100_2")); fileSystem.close(); } |
在IDEA上运行该程序。执行完毕后可以在 http://192.168.110.101:50070/explorer.html 中看到100_2的目录了。
7、编写Java代码——文件上传
通过如下代码往HDFS文件系统中上传文件(假设本地文件为d:\tmp\hello.txt,上传到HDFS的/100_1/目录下,注意该目录原本并不存在)
/** * 实现一个文件的上传 */ @Test public void putFileToHDFS() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "root" ); Path srcPath = new Path("D:\\tmp\\hello.txt"); Path destPath = new Path("/100_1/hello.txt"); fileSystem.copyFromLocalFile(srcPath,destPath); fileSystem.close();
} |
点击100_1进入后目录后
/** * 伪造用户,实现一个文件的上传 */ @Test public void putFileToHDFS2() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "zhang" ); Path srcPath = new Path("D:\\tmp\\hello.txt"); Path destPath = new Path("/100_1/hello2.txt"); fileSystem.copyFromLocalFile(srcPath,destPath); fileSystem.close(); } |
/** * 设置副本数,实现一个文件的上传 */ @Test public void putFileToHDFS3() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); configuration.set("dfs.replication","2"); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "zhang" ); Path srcPath = new Path("D:\\tmp\\hello.txt"); Path destPath = new Path("/100_2/hello3.txt"); fileSystem.copyFromLocalFile(srcPath,destPath); fileSystem.close(); } } |
8、编写Java代码——删除文件夹
/** * 删除文件夹 */ @Test public void deleteAtHDFS() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); configuration.set("dfs.replication","2"); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "zhang" ); fileSystem.delete(new Path("/100_3"),true); fileSystem.close(); } |
删除前和删除后对比
9、编写Java代码——重命名文件
@Test public void renameAtHDFS() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); configuration.set("dfs.replication","2"); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "zhang" ); fileSystem.rename(new Path("/100_2/hello3.txt"),new Path("/100_2/hello4.txt")); fileSystem.close(); } |
重命名前与重命名后对比
10、编写Java代码——遍历文件夹
/** * 遍历文件,获取所有文件信息 */ @Test public void readListAtHDFS() throws Exception { //向HDFS文件系统创建文件夹 //1.新建一个Configuration对象 //idea的智能提示alt + enter Configuration configuration = new Configuration(); configuration.set("dfs.replication", "2"); FileSystem fileSystem = FileSystem.get( new URI("hdfs://192.168.110.101:8020"), configuration, "root" ); RemoteIterator while (iterator.hasNext()) { LocatedFileStatus fileStatus = iterator.next(); System.out.println("权限=" + fileStatus.getPermission()); System.out.println("文件名" + fileStatus.getPath().getName()); System.out.println("文件大小=" + fileStatus.getLen()); System.out.println("文件副本数=" + fileStatus.getReplication()); //获取块的位置信息 BlockLocation[] blockLocations = fileStatus.getBlockLocations(); for (BlockLocation blockLocation : blockLocations) { System.out.println("块的偏移量=" + blockLocation.getOffset()); System.out.println("块大小=" + blockLocation.getLength()); String hosts[] = blockLocation.getHosts(); for (String host : hosts) { System.out.println("副本存储的主机位置=" + host); } System.out.println("块信息---------------"); } System.out.println("文件信息-----------------------------"); } fileSystem.close(); } } |
留意终端的输出结果
注意hello4.txt的副本是2个。