这篇博客通过客户端代码实现文件上传、文件下载、文件夹删除、文件名更改、文件详情查看、文件和文件夹判断,主要目的是熟悉相关的API。

在进行API操作之前首先得做好客户端操作的相关准备和配置,具体参考HDFS客户端操作前期准备这篇博客。

一切准备就绪之后,就可以打开Eclipse进行代码的实现了。这里都是在HDFSClient类中进行实现的。

1. HDFS文件上传

1.1. 实现代码

	@Test
	public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
		
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 将本地文件上传至HDFS之中
		fs.copyFromLocalFile(new Path("G:/zzh.txt"), new Path("/zzh.txt"));
		
		// 3. 关闭文件系统
		fs.close();
	}

代码中,通过调用copyFromLocalFile()方法将本地文件上传到HDFS之中。

运行测试代码,通过浏览器查看,可以看到文件上传成功。

通过上面的图片可以发现这个文件默认的副本数为3,这也是HDFS默认的,那么如果我要修改这个副本数目该如何操作呢?首先想到的应该是通过设置集群的配置文件来改变副本数,这当然是可行的,但是这样一改变,以后所有的文件默认副本数都会变化了(都不是3了),所以这种方法这里暂不考虑,下面通过代码和改变项目配置文件来改变副本数。

1.2. 测试参数优先级

1.2.1. 通过改变项目配置文件来改变

在工程sr/main/resources/目录下新建hdfs-site.xml文件,并将下面的内容复制上去(其实这个文件也就是集群里面的配置文件):

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<property>
		<name>dfs.replication</name>
		<!-- 这里降副本数设置为1 -->
        <value>1</value>
	</property>
</configuration>

上传代码中的目标文件名称修改(这里我修改为了zzh1.txt),然后重新运行测试代码,可以发现副本数为1,如下图所示。

1.2.2. 通过代码改变

具体实现代码如下:

@Test
	public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
		
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		conf.set("dfs.replication", "2"); // 这里降副本数修改成2
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 将本地文件上传至HDFS之中
		fs.copyFromLocalFile(new Path("G:/zzh.txt"), new Path("/zzh2.txt"));
		
		// 3. 关闭文件系统
		fs.close();
	}

这里通过配置文件修改副本数,然后也修改了目的文件名,重新运行测试代码,其结果如下图所示。

1.2.3. 参数优先级

通过上面的一系列操作,如上面介绍过的“通过修改项目配置文件”和“代码实现”参数修改,可以知道通过代码实现参数的修改优先级是最高的,可以覆盖掉“通过修改项目配置文件”对参数的修改(如上面介绍的通过修改项目配置文件将副本数设置为1,而通过代码覆盖掉了可以直接设置成2),因此可以知道参数的优先级为:

客户端中设置的值 > 用户自定义配置文件 > 集群服务器中的配置

2. HDFS文件下载

这里实现将HDFS文件系统中的文件下载的本地客户端中,具体实现代码如下:

@Test
	@Test
	public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException {
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 将文件系统中的文件下载到本地电脑中
		fs.copyToLocalFile(new Path("/zzh2.txt"), new Path("G:/zzh2.txt"));
		
		// 3. 关闭文件系统
		fs.close();
	}

这里将文件系统中的zzh2.txt文件下载到本地指定位置。

可以看到可以除了指定要下载的文件,还多了一个crc文件检测文件,这个文件是自动产生的,如果不需要这个文件,可以在代码中使用另外一个方法fs.copyToLocalFile(delSrc, src, dst, useRawLocalFileSystem);。其中第4个参数就是是否开启文件校验的,设置为True也就不会产生crc文件了。

3. HDFS文件删除

这里将文件系统中的文件或者文件夹删除操作,具体代码如下所示:

	@Test
	public void testDelete() throws IOException, InterruptedException, URISyntaxException {
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 删除文件系统中的文件或者文件夹,第二个参数就是当要删除文件夹是就设置为True。
		fs.delete(new Path("/zzh"), true);
		
		// 3. 关闭文件系统
		fs.close();
	}

4. HDFS文件名更改

	@Test
	public void testRename() throws IOException, InterruptedException, URISyntaxException {
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 执行修改文件名操作
		fs.rename(new Path("/zzh.txt"), new Path("/zhangzh"));
		
		// 3. 关闭
		fs.close();
	}

将文件系统中的zzh.txt文件修改为了zhangzh

5. HDFS文件详情查看

	@Test
	public void testListFile() throws IOException, InterruptedException, URISyntaxException {
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 获取文件详情
		RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
		while(listFiles.hasNext()) {
			LocatedFileStatus status = listFiles.next();
			// 输出文件详情
			// 输出文件名
			System.out.println(status.getPath().getName());
			// 获取文件长度
			System.out.println(status.getLen());
			// 获取文件权限
			System.out.println(status.getPermission());
			// 获取存储块信息
			BlockLocation[] blockLocations = status.getBlockLocations();
			for (BlockLocation blockLocation : blockLocations) {
				// 获取主机名称
				String[] hosts = blockLocation.getHosts();
				for (String host : hosts) {
					System.out.println(host);
				}
			}
			
			System.out.println("-------------------------------------");
			
		}
		
		// 3. 关闭资源
		fs.close();
	}

测试运行可以看到列出的一些块的信息。

6. HDFS文件和文件夹判断

	@Test
	public void testListStatus() throws IOException, InterruptedException, URISyntaxException {
		// 1. 获取文件系统
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "zohar");
		
		// 2. 判断文件还是文件夹
		FileStatus[] listStatus = fs.listStatus(new Path("/"));
		for (FileStatus fileStatus : listStatus) {
			if (fileStatus.isFile()) {
				// 如果是文件
				System.out.println("文件:"+ fileStatus.getPath().getName());
			}else {
				// 如果是文件夹
				System.out.println("文件夹:"+fileStatus.getPath().getName());
			}
		}
		
		// 3. 关闭文件
		fs.close();
	}