Hadoop(三) HDFS 使用

目录

准备工作

HDFS API的使用

org.apache.hadoop.fs.FileSystem

org.apache.hadoop.fs.Path

org.apache.hadoop.fs.FsStatus

org.apache.hadoop.fs.FileStatus

org.apache.hadoop.fs.FSDataInputStream

org.apache.hadoop.fs.FSDataOutputStream

示例

常用客户端命令


准备工作

使用开发工具为idea

1.需要将hadoop的hdfs-site.xml, core-site.xml这两个配置文件拷贝到项目的resources目录下

2.需要在maven中引入

<dependency> 
    <groupId>org.apache.hadoop</groupId> 
    <artifactId>hadoop-client</artifactId> 
    <version>2.7.3</version> 
</dependency>

HDFS API的使用

org.apache.hadoop.fs.FileSystem

抽象类,定义了文件系统访问的一般步骤。涉及到具体要访问什么样的文件系统,由其子类实现
比方说分布式文件系统,本地文件系统等等,其子类如下

org.apache.hadoop.fs.Path

用于创建一个路径,来表示一个文件或目录。可以是普通的文件路径,也可以是URI

org.apache.hadoop.fs.FsStatus

表示文件系统的存储空间使用情况

org.apache.hadoop.fs.FileStatus

表示文件的相关属性

org.apache.hadoop.fs.FSDataInputStream

读入HDFS系统的文件接口

org.apache.hadoop.fs.FSDataOutputStream

向HDFS系统写入文件

示例

@Test
    // 读数据
    public void test() throws IOException {
        /**
         * 加载配置文件
         *
         * * 底层会加载一堆的配置文件:
         *          *
         *          * core-default.xml
         *          * hdfs-default.xml
         *          * mapred-default.xml
         *          * yarn-default.xml
         *
         * * 当前这个hdfs-site.xml文件就放置在这个项目中的src下。也就是classpath路径下。
         *          * 所以 FS在初始化的时候,会把hdfs-site.xml这个文件中的name-value对解析到conf中
         *          * 但是:
         *          * 1、如果hdfs-site.xml 不在src下, 看是否能加载???  不能
         *          * 2、如果文件名不叫做 hdfs-default.xml 或者 hdsf-site.xml  看是否能自动加载???  不能
         *          * 得出的结论:
         *          * 如果需要项目代码自动加载配置文件中的信息,那么就必须把配置文件改成-default.xml或者-site.xml的名称
         *          * 而且必须放置在src下
         *          *
         *          * 那如果不叫这个名,或者不在src下,也需要加载这些配置文件中的参数:
         *          * 必须使用conf对象提供的一些方法去手动加载
         *          conf.set("dfs.replication", "2"); #注意所有的值都是以字符串的形式传入
         */
        Configuration conf = new Configuration();

        //代码入口点,初始化hdfs文件系统
        FileSystem fs = FileSystem.get(conf);

        //通过fs读数据
        Path p = new Path("/user/centos/user");
        FSDataInputStream fis = fs.open(p);

        // 读取文件
        int len = 0;
        byte[] buff = new byte[1024];
        while((len = fis.read(buff)) != -1) {
            System.out.println(new String(buff,0,len));
        }

    }

    @Test
    //出现 winutil问题
    // 写入文件
    // 对hdfs的操作会更改namenode信息时,就会涉及到权限问题
    //* 更改操作用户有两种方式:
    //         * 1、直接设置运行的用户名为hadoop
    //         * VM arguments ;   -D HADOOP_USER_NAME=admin
    //         * 2、在代码中进行声明
    //         * System.setProperty("HADOOP_USER_NAME", "admin");

    public void test2() throws Exception{
        // 设置操作的用户名,防止出现权限问题
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path p = new Path("/user/centos/t4.txt");
        FSDataOutputStream out = fs.create(p);
        out.write("the people's republic of china".getBytes());
        out.flush();
        out.close();
    }

    @Test
    // 向已经存在的文件,追加新内容
    public void test3() throws Exception{
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path p = new Path("/user/centos/t4.txt");
        FSDataOutputStream append = fs.append(p);
        append.write("\n i love this computer! it's has big power.".getBytes());
        append.flush();
        append.close();
    }

    @Test
    // 删除文件
    public void test4() throws Exception {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path p = new Path("/user/centos/tt");

        // recursive 这个参数设为为true, 递归的删除它的子目录
        // 为false时如果该目录下有内容会报错
        fs.delete(p, true);
        fs.close();
    }

    @Test
    // 把hdfs内的文件复制到本地,或者说是下载文件
    public void test5() throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path p = new Path("/user/centos/t4.txt");
        FSDataInputStream in = fs.open(p);

        FileOutputStream out = new FileOutputStream("g:/mr/tt.txt");
        IOUtils.copyBytes(in, out, 1024);
        in.close();
        out.close();
        fs.close();
    }

    @Test
    /**
     * 递归列出指定目录内的内容
     */
    public void test6() throws Exception {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();

        FileSystem fs = FileSystem.get(conf);
        listDF(fs, new Path("/"));
        fs.close();
    }

    public void listDF(FileSystem fs, Path path) throws IOException {
        FileStatus[] statuses = fs.listStatus(path);
        for(FileStatus status : statuses) {
            if(status.isFile()) {
                System.out.println(status.getPath());
            } else {
                listDF(fs, status.getPath());
            }

        }
    }


    @Test
    /**
     * 测试配置的优先级
     * 1)客户端代码中设置的值 >(2)classpath下的用户自定义配置文件 >(3)然后是服务器的默认配置
     */
    public void test7() throws IOException {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        conf.set("dfs.replication", "2");
        FileSystem fs = FileSystem.get(conf);
        Path p = new Path("/user/centos/t10.txt");
        FSDataOutputStream out = fs.create(p);
        out.write("the people's republic of china".getBytes());
        out.flush();
        out.close();
    }

    @Test
    /**
     * 列出指定目录下的文件及其块信息
     */
    public void test8() throws IOException {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);

        Path path = new Path("/user/centos");
        RemoteIterator<LocatedFileStatus> fsInfo = fs.listFiles(path, true);

        while(fsInfo.hasNext()) {
            LocatedFileStatus file = fsInfo.next();
            System.out.println("path:" + file.getPath());
            System.out.println("name:" + file.getPath().getName());
            System.out.println("len: " + file.getLen());
            System.out.println("replication:" + file.getReplication());

            BlockLocation[] blockLocations = file.getBlockLocations();

            for(BlockLocation bl : blockLocations) {
                System.out.println("hosts:" + Arrays.toString(bl.getHosts()));
            }
            System.out.println("============================");
        }

        Path path2 = new Path("/user/centos/t4.txt");
        System.out.println(fs.getFileStatus(path2).getLen());
        System.out.println(fs.getFileStatus(path2).getReplication());
        System.out.println(fs.getFileStatus(path2).getBlockSize());

    }

@Test
    /**
     * 统计hdfs中文件大小小于blocksize的文件占比
     */
    public void test12()   {
        // fs.getFileStatus(path2).getLen(); 可以直接使用这个查看文件的大小
        // fileStatus.getBlockSize() 这个返回的是这个文件的所设定的块大小
        System.setProperty("HADOOP_USER_NAEM", "centos");
        Configuration conf = new Configuration();

        try {
            FileSystem fs = FileSystem.get(conf);
            FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
            Queue<FileStatus> queue = new LinkedList<>();
            queue.addAll(Arrays.asList(fileStatuses));
            // 统计有多少个文件块
            int countBlock1 = 0;
            // 统计少于文件块大小的块
            int countBlock2 = 0;
            FileStatus fileStatus = null;

            while ((fileStatus = queue.poll()) != null) {
                try {
                    if (fileStatus.isDirectory()) {
                        queue.addAll(Arrays.asList(fs.listStatus(fileStatus.getPath())));
                    } else if (fileStatus.isFile()) {
                        System.out.println("file name: " + fileStatus.getPath() + ", size: " + fileStatus.getLen()/(1024*1024) + " mb");
                        BlockLocation[] fileBlockLocations = fs.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());

                        for(BlockLocation bl : fileBlockLocations) {
                            countBlock1 ++;
                            if(bl.getLength() < fileStatus.getBlockSize()) {
                                countBlock2++;
                            }
                        }
                    }
                } catch (Exception e) {

                }
            }

            System.out.println("scale: " + (double)countBlock2 / countBlock1);

        } catch (Exception e) {

        }


    }

    @Test
    /**
     * 统计系统中文件的平均副本数
     */
    public void test13() {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        int totalFile = 0;
        int totalReplication = 0;
        try {
            FileSystem fs = FileSystem.get(conf);
            // 刚开始因为,hadoop的用户名设置错误,导致这里获取不到信息
            RemoteIterator<LocatedFileStatus> listStatusIter = fs.listFiles(new Path("/"), true);
            while(listStatusIter.hasNext()) {

                LocatedFileStatus fileStatus = listStatusIter.next();
                if(fileStatus.isFile()) {
                    totalFile++;
                    totalReplication += fileStatus.getReplication();
                }
            }


        } catch (Exception e) {

        } finally {
            if(totalFile != 0)
                System.out.println("average replication : " + totalReplication / totalFile);
        }

    }

    @Test
    /**
     * 统计系统中文件的平均block
     */
    public void test14() {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        int totalFile = 0;
        int totalBlock = 0;
        try {
            FileSystem fs = FileSystem.get(conf);
            RemoteIterator<LocatedFileStatus> fileStatusIter = fs.listFiles(new Path("/"), true);
            while(fileStatusIter.hasNext()) {
                LocatedFileStatus fileStatus = fileStatusIter.next();
                if(fileStatus.isFile()) {
                    totalBlock += fileStatus.getBlockLocations().length;
                    System.out.println(fileStatus.getBlockLocations().length);
                    totalFile ++;
                }

            }
        } catch (Exception e) {

        } finally {
            if(totalFile != 0) {
                System.out.println("average block " + (double)totalBlock / totalFile);
            }
        }
    }

    /**
     * 统计HDFS整个文件系统中的不足指定数据块大小的数据块的比例
     *
     *
     */
    @Test
    public void test15() {
        System.setProperty("HADOOP_USER_NAME", "centos");
        Configuration conf = new Configuration();
        int totalBlock = 0;
        int count = 0;
        try {
            FileSystem fs = FileSystem.get(conf);


            RemoteIterator<LocatedFileStatus> fileStatusIter = fs.listFiles(new Path("/"), true);
            while(fileStatusIter.hasNext()) {
                LocatedFileStatus fileStatus = fileStatusIter.next();
                if(fileStatus.isFile()) {
                    totalBlock += fileStatus.getBlockLocations().length;

                    for(BlockLocation bl : fileStatus.getBlockLocations()) {
                        if(bl.getLength() < fileStatus.getBlockSize()) {
                            count ++;
                        }
                    }
                }
            }
        } catch (Exception e) {

        } finally {
            System.out.println((double)count / totalBlock);
        }
    }

 

常用客户端命令

0.直接在命令行,输入hadoop, hadoop fs, hdfs fs
  都会给出相应的命令提示

1. hadoop fs 与 hdfs dfs 等价
   列出hdfs 文件操作的所有相关命令
   
2. hadoop fs -help command-name
   列出某个命令的帮助信息
   
3. hadoop fs -ls direct-path
    列出某个目录内下的内容
	
4. hadoop fs -mkdir /data
   在hdfs上创建目录
   
5. hadoop fs -moveFromLocal source dest
    将本地文件移到hdfs上
	
	hadoop fs -copyFromLocal source dest
	将本地文件拷贝到hdfs上
	
	hadoop fs -copyToLocal source dest
	 拷贝hdfs文件到本地
	 
	hadoop fs -cp source dest
	在hdfs上拷贝文件到系统的其他目录
	
	hadoop fs -mv source dest
	在hdfs上移动文件到系统的其他目录
	
	hadoop fs -get source dest
	下载hdfs文件到本地
	
	hadoop fs -getmerge source dest
	下载多个hdfs文件到本地,且只生成一个文件
	
	hadoop fs -put source dest 
	上传本地文件到hdfs
	
	hadoop fs -rm filename
	删除hdfs上的某个文件
	
	hadoop fs -rmdir direct-name
	删除文件夹
	
	
	
6. hadoop fs -cat /centos/hello.txt
   查看hdfs上的文件
   
7. hadoop fs -appendToFile source dest
   追加文件到原有的文件
   如果目标文件不存在会创建
   
9. hadoop fs -tail /centos/hello
   显示一个文件末尾
   
10. hadoop fs -chmode 777 /centos/hello
   修改权限
   
11. hadoop fs -chown root:root /centos/hello
   修改文件所有者
   
12. hadoop fs -df -h path
   统计hdfs 文件系统可用空间信息
   
13. hadoop fs -du -h path
   统计文件夹大小信息

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章