junit及HDFS API常用方法

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++;
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值