亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java操作HDFS開發環境搭建以及HDFS的讀寫流程

發布時間:2020-06-13 00:02:19 來源:網絡 閱讀:30352 作者:ZeroOne01 欄目:大數據

Java操作HDFS開發環境搭建

在之前我們已經介紹了如何在Linux上進行HDFS偽分布式環境的搭建,也介紹了hdfs中一些常用的命令。但是要如何在代碼層面進行操作呢?這是本節將要介紹的內容:

1.首先使用IDEA創建一個maven工程:
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

maven默認是不支持cdh的倉庫的,需要在pom.xml中配置cdh的倉庫,如下:

  <repositories>
    <repository>
      <id>cloudera</id>
      <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
    </repository>
  </repositories>

注意:如果你maven的settings.xml文件中,將mirrorOf的值配置成了*的話,那么就需要將其修改為*,!clouderacentral,因為*表示覆蓋所有倉庫地址會導致maven無法從cloudera的倉庫下載依賴包,而*,!cloudera 表示不覆蓋id為cloudera的倉庫,關于這個問題可以自行了解一下。具體配置如下示例:

<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>*,!cloudera</mirrorOf>
</mirror>

最后添加相關的依賴項:

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hadoop.version>2.6.0-cdh6.7.0</hadoop.version>
  </properties>

  <dependencies>
    <!-- hadoop依賴 -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>${hadoop.version}</version>
    </dependency>

    <!-- 單元測試依賴 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

Java API操作HDFS文件系統

搭建完工程環境后,我們就可以調用Hadoop的API來操作HDFS文件系統了,下面我們來寫一個測試用例,在HDFS文件系統上創建一個目錄:

package org.zero01.hadoop.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.net.URI;

/**
 * @program: hadoop-train
 * @description: Hadoop HDFS Java API 操作
 * @author: 01
 * @create: 2018-03-25 13:59
 **/
public class HDFSAPP {

    // HDFS文件系統服務器的地址以及端口
    public static final String HDFS_PATH = "hdfs://192.168.77.130:8020";
    // HDFS文件系統的操作對象
    FileSystem fileSystem = null;
    // 配置對象
    Configuration configuration = null;

    /**
     * 創建HDFS目錄
     */
    @Test
    public void mkdir()throws Exception{
        // 需要傳遞一個Path對象
        fileSystem.mkdirs(new Path("/hdfsapi/test"));
    }

    // 準備資源
    @Before
    public void setUp() throws Exception {
        configuration = new Configuration();
        // 第一參數是服務器的URI,第二個參數是配置對象,第三個參數是文件系統的用戶名
        fileSystem = FileSystem.get(new URI(HDFS_PATH), configuration, "root");
        System.out.println("HDFSAPP.setUp");
    }

    // 釋放資源
    @After
    public void tearDown() throws Exception {
        configuration = null;
        fileSystem = null;

        System.out.println("HDFSAPP.tearDown");
    }
}

運行結果:
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

可以看到是運行成功的,然后到服務器上,查看文件是否多了我們創建的目錄:

[root@localhost ~]# hdfs dfs -ls /
Found 3 items
-rw-r--r--   1 root supergroup  311585484 2018-03-24 23:15 /hadoop-2.6.0-cdh6.7.0.tar.gz
drwxr-xr-x   - root supergroup          0 2018-03-25 22:17 /hdfsapi
-rw-r--r--   1 root supergroup         49 2018-03-24 23:10 /hello.txt
[root@localhost ~]# hdfs dfs -ls /hdfsapi
Found 1 items
drwxr-xr-x   - root supergroup          0 2018-03-25 22:17 /hdfsapi/test
[root@localhost ~]# 

如上,代表我們的目錄創建成功了。

我們再來增加一個方法,測試創建文件,并寫入一些內容到文件中:

/**
 * 創建文件
 */
@Test
public void create() throws Exception {
    // 創建文件
    FSDataOutputStream outputStream = fileSystem.create(new Path("/hdfsapi/test/a.txt"));
    // 寫入一些內容到文件中
    outputStream.write("hello hadoop".getBytes());
    outputStream.flush();
    outputStream.close();
}

執行成功后,同樣的到服務器上,查看是否有我們創建的文件,并且文件的內容是否是我們寫入的內容:

[root@localhost ~]# hdfs dfs -ls /hdfsapi/test
Found 1 items
-rw-r--r--   3 root supergroup         12 2018-03-25 22:25 /hdfsapi/test/a.txt
[root@localhost ~]# hdfs dfs -text /hdfsapi/test/a.txt
hello hadoop
[root@localhost ~]# 

每次操作完都得去服務器上查看,很麻煩,其實我們也可以直接在代碼中讀取文件系統中某個文件的內容,如下示例:

/**
 * 查看HDFS里某個文件的內容
 */
@Test
public void cat() throws Exception {
    // 讀取文件
    FSDataInputStream in = fileSystem.open(new Path("/hdfsapi/test/a.txt"));
    // 將文件內容輸出到控制臺上,第三個參數表示輸出多少字節的內容
    IOUtils.copyBytes(in, System.out, 1024);
    in.close();
}

現在創建目錄、文件以及讀取文件內容都知道如何操作了,或許我們還需要知道如何重命名文件,如下示例:

/**
 * 重命名文件
 */
@Test
public void rename() throws Exception {
    Path oldPath = new Path("/hdfsapi/test/a.txt");
    Path newPath = new Path("/hdfsapi/test/b.txt");
    // 第一個參數是原文件的名稱,第二個則是新的名稱
    fileSystem.rename(oldPath, newPath);
}

增、查、改我們都已經知道如何操作了,就差最后一個刪除的操作了,如下示例:

/**
 * 刪除文件
 * @throws Exception
 */
@Test
public void delete()throws Exception{
    // 第二個參數指定是否要遞歸刪除,false=否,true=是
    fileSystem.delete(new Path("/hdfsapi/test/mysql_cluster.iso"), false);
}

對文件的增、刪、查、改都介紹完了,下面我們來看看如何上傳本地文件到HDFS文件系統中,我這里有一個local.txt文件,文件內容如下:

This is a local file

編寫測試代碼如下:

/**
 * 上傳本地文件到HDFS
 */
@Test
public void copyFromLocalFile() throws Exception {
    Path localPath = new Path("E:/local.txt");
    Path hdfsPath = new Path("/hdfsapi/test/");
    // 第一個參數是本地文件的路徑,第二個則是HDFS的路徑
    fileSystem.copyFromLocalFile(localPath, hdfsPath);
}

執行以上的方法成功后,我們到HDFS上,看看是否拷貝成功:

[root@localhost ~]# hdfs dfs -ls /hdfsapi/test/
Found 2 items
-rw-r--r--   3 root supergroup         12 2018-03-25 22:33 /hdfsapi/test/b.txt
-rw-r--r--   3 root supergroup         20 2018-03-25 22:45 /hdfsapi/test/local.txt
[root@localhost ~]# hdfs dfs -text /hdfsapi/test/local.txt
This is a local file
[root@localhost ~]# 

以上演示了上傳一個小的文件,但是如果我需要上傳一個比較大的文件,并且還希望有個進度條的話,就得使用以下這個種方式了:

/**
 * 上傳大體積的本地文件到HDFS,并顯示進度條
 */
@Test
public void copyFromLocalFileWithProgress() throws Exception {
    InputStream in = new BufferedInputStream(new FileInputStream(new File("E:/Linux Install/mysql_cluster.iso")));
    FSDataOutputStream outputStream = fileSystem.create(new Path("/hdfsapi/test/mysql_cluster.iso"), new Progressable() {
        public void progress() {
            // 進度條的輸出
            System.out.print(".");
        }
    });
    IOUtils.copyBytes(in, outputStream, 4096);
    in.close();
    outputStream.close();
}

同樣的,執行以上的方法成功后,我們到HDFS上,看看是否上傳成功:

[root@localhost ~]# hdfs dfs -ls -h /hdfsapi/test/
Found 3 items
-rw-r--r--   3 root supergroup         12 2018-03-25 22:33 /hdfsapi/test/b.txt
-rw-r--r--   3 root supergroup         20 2018-03-25 22:45 /hdfsapi/test/local.txt
-rw-r--r--   3 root supergroup    812.8 M 2018-03-25 23:01 /hdfsapi/test/mysql_cluster.iso
[root@localhost ~]#

既然有上傳文件自然就有下載文件,而且上傳文件的方式有兩種。所以下載文件的方式也有兩種,如下示例:

/**
 * 下載HDFS文件1
 * 
 */
@Test
public void copyToLocalFile1() throws Exception {
    Path localPath = new Path("E:/b.txt");
    Path hdfsPath = new Path("/hdfsapi/test/b.txt");
    fileSystem.copyToLocalFile(hdfsPath, localPath);
}

/**
 * 下載HDFS文件2
 *
 */
@Test
public void copyToLocalFile2() throws Exception {
    FSDataInputStream in = fileSystem.open(new Path("/hdfsapi/test/b.txt"));
    OutputStream outputStream = new FileOutputStream(new File("E:/b.txt"));
    IOUtils.copyBytes(in, outputStream, 1024);
    in.close();
    outputStream.close();
}
  • 注意:以上演示的第一種下載方式在windows操作系統上可能會報空指針錯誤,在windows上建議使用第二種方式

下面我們來演示一下如何列出某個目錄下的所有文件,示例:

/**
 * 查看某個目錄下所有的文件
 *
 * @throws Exception
 */
@Test
public void listFiles() throws Exception {
    FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/hdfsapi/test/"));
    for (FileStatus fileStatus : fileStatuses) {
        System.out.println("這是一個:" + (fileStatus.isDirectory() ? "文件夾" : "文件"));
        System.out.println("副本系數:" + fileStatus.getReplication());
        System.out.println("大小:" + fileStatus.getLen());
        System.out.println("路徑:" + fileStatus.getPath() + "\n");
    }
}

控制臺打印結果如下:

這是一個:文件
副本系數:3
大小:12
路徑:hdfs://192.168.77.130:8020/hdfsapi/test/b.txt

這是一個:文件
副本系數:3
大小:20
路徑:hdfs://192.168.77.130:8020/hdfsapi/test/local.txt

這是一個:文件
副本系數:3
大小:852279296
路徑:hdfs://192.168.77.130:8020/hdfsapi/test/mysql_cluster.iso

注意,從控制臺打印結果中,我們可以看到一個問題:我們之前已經在hdfs-site.xml中設置了副本系數為1,為什么此時查詢文件看到的系數是3呢?

其實這是因為這幾個文件都是我們在本地通過Java API上傳上去的,在本地我們并沒有設置副本系數,所以這時就會使用Hadoop的默認副本系數:3。

如果我們是在服務器上,通過hdfs命令put上去的,那么才會采用我們在配置文件中設置的副本系數。不信的話,可以在代碼中將路徑修改為根目錄,這時控制臺輸出如下:

這是一個:文件
副本系數:1
大小:311585484
路徑:hdfs://192.168.77.130:8020/hadoop-2.6.0-cdh6.7.0.tar.gz

這是一個:文件夾
副本系數:0
大小:0
路徑:hdfs://192.168.77.130:8020/hdfsapi

這是一個:文件
副本系數:1
大小:49
路徑:hdfs://192.168.77.130:8020/hello.txt

根目錄下的文件都是我們之前通過hdfs命令put上去,所以這些文件的副本系數才是我們在配置文件中設置的副本系數。


HDFS寫數據流程

關于HDFS寫數據流程,我在網絡上找到一篇描述非常簡潔易懂的漫畫形式講解HDFS的原理,作者不詳。比一般PPT要通俗易懂很多,是難得的學習資料,特此摘錄到本文中。

1、三個部分: 客戶端、NameNode(可理解為主控和文件索引類似linux的inode)、DataNode(存放實際數據的存server)
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

2、HDFS寫數據過程:
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程


HDFS讀取數據流程

3、讀取數據過程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

4、容錯:第一部分:故障類型及其檢測方法(nodeserver 故障,和網絡故障,和臟數據問題)
Java操作HDFS開發環境搭建以及HDFS的讀寫流程
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

5、容錯第二部分:讀寫容錯
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

6、容錯第三部分:dataNode 失效
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

7、備份規則
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

8、結束語
Java操作HDFS開發環境搭建以及HDFS的讀寫流程

關于這個漫畫還有一個中文版的,地址如下:

https://www.cnblogs.com/raphael5200/p/5497218.html


HDFS文件系統的優缺點

HDFS優點:

  • 數據冗余(多副本存儲)、硬件容錯
  • 處理流式的數據訪問,一次寫入多次讀取
  • 適合存儲大文件
  • 可以構建在廉價機器上,節省成本

HDFS缺點:

  • 不適合低延遲數據訪問
  • 無法高效存儲大量小文件
    • 因為即便只有1M的文件,也是擁有自己的元數據的。所以如果存在大量的小文件,那么相對應的元數據需要占用的存儲空間就越大,元數據過多會給NameNode增加壓力
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

漾濞| 拜城县| 河西区| 沙坪坝区| 仲巴县| 荔波县| 桂东县| 鹤峰县| 临沧市| 澄江县| 连平县| 齐齐哈尔市| 垣曲县| 台南县| 历史| 高尔夫| 龙山县| 昌吉市| 简阳市| 互助| 景德镇市| 信阳市| 屏东市| 西贡区| 比如县| 微博| 汉川市| 会昌县| 麻栗坡县| 玛多县| 准格尔旗| 阳谷县| 阜阳市| 饶平县| 塘沽区| 东乌珠穆沁旗| 甘孜县| 新密市| 伊宁市| 多伦县| 福贡县|