package com.haohaodata.bigdata;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URI;
/**
* Created by hager on 2020/1/12.
* junit 及 HDFS API编程
*
* 1、对于你要测试的方法,需要使用@Test这个注解
* 2、@Before和@After分别是在每个测试方式执行前后执行(即:每个测试方法都会执行一次@Before和@After)
* 3、@BeforeClass和@AfterClass是在所有测试方法执行前后执行(即:只执行一次@BeforeClass和@AfterClass)
*/
public class HDFSAPITest {
FileSystem fileSystem;
/**
* 在 Before 中完成 FileSystem 的初始化操作
* @throws Exception
*/
@Before
public void setUp() throws Exception {
URI uri = new URI("hdfs://hadoop001:9000");
Configuration configuration = new Configuration();
configuration.set("dfs.client.use.datanode.hostname", "true");
configuration.set("dfs.replication", "1");
fileSystem = FileSystem.get(uri, configuration, "haohao");
}
/**
* 在 After 方法中完成 FileSystem 的关闭操作
* @throws Exception
*/
@After
public void tearDown() throws Exception {
if (null != fileSystem) {
fileSystem.close();
}
}
/**
* 在HDFS上创建文件夹
* @throws Exception
*/
@Test
@Ignore // 不执行
public void mkdir() throws Exception {
fileSystem.mkdirs(new Path("/haohaodata/test1"));
}
/**
* 将本地文件拷贝到HDFS上
* @throws Exception
*/
@Test
@Ignore
public void copyFromLocalFile() throws Exception{
// 本地文件路径
Path src = new Path("data/haohaodata.txt");
//dst : HDFS文件路径
//dst: 如果指定的是一个目录 如:/hdfsapiv1 ,会将haohao.txt拷贝到/hdfsapiv1目录下 如:/hdfsapiv1/haohao.txt
//dst: 如果指定的是一个文件 如:/hdfsapiv1/haohaodata.txt ,会将haohao.txt文件中的内容拷贝到文件haohaodata.txt中
Path dst = new Path("/hdfsapiv1");
fileSystem.copyFromLocalFile(src, dst);
// true: 删除本地文件 false: 不删除(default)
fileSystem.copyFromLocalFile(true, src, dst);
// 第一个参数表示:是否删除本地文件;第二个参数表示:如果HDFS已经存在该文件,是否覆盖HDFS上的文件
// 如果文件已经存在,第二个参数设置为false ,会报错:java.io.IOException: Target /hdfsapiv1/haohaodata.txt already exists
fileSystem.copyFromLocalFile(false, false, src, dst);
}
/**
* 从HDFS上拷贝文件到本地
* @throws Exception
*/
@Test
@Ignore
public void copyToLocalFile() throws Exception{
// HDFS文件路径
Path src = new Path("/copyToLocalFile/a.txt");
// 本地文件路径
// dst指定目录或者指定文件(同copyFromLocalFile)
Path dst = new Path("data");
fileSystem.copyToLocalFile(src, dst);
// 第一个参数:是否删除HDFS上的文件(true:删除;false:不删)
// 如果本地目录data下,文件已经存在,会自动覆盖
fileSystem.copyToLocalFile(false, src, dst);
// 第三个参数:useRawLocalFileSystem:whether to use RawLocalFileSystem as local file system or not.(不太理解)
fileSystem.copyToLocalFile(false, src, dst, false);
}
/**
* rename 有2个功能:
* 1、修改文件名称
* 2、移动文件,相当于Linux命令mv
* TODO 注意:rename 操作不会改变文件的修改时间
* @throws Exception
*/
@Test
@Ignore
public void renameFile() throws Exception{
// HDFS文件名称
Path src1 = new Path("/copyToLocalFile/a.txt");
// HDFS修改后的文件名称
Path dst1 = new Path("/copyToLocalFile/aaa.txt");
// mv
Path src2 = new Path("/copyToLocalFile/aaa.txt");
Path dst2 = new Path("/hdfsapiv1/mv.txt");
fileSystem.rename(src1, dst1);
fileSystem.rename(src2, dst2);
}
/**
* HDFS list 文件夹下的所有 文件 文件 文件
* @throws Exception
*/
@Test
// @Ignore
public void listFiles() throws Exception{
// 参数1:文件夹路径 ; 参数2: 是否递归
RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(new Path("/haohaodata"), false);
// 如果第二个参数设置为false,则不会读取/hdfsapiv1目录下的文件夹,只会读取文件
// RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(new Path("/hdfsapiv1"), false);
while (files.hasNext()){
LocatedFileStatus fileStatus = files.next();
// 获取文件路径
String filePath = fileStatus.getPath().toString();
// 获取文件长度
long fileLen = fileStatus.getLen();
// 获取文件副本数量
short fileReplication = fileStatus.getReplication();
// 获取文件权限
FsPermission permission = fileStatus.getPermission();
// 判断是文件 还是文件夹
String isDir = fileStatus.isDirectory() ? "文件夹" : "文件";
// 获取文件Block位置(一个文件可能有多个Block)
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation local : blockLocations){
String[] hosts = local.getHosts();
// 存在多台机器上(和副本数有关)
for (String host: hosts){
System.out.println("hosts: "+ host);
}
}
System.out.println( filePath + "\t" + fileLen + "\t" + fileReplication + "\t" + permission + "\t" + isDir);
}
}
/**
* 删除HDFS文件夹
* @throws Exception
*/
@Test
@Ignore
public void delete() throws Exception{
// 删除路径/copyToLocalFile/test 不递归 报错
// org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.fs.PathIsNotEmptyDirectoryException): `/copyToLocalFile/test is non empty': Directory is not empty
fileSystem.delete(new Path("/copyToLocalFile/test"), false);
// 删除路径/copyToLocalFile/test 递归(test被删除)
fileSystem.delete(new Path("/copyToLocalFile/test"), true);
}
/**
* IO
* 字节流
* InputStream
* OutputStream
* 字符流
* Reader
* Writer
*
* 使用 IO 字节流 InputStream 拷贝本地文件到HDFS上
* @throws Exception
*/
@Test
@Ignore
public void copyFromLocalFileIO() throws Exception{
// 读
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File("data/haohaodata.txt")));
// 写
FSDataOutputStream out = fileSystem.create(new Path("/hdfsapiv1/hao.txt"));
IOUtils.copyBytes(in, out, 1024);
// 关闭
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
/**
* 从HDFS使用拷贝文件到本地 使用IO的方式
* 需求:把每个block给单独下载下来
* @throws Exception
*/
@Test
@Ignore
public void copyToLocalFileIO01() throws Exception{
// 从HDFS上读去文件
FSDataInputStream open = fileSystem.open(new Path("/hdfsapiv1/hadoop-2.6.0-cdh5.16.2.tar.gz"));
// 写到本地文件
FileOutputStream out = new FileOutputStream(new File("data/hadoop.tar.gz.part0"));
byte[] buffer = new byte[1024];
// 0 - 128M
for (int i=0 ; i<1024*128 ; i++){
open.read(buffer);
out.write(buffer);
}
IOUtils.closeStream(open);
IOUtils.closeStream(out);
}
@Test
@Ignore
public void copyToLocalFileIO02() throws Exception{
// 从HDFS上读去文件
FSDataInputStream open = fileSystem.open(new Path("/hdfsapiv1/hadoop-2.6.0-cdh5.16.2.tar.gz"));
// 写到本地文件
FileOutputStream out = new FileOutputStream(new File("data/hadoop.tar.gz.part1"));
// 设置指定读取的offset
open.seek(1024*1024*128);
byte[] buffer = new byte[1024];
for (int i=0 ; i<1024*128 ; i++){
open.read(buffer);
out.write(buffer);
}
IOUtils.closeStream(open);
IOUtils.closeStream(out);
}
@Test
@Ignore
public void copyToLocalFileIO03() throws Exception{
// 从HDFS上读去文件
FSDataInputStream open = fileSystem.open(new Path("/hdfsapiv1/hadoop-2.6.0-cdh5.16.2.tar.gz"));
// 写到本地文件
FileOutputStream out = new FileOutputStream(new File("data/hadoop.tar.gz.part2"));
// 设置指定读取的offset
open.seek(1024*1024*128*2);
byte[] buffer = new byte[1024];
for (int i=0 ; i<1024*128 ; i++){
open.read(buffer);
out.write(buffer);
}
IOUtils.closeStream(open);
IOUtils.closeStream(out);
}
@Test
@Ignore
public void copyToLocalFileIO04() throws Exception{
// 从HDFS上读去文件
FSDataInputStream open = fileSystem.open(new Path("/hdfsapiv1/hadoop-2.6.0-cdh5.16.2.tar.gz"));
// 写到本地文件
FileOutputStream out = new FileOutputStream(new File("data/hadoop.tar.gz.part3"));
// 设置指定读取的offset 384M
open.seek(1024*1024*128*3);
IOUtils.copyBytes(open, out, 1024);
IOUtils.closeStream(open);
IOUtils.closeStream(out);
}
/**
* TODO 小测题目
* 需求:
*
* 使用方法:
* rename("20201011")
* rename("20201012")
*
* 输入:
* /haohaodata/20201011/188.txt
* /haohaodata/20201011/2sf.txt
* /haohaodata/20201011/36t.txt
* /haohaodata/20201012/1ns.txt
* /haohaodata/20201012/2sfs.txt
* /haohaodata/20201012/37hjd.txt
*
* 输出:
* /haohaodata/20201011/20201011-0.txt
* /haohaodata/20201011/20201011-1.txt
* /haohaodata/20201011/20201011-2.txt
* /haohaodata/20201012/20201012-0.txt
* /haohaodata/20201012/20201012-1.txt
* /haohaodata/20201012/20201012-2.txt
*
* @throws Exception
*/
@Test
@Ignore
public void rename() throws Exception {
String day = "20200111";
RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(new Path("/haohaodata/" + day), true);
int i = 0;
while (files.hasNext()) {
LocatedFileStatus next = files.next();
String file = next.getPath().toString();
Path src = new Path(file);
Path dst = new Path("/haohaodata/" + day + "/" + day + "-" + i + ".txt");
fileSystem.rename(src, dst);
i++;
}
}
}
junit及HDFS API常用方法
最新推荐文章于 2024-09-21 17:07:20 发布