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
   統計文件夾大小信息

 

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