教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢/投訴熱線:400-618-4000

如何使用Java API操作HDFS系統(tǒng)?

更新時(shí)間:2021年08月12日11時(shí)56分 來(lái)源:傳智教育 瀏覽次數(shù):

本節(jié)將通過(guò)Java API來(lái)演示如何操作HDFS文件系統(tǒng),包括文件上傳與下載以及目錄操作等,具體介紹如下:

1.搭建項(xiàng)目環(huán)境

打開(kāi)Eclipse選擇FileàNewàMaven Project創(chuàng)建Maven工程,選擇“Create a simple project ”選項(xiàng),點(diǎn)擊【Next】按鈕,會(huì)進(jìn)入“New Maven Project”界面,如圖1所示。

使用Java API操作HDFS

圖1 創(chuàng)建Maven工程

在圖1中,勾選“Create a simple project(skip archetype selection)”表示創(chuàng)建一個(gè)簡(jiǎn)單的項(xiàng)目(跳過(guò)對(duì)原型模板的選擇),然后勾選“User default Workspace location”表示使用本地默認(rèn)的工作空間之后,點(diǎn)擊【Next】按鈕,如圖2所示。

使用Java API操作HDFS

圖2 創(chuàng)建Maven工程配置

在圖2中,GroupID也就是項(xiàng)目組織唯一的標(biāo)識(shí)符,實(shí)際對(duì)應(yīng)Java的包結(jié)構(gòu),這里輸入com.itcast。ArtifactID就是項(xiàng)目的唯一標(biāo)識(shí)符,實(shí)際對(duì)應(yīng)項(xiàng)目的名稱,就是項(xiàng)目根目錄的名稱,這里輸入HadoopDemo,打包方式這里選擇Jar包方式即可,后續(xù)創(chuàng)建Web工程選擇War包。

此時(shí)Maven工程已經(jīng)被創(chuàng)建好了,會(huì)發(fā)現(xiàn)在Maven項(xiàng)目中,有一個(gè)pom.xml的配置文件,這個(gè)配置文件就是對(duì)項(xiàng)目進(jìn)行管理的核心配置文件。

使用Java API操作HDFS需要用到hadoop-common、hadoop-hdfs、hadoop-client三種依賴,同時(shí)為了進(jìn)行單元測(cè)試,還要引入junit的測(cè)試包,具體代碼如文件所示。

文件 pom.xml

   <?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.itcast</groupId>
    <artifactId>HadoopDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
   **<dependencies>**
      **<dependency>**
        **<groupId>org.apache.hadoop</groupId>**
        **<artifactId>hadoop-common</artifactId>**
        **<version>2.7.4</version>**
      **</dependency>**
      **<dependency>**
        **<groupId>org.apache.hadoop</groupId>**
        **<artifactId>hadoop-hdfs</artifactId>**
        **<version>2.7.4</version>**
      **</dependency>**
      **<dependency>**
        **<groupId>org.apache.hadoop</groupId>**
        **<artifactId>hadoop-client</artifactId>**
        **<version>2.7.4</version>**
      **</dependency>**
      **<dependency>**
        **<groupId>junit</groupId>**
        **<artifactId>junit</artifactId>**
        **<version>RELEASE</version>**
      **</dependency>**
    **</dependencies>**
  </project>```

當(dāng)添加依賴完畢后,Hadoop相關(guān)Jar包就會(huì)自動(dòng)下載,部分Jar包如圖3所示。

![img](uploads/course/bigData/images/3.4.2/clip_image006-1591775346489.jpg)

&gt; 圖3   成功導(dǎo)入Jar包

從圖3可以看出,所需要的Hadoop的Jar包所在路徑就是setting.xml中配置的本地倉(cāng)庫(kù)位置。

**2****.初始化客戶端對(duì)象**

首先在項(xiàng)目src文件夾下創(chuàng)建com.itcast.hdfsdemo包,并在該包下創(chuàng)建HDFS_CRUD.java文件,編寫(xiě)Java測(cè)試類,構(gòu)建Configuration和FileSystem對(duì)象,初始化一個(gè)客戶端實(shí)例進(jìn)行相應(yīng)的操作,具體代碼如文件3-2所示。

文件  HDFS_CRUD.java

```java
   package com.itcast.hdfsdemo;
   import java.io.*;
   import org.apache.hadoop.conf.Configuration;
   import org.apache.hadoop.fs.*;
   import org.junit.*;
   public class HDFS_CRUD {
     FileSystem fs = null;
     @Before
     public void init() throws Exception {
      // 構(gòu)造一個(gè)配置參數(shù)對(duì)象,設(shè)置一個(gè)參數(shù):我們要訪問(wèn)的hdfs的URI
      Configuration conf = new Configuration();
      // 這里指定使用的是HDFS文件系統(tǒng)
      **conf.set("fs.defaultFS", "hdfs://hadoop01:9000")**;
      // 通過(guò)如下的方式進(jìn)行客戶端身份的設(shè)置
      **System.setProperty("HADOOP_USER_NAME", "root")**;
      // 通過(guò)FileSystem的靜態(tài)方法獲取文件系統(tǒng)客戶端對(duì)象
      fs = FileSystem.get(conf);
    }
  }

在上述代碼中,@Before是一個(gè)用于在Junit單元測(cè)試框架中控制程序最先執(zhí)行的注解,這里可以保證init()方法在程序中最先執(zhí)行。

小提示:

FileSystem.get()方法從conf中的設(shè)置的參數(shù) fs.defaultFS的配置值,用來(lái)設(shè)置文件系統(tǒng)類型。如果代碼中沒(méi)有指定為fs.defaultFS,并且工程classpath下也沒(méi)有給定相應(yīng)的配置,則conf中的默認(rèn)值就來(lái)自于hadoop-common-2.7.4.jar包中的core-default.xml,默認(rèn)值為:“file:/// ”,這樣獲取的不是DistributedFileSystem實(shí)例,而是一個(gè)本地文件系統(tǒng)的客戶端對(duì)象。

3.上傳文件到HDFS

初始化客戶端對(duì)象后,接下來(lái)實(shí)現(xiàn)上傳文件到HDFS的功能。由于采用Java測(cè)試類來(lái)實(shí)現(xiàn)JavaApi對(duì)HDFS的操作,因此可以在HDFS_CRUD.java文件中添加一個(gè)testAddFileToHdfs()方法來(lái)演示本地文件上傳到HDFS的示例,具體代碼如下:

@Test
public void testAddFileToHdfs() throws IOException {
  // 要上傳的文件所在本地路徑
  Path src = new Path("D:/test.txt");
  // 要上傳到hdfs的目標(biāo)路徑
  Path dst = new Path("/testFile");
  // 上傳文件方法
  fs.copyFromLocalFile(src, dst);
  // 關(guān)閉資源
  fs.close();
}

從上述代碼可以看出,可以通過(guò)FileSystem對(duì)象的copyFromLocalFile()方法,將本地?cái)?shù)據(jù)上傳至HDFS中。copyFromLocalFile()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是要上傳的文件所在的本地路徑(需要提前創(chuàng)建),第二個(gè)參數(shù)是要上傳到HDFS的目標(biāo)路徑。

4.從HDFS下載文件到本地

在HDFS_CRUD.java文件中添加一個(gè)testDownloadFileToLocal()方法,來(lái)實(shí)現(xiàn)從HDFS中下載文件到本地系統(tǒng)的功能,具體代碼如下:

// 從hdfs中復(fù)制文件到本地文件系統(tǒng)

@Test
public void testDownloadFileToLocal() throws IllegalArgumentException,
  IOException {
  // 下載文件
  fs.copyToLocalFile(new Path("/testFile"), new Path("D:/"));
    fs.close();
}

從上述代碼可以看出,可以通過(guò)FileSystem對(duì)象的copyToLocalFile()方法從HDFS上下載文件到本地。copyToLocalFile()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)是HDFS上的文件路徑,第二個(gè)參數(shù)是下載到本地的目標(biāo)路徑。
注意:
在Windows平臺(tái)開(kāi)發(fā)HDFS項(xiàng)目時(shí),若不設(shè)置Hadoop開(kāi)發(fā)環(huán)境,則會(huì)報(bào)以下的錯(cuò)誤:

java.io.IOException: (null) entry in command string: null chmod 0644 D:\testFile

解決方式:

(1)根據(jù)教材提示,安裝配置windows平臺(tái)hadoop(注意,配置后必須重啟電腦),運(yùn)行沒(méi)有問(wèn)題。

(2)直接使用下載的hadoop linux平臺(tái)下的壓縮包進(jìn)行解壓,然后在解壓包bin目錄下額外添加windows相關(guān)依賴文件(winutils.exe、winutils.pdb、hadoop.dll),然后進(jìn)行hadoop環(huán)境變量配置(注意,配置后必須重啟電腦),運(yùn)行同樣沒(méi)有問(wèn)題。

(3)使用FileSystem自帶的方法即使不配置windows平臺(tái)hadoop也可以正常運(yùn)行(這種方法下載后就是沒(méi)有附帶一個(gè)類似.testFile.crc的校驗(yàn)文件):

fs.copyToLocalFile(false,new Path("/testFile"), new Path("D:/"),true);

5.目錄操作

在HDFS_CRUD.java文件中添加一個(gè)testMkdirAndDeleteAndRename()方法,實(shí)現(xiàn)目錄的創(chuàng)建、刪除、重命名的功能,具體代碼如下:

// 創(chuàng)建,刪除,重命名文件

@Test

public void testMkdirAndDeleteAndRename() throws Exception {
  // 創(chuàng)建目錄
  fs.mkdirs(new Path("/a/b/c"));
  fs.mkdirs(new Path("/a2/b2/c2"));
  // 重命名文件或文件夾
  fs.rename(new Path("/a"), new Path("/a3"));
  // 刪除文件夾,如果是非空文件夾,參數(shù)2必須給值true
  fs.delete(new Path("/a2"), true);
}

從上述代碼可以看出,可以通過(guò)調(diào)用FileSystem的mkdirs()方法創(chuàng)建新的目錄;調(diào)用delete()方法可以刪除文件夾,delete()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)表示要?jiǎng)h除的文件夾路徑,第二個(gè)參數(shù)用于設(shè)置是否遞歸刪除目錄,其值為true或false,true表示遞歸刪除,false表示非遞歸刪除;調(diào)用rename()方法可以對(duì)文件或文件夾重命名,rename()接收兩個(gè)參數(shù),第一個(gè)參數(shù)代表需要修改的目標(biāo)路徑,第二個(gè)參數(shù)代表新的命名。

6.查看目錄中的文件信息

在HDFS_CRUD.java文件中添加一個(gè)testListFiles()方法,實(shí)現(xiàn)查看目錄中所有文件的詳細(xì)信息的功能,代碼如下:

// 查看目錄信息,只顯示文件

@Test

public void testListFiles() throws FileNotFoundException,

  IllegalArgumentException, IOException {

  // 獲取迭代器對(duì)象

  RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(

                         new Path("/"), true);

  while (listFiles.hasNext()) {

    LocatedFileStatus fileStatus = listFiles.next();

    // 打印當(dāng)前文件名

    System.out.println(fileStatus.getPath().getName());

    // 打印當(dāng)前文件塊大小

    System.out.println(fileStatus.getBlockSize());

    // 打印當(dāng)前文件權(quán)限

    System.out.println(fileStatus.getPermission());

    // 打印當(dāng)前文件內(nèi)容長(zhǎng)度

    System.out.println(fileStatus.getLen());

    // 獲取該文件塊信息(包含長(zhǎng)度,數(shù)據(jù)塊,datanode的信息)

    BlockLocation[] blockLocations =

                   fileStatus.getBlockLocations();

    for (BlockLocation bl : blockLocations) {

      System.out.println("block-length:" + bl.getLength() + 

              "--" + "block-offset:" + bl.getOffset());

      String[] hosts = bl.getHosts();

      for (String host : hosts) {

        System.out.println(host);

      }

    }

System.out.println("-----------分割線-------------");

  }

}

在上述代碼中,可以調(diào)用FileSystem的listFiles()方法獲取文件列表,其中第一個(gè)參數(shù)表示需要獲取的目錄路徑,第二個(gè)參數(shù)表示是否遞歸查詢,這里傳入?yún)?shù)為true,表示需要遞歸查詢。










猜你喜歡:

HDFS分布式文件系統(tǒng)的優(yōu)點(diǎn)缺點(diǎn)分別是什么?

HDFS的高可用架構(gòu)是怎樣工作的?

HDFS存儲(chǔ)架構(gòu)中主從節(jié)點(diǎn)關(guān)系?工作原理是什么?

傳智教育Python大數(shù)據(jù)開(kāi)發(fā)高級(jí)軟件工程師培訓(xùn)

0 分享到:
和我們?cè)诰€交談!