HDFS的JAVA API操作
HDFS在生产应用中主要是客户端的开发,其核心步骤是从HDFS提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件。
主要类
Configuration
其实就是我们Java项目的core-site.xml文件,就像安装Hadoop时要配置core-site.xml文件一样,我们的java项目也要正确配置才能连接Hadoop。
-
在实例化的时候,Configuration类会自动读取:
core-default.xml(不需要我们增加)
core-site.xml(我们配置)
其实和Hadoop配置一样,core-site没配置的时候,就取默认的core-default.xml里的配置。
Configuration类除了自动读取配置文件以外,还提供了一系列操作配置的方法,可以在程序里修改配置(而不是修改配置文件)。
FileSystem
类似Hadoop shell,对文件操作,通过该类可以对文件进行CRUD。
和Hadoop shell一样,可以对Hadoop支持的文件系统操作。
-
无参构造器是protected的,一般使用get方法获取该类的对象。
get方法获取对象有4种重写,一般我们只会用两种,见下文。
示例代码
1.建立Maven项目,导入基本依赖
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
2.在resources文件夹下建立core-site.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://192.168.98.129:9000</value>
</property>
</configuration>
备注:Hadoop中似乎已经封装了log4j日志,可以把log4j.properties也添加进去,否则log4j就一直报找不到配置文件。不加也可以。
3.建立测试类
1.基本使用
package com.rzp.hdfs;
//注意导入的包一定要正确
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class TestHDFSClient {
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
//实例化Configuration
Configuration conf = new Configuration();
//使用root用户登录,如果不写,会用当前程序运行环境的用户登录,比如windows的Administrator用户导致报错
System.setProperty("HADOOP_USER_NAME","root");
//查看core-site.xml文件中fs.defaultFS的值
System.out.println(conf.get("fs.defaultFS"));
//第一种获取FileSystem的对象的方式,通过get(conf)方法,
FileSystem fs1 = FileSystem.get(conf);
//在根目录下增加/helloByJava文件夹
fs1.create(new Path("/helloByJava"));
//关闭连接
fs1.close;
}
}
测试结果:输出了配置中的值,Hadoop根目录下也增加对应文件夹,说明连接成功。
2.通过set方法,修改conf的参数
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException { Configuration conf = new Configuration();
//set方法,修改conf的参数,可以把core-site.xml文件删除测试
conf.set("fs.defaultFS","hdfs://192.168.98.129:9000"); System.setProperty("HADOOP_USER_NAME","root");
System.out.println(conf.get("fs.defaultFS"));
FileSystem fs1 = FileSystem.get(conf);
fs1.create(new Path("/helloByJava"));
}
3.第二种FileSystem实例化的方法,指定用户的get方法
public void test1() throws URISyntaxException, IOException, InterruptedException {
Configuration conf = new Configuration();
//直接指定操作该对象的用户名
FileSystem fs1 = FileSystem.get(new URI("hdfs://192.168.98.129:9000"),conf,"root");
fs1.create(new Path("/helloByJava"));
//关闭连接
fs1.close;
}
FileSystem的主要方法
copyToLocalFile--下载文件到本地
@Test
public void test2() throws URISyntaxException, IOException, InterruptedException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.98.129:9000"),conf,"root");
//第一个地址是Hadoop路径,第二个地址是本地路径
fs.copyToLocalFile(new Path("/install.log.syslog"),new Path("./log"));
}
copyFromLocalFile 上传文件
static FileSystem fs = null;
public static void init() throws Exception {
Configuration conf = new Configuration();
fs = FileSystem.get(new URI("hdfs://192.168.98.129:9000"), conf, "root");
}
@Test
public void testAddFileToHdfs() throws Exception {
HdfsClient.init();
//第一个地址是本地路径,第二个地址是Hadoop的路径
fs.copyFromLocalFile(new Path("D:\\log.log"), new Path("/")); fs.close();
}
文件CRUD
@Test
public void testMkdirAndDeleteAndRename() throws Exception {
HdfsClient.init(); // 创建目录
fs.mkdirs(new Path("/a1/b1/c1"));
fs.mkdirs(new Path("/d1"));
// 删除文件,如果是非空文件夹,参数2必须给值true
fs.delete(new Path("/a1"), true);
// 重命名文件或文件夹
fs.rename(new Path("/d1"), new Path("/d2"));
fs.close();
}
查看目录(该部分笔者还没梳理完,所以没有注释,梳理完再修改)
/**
* 查看目录信息,只显示文件
*
* @throws IOException
* @throws IllegalArgumentException
* @throws FileNotFoundException
*/
@Test
public void testListFiles() throws Exception {
HdfsClient.init();
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while (listFiles.hasNext()) {
LocatedFileStatus fileStatus = listFiles.next();
System.out.println(fileStatus.getPath().getName());
System.out.println(fileStatus.getBlockSize());
System.out.println(fileStatus.getPermission());
System.out.println(fileStatus.getLen());
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation bl : blockLocations) {
System.out.println("block-length:" + bl.getLength() + "--" + "block-offset:" + bl.getOffset());
String[] hosts = bl.getHosts();
for (String host : hosts) {
System.out.println(host);
}
}
System.out.println("--------------打印的分割线--------------");
}
}
/**
* 查看文件及文件夹信息
*
* @throws IOException
* @throws IllegalArgumentException
* @throws FileNotFoundException
*/
@Test
public void testListAll() throws Exception {
HdfsClient.init();
FileStatus[] listStatus = fs.listStatus(new Path("/"));
String flag = "";
for (FileStatus fstatus : listStatus) {
if (fstatus.isFile()) {
flag = "f-- ";
} else {
flag = "d-- ";
}
System.out.println(flag + fstatus.getPath().getName());
System.out.println(fstatus.getPermission());
}
}