【hadoop】9.HDFS-客戶端操做

簡介

經過本章節您能夠學習到java

  1. hadoop基本開發環境的搭建
  2. hadoop經常使用操做的客戶端操做實現。

一、環境準備

1.一、hadoop jar包安置

一、將hadoop2.7.2.tar.gz解壓到指定目錄,例如linux

D:/software/hadoop-2.7.2

hadoop2.7.2.tar.gz就是咱們一開始在linux解壓的編譯包。shell

二、添加win10所需的組件到bin目錄(D:/software/hadoop-2.7.2/bin):將hadoopBin.rar解壓,並將裏面的7個文件複製到D:/software/hadoop-2.7.2/bin目錄。apache

本系列相關的教程都會在章節【hadoop】1.Hadoop簡介中提供的百度外鏈下載到。windows

個人是win10環境,因此須要添加以上的組件。maven

若是你的版本不一致,能夠從相關網站下載到編譯包,至少目前hadoop已經3.x了。ide

1.二、環境變量配置

一、添加HADOOP_HOME變量,值爲D:/software/hadoop-2.7.2/;oop

二、編輯PATH變量,添加新值%HADOOP_HOME%\bin學習

三、進入windows命令行界面,檢測是否成功測試

四、關聯集羣hosts主機名,修改windows的主機文件

C:\Windows\System32\drivers\etc
添加下面3臺主機映射

五、建立目錄D:\hadoop,並在內部建立一個test.txt文件,隨便寫入一些內容。接下來咱們的測試就是將這個文件上傳到HDFS集羣。

接下來須要本身建立的測試文件就本身建立測試,這裏不做過多說明了。

1.三、編寫第一個客戶端程序

一、使用idea建立一個maven項目

二、配置pom文件,信息以下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zhaoyi</groupId>
    <artifactId>firsthadoop</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <hadoop.version>2.7.3</hadoop.version>
    </properties>
    <dependencies>
    <!-- 引入hadoop相關依賴 -->
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>${hadoop.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>${hadoop.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-hdfs</artifactId>
        <version>${hadoop.version}</version>
    </dependency>
    </dependencies>
</project>

三、建立類com.zhaoyi.hdfs.HDFSClient

package com.zhaoyi;

import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.Test;

import java.net.URI;

public class HDFSClient {
    private final static String HADOOP_USER = "root";
    private final static String HDFS_URL = "hdfs://h133:8020";

    public static void main(String[] args) throws Exception {
        // 一、獲取配置實體
        final Configuration configuration = new Configuration();
        // 二、獲取文件系統
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration,HADOOP_USER);
        // 三、拷貝本地數據到集羣
        fileSystem.copyFromLocalFile(new Path("D:/hadoop/test.txt"),new Path("/user/zhaoyi/input"));
        // 四、關閉文件系統
        fileSystem.close();
    }  
}

運行該類,就能夠發現咱們建立的文件上傳到了/user/zhaoyi/input下。接下來咱們就在該類的基礎上進行其餘的測試。

FileSystem.get共有3個重載方法,前兩個方法提取的默認認證用戶名都爲當前用戶的帳戶名,所以,若是您不指定用戶名,會使用你的當前windows帳戶去認證,顯然是沒辦法經過的。不過,若是你的HADOOP_USER和WINDOWS_USER一致的話,這裏不會有什麼問題。推薦使用get的第三個重載方法獲取文件系統。

二、編寫各類測試

2.一、查看文件系統實體信息

@Test
    // 獲取文件系統
    public void getFileSystem() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration,HADOOP_USER);
        // print fs info
        System.out.println(fileSystem);
    }

輸出

DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1963602416_1, ugi=root (auth:SIMPLE)]]

2.二、文件上傳

編寫測試用例

@Test
    public void putFileToHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
        // set destination path
        String destinationPath = "/user/yuanyong";
        // uploadFile
        fileSystem.copyFromLocalFile(true, new Path("D:/hadoop/前塵如夢.txt"),new Path(destinationPath) );
        // close fs
        fileSystem.close();
    }

咱們來查看copyFromLocalFile的源碼信息,第一個參數的最終執行:

return deleteSource ? srcFS.delete(src, true) : true;

該參數設置爲true,則表明上傳完成以後會將源文件給刪除,是否是以爲很像move操做。若是您不想讓他刪除,能夠省略此參數,或者設置爲false便可。

2.三、文件下載

@Test
    public void getFileFromHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
        // set download path.
        String downloadPath = "D:/";
//        fileSystem.copyToLocalFile(new Path("/user/new.file"),new Path(downloadPath));
        fileSystem.copyToLocalFile(false,new Path("/user/new.file"),new Path(downloadPath),false);
        fileSystem.close();
    }

一樣,fileSystem.copyToLocalFile也有3個重載方法,其中第三個重載方法的第一個參數指定是否刪除源文件,最後一個參數指定是否執行本地的文件系統校檢(默認false),false則會在本地生成一個名爲.filename.crc的校檢文件,設置爲true則不生成

關於文件校檢:不指定本地校檢時,會透明的建立一個.filename.crc的文件。校驗文件大小的字節數由io.bytes.per.checksum屬性設置,默認是512bytes,即每512字節就生成一個CRC-32校驗和。

3.四、建立目錄

@Test
    public void makeDirInHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
        fileSystem.mkdirs(new Path("/user/areya/my/best/love"));
        System.out.println("create dir success.");
        fileSystem.close();
    }

建立目錄默認就是遞歸方式。

fileSystem.mkdirs有兩個重載方法,另一個 public boolean mkdirs(Path var1, FsPermission var2)具體用到再說明。

3.五、刪除文件

@Test
    public void deleteInHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
        fileSystem.delete(new Path("/user/areya"),true);
        System.out.println("delete dir success.");
        fileSystem.close();
    }

fileSystem.delete也可只指定一個參數,不過該方法會在從此的版本刪除,不推薦使用。

3.六、重命名文件

@Test
    public void renameInHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
        fileSystem.rename(new Path("/user/yuanyong"),new Path("/user/hongqun"));
        System.out.println("rename dir success.");
        fileSystem.close();
    }

3.七、查看文件詳情

接下來咱們將當前測試在HDFS上的全部文件相關信息都打印一遍。

@Test
    public void getFileInfoInHDFS() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);

        // get all file.
        RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true);

        while (listFiles.hasNext()){
            System.out.println("------------------");
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("path: " + fileStatus.getPath());
            System.out.println("group: " + fileStatus.getGroup());
            System.out.println("owner: " + fileStatus.getOwner());
            System.out.println("access time: " + fileStatus.getAccessTime());
            System.out.println("block size: " + fileStatus.getBlockSize());
            System.out.println("length: " + fileStatus.getLen());
            System.out.println("modify time: " + fileStatus.getModificationTime());
            System.out.println("modify time: " + fileStatus.getModificationTime());
            System.out.println("permission: " + fileStatus.getPermission());
            System.out.println("replicate: " + fileStatus.getReplication());
//            System.out.println("symlink: " + fileStatus.getSymlink());

            System.out.println("This file blocks info:");
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            for (BlockLocation blockLocation:blockLocations) {
                System.out.println("block length:" + blockLocation.getLength());
                System.out.println("block offsets:" + blockLocation.getOffset());

                System.out.println("block hosts:");
                for (String host : blockLocation.getHosts()) {
                    System.out.println(host);
                }


            }

        }

        System.out.println("-------------");
        System.out.println("print end.");
    }

輸出結果:

path: hdfs://h133:8020/user/hongqun/前塵如夢.txt
group: supergroup
owner: root
access time: 1546474991076
block size: 134217728
length: 20
modify time: 1546474991244
modify time: 1546474991244
permission: rw-r--r--
replicate: 3
This file blocks info:
block length:20
block offsets:0
block hosts:
h133
h135
h134
------------------
path: hdfs://h133:8020/user/hongqun/test/new.file
group: supergroup
owner: root
access time: 1546465187927
block size: 134217728
length: 21
modify time: 1546465174342
modify time: 1546465174342
permission: rw-r--r--
replicate: 3
This file blocks info:
block length:21
block offsets:0
block hosts:
h135
h134
h133
------------------
path: hdfs://h133:8020/user/new.file
group: supergroup
owner: root
access time: 1546477521786
block size: 134217728
length: 21
modify time: 1546465709803
modify time: 1546465709803
permission: rw-r--r--
replicate: 3
This file blocks info:
block length:21
block offsets:0
block hosts:
h133
h134
h135

從輸出結果咱們能夠了解到listFiles方法只會列出全部的文件(而非文件夾)信息。

3.八、獲取全部文件(夾)詳情

前面咱們經過listFiles獲取了文件的信息,接下來咱們獲取某個路徑下文件的信息,並輸出其中的文件和文件夾類型文件。

@Test
    public void getAllFileInfoInHDFS() throws Exception {
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);

        // get dir "/user"'s file.
        FileStatus[] listFiles = fileSystem.listStatus(new Path("/user"));
        for (FileStatus fileStatus:listFiles) {
            if(fileStatus.isDirectory()){
                System.out.println("dir:" + fileStatus.getPath().getName());
            }else if(fileStatus.isFile()){
                System.out.println("file:" + fileStatus.getPath().getName());
            }else if(fileStatus.isEncrypted()){
                System.out.println("cry:" + fileStatus.getPath().getName());
            }else if(fileStatus.isSymlink()){
                System.out.println("symlink:" + fileStatus.getPath().getName());
            }

        }

        System.out.println("-------------");
        System.out.println("print end.");
    }  System.out.println("print end.");
    }

輸出以下:

dir:hongqun
file:new.file
dir:zhaoyi
-------------
print end.

HDFS中可能存在4種類型的文件。

3.九、總結

總結一下咱們以上的操做共性:

// 1. 建立配置對象
Configuration configuration = new Configuration();
// 2. 建立文件系統操做對象:設置文件系統URI、配置信息以及HDFS用戶名
FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL), configuration, HADOOP_USER);
// 3. 執行操做
fileSystem.xxxx(parameter);

四、經過IO流的方式操做文件

接下來咱們經過IO流方式完成文件的一些常規上傳下載操做。從新建立一個客戶端類。

4.一、上傳文件

package com.zhaoyi;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;

public class HDFSIOClient {
    private final static String HADOOP_USER = "root";
    private final static String HDFS_URL = "hdfs://h133:8020";

    @Test
    public void uploadFile() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER);
        // 1. 獲取輸入流
        FileInputStream fis = new FileInputStream(new File("D:/hadoop/天淨沙.txt"));
        // 2. 獲取輸出流
        FSDataOutputStream fos = fileSystem.create(new Path("/user/天淨沙.txt"));
        // 3. 流對接 & 關閉流
        try {
            IOUtils.copyBytes(fis, fos,configuration);
            System.out.println("upload file success.");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            fis.close();
            fos.close();
            fileSystem.close();
        }
    }    
}

輸出與輸入的參考系是相對於當前內存系統(也能夠理解爲咱們的客戶端)而言的。本地文件系統屬於輸入流,上傳的目的地HDFS文件系統則屬於輸出流。

4.二、下載文件

@Test
    public void downloadFile() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER);
        // 1. 獲取輸入流
        FSDataInputStream fis = fileSystem.open(new Path("/user/奧丁的子女.txt"));
        // 2. 獲取輸出流
        FileOutputStream fos = new FileOutputStream(new File("D:/hadoop/奧丁的子女.txt"));

        // 3. 流對接&關閉流
        try {
            IOUtils.copyBytes(fis, fos,configuration);
            System.out.println("download file success.");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            fis.close();
            fos.close();
            fileSystem.close();
        }
    }

從這裏咱們要明白:相對於本地客戶端來講,本地文件系統在下載模式下屬於輸出的對象,所以使用輸出流對應;HDFS文件系統屬於輸入的對象,所以使用輸入流,FileSystem的create建立輸出流,open方法建立輸入流。

4.三、定位方式讀取文件

還記得咱們以前的很大的hadoop安裝文件夾嗎,接下來咱們來定位方式下載該文件。您也能夠從新上傳一次:

[root@h133 ~]# hadoop fs -put /opt/software/hadoop-2.7.2.tar.gz /user/
[root@h133 ~]# hadoop fs -ls /user/
Found 6 items
-rw-r--r--   3 root supergroup  212046774 2019-01-03 11:06 /user/hadoop-2.7.2.tar.gz
drwxr-xr-x   - root supergroup          0 2019-01-03 08:23 /user/hongqun
-rw-r--r--   3 root supergroup         21 2019-01-03 05:48 /user/new.file
drwxr-xr-x   - root supergroup          0 2019-01-03 06:11 /user/zhaoyi
-rw-r--r--   3 root supergroup         28 2019-01-03 10:39 /user/天淨沙.txt
-rw-r--r--   3 root supergroup        167 2019-01-03 10:50 /user/奧丁的子女.txt

接下來咱們下載hadoop-2.7.2.tar.gz,分紅兩部分:第一次下載128M,剩餘的放到第二次進行下載。

// 進行第一次下載
    @Test
    public void downloadFileBySeek1() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER);
        // part 1. 128M
        // 1. 獲取輸入流
        FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz"));
        // 2. 獲取輸出流
        FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part1"));
        // 3. 流對接(第一部分只需讀取128M便可)
        byte[] buff = new byte[1024];
        try {
            for (int i = 0; i < 1024 * 128; i++) {
                inputStream.read(buff);
                outputStream.write(buff);
            }
        } finally {
            IOUtils.closeStream(inputStream);
            IOUtils.closeStream(outputStream);
            IOUtils.closeStream(fileSystem);
        }

    }

        // 進行第一次下載
    @Test
    public void downloadFileBySeek1() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER);
        // part 1. 128M
        // 1. 獲取輸入流
        FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz"));
        // 2. 獲取輸出流
        FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part1"));
        // 3. 流對接(第一部分只需讀取128M便可)
        byte[] buff = new byte[1024];
        try {
            for (int i = 0; i < 1024 * 128; i++) {
                inputStream.read(buff);
                outputStream.write(buff);
            }
        } finally {
            IOUtils.closeStream(inputStream);
            IOUtils.closeStream(outputStream);
            IOUtils.closeStream(fileSystem);
        }

    }

    
    // 第二次尋址下載
    @Test
    public void downloadFileBySeek2() throws Exception{
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI(HDFS_URL),configuration, HADOOP_USER);
        // part 1. 128M
        // 1. 獲取輸入流
        FSDataInputStream inputStream = fileSystem.open(new Path("/user/hadoop-2.7.2.tar.gz"));
        // 2. 獲取輸出流
        FileOutputStream outputStream = new FileOutputStream(new File("D:/hadoop/hadoop-2.7.2.tar.gz.part2"));
        // 3. 指向第二塊數據地址
        inputStream.seek(1024 * 1024 * 128);
        try {
            IOUtils.copyBytes(inputStream,outputStream,configuration);
        } finally {
            IOUtils.closeStream(inputStream);
            IOUtils.closeStream(outputStream);
            IOUtils.closeStream(fileSystem);
        }

    }

分別運行兩個測試方法以後,在目錄D:/hadoop/下就會生成兩個tar.gz.part1和part2的分塊文件。接下來運行windows命令行執行追加劇定向操做,將兩個文件合併爲1個。

type hadoop-2.7.2.tar.gz* > hadoop-2.7.2.tar.gz

便可合併咱們最初的hadoop壓縮包文件,能夠經過解壓縮或者md5計算驗證是否一致。

參考

本系列的文章參考資料來源有3個地方:

  1. 尚硅谷官方大數據教學視頻。
  2. 書籍《hadoop權威指南 第四版》
  3. 官方文檔。
相關文章
相關標籤/搜索