更新時間:2021年08月12日11時56分 來源:傳智教育 瀏覽次數(shù):
本節(jié)將通過Java API來演示如何操作HDFS文件系統(tǒng),包括文件上傳與下載以及目錄操作等,具體介紹如下:
1.搭建項目環(huán)境
打開Eclipse選擇FileàNewàMaven Project創(chuàng)建Maven工程,選擇“Create a simple project ”選項,點擊【Next】按鈕,會進入“New Maven Project”界面,如圖1所示。
圖1 創(chuàng)建Maven工程
在圖1中,勾選“Create a simple project(skip archetype selection)”表示創(chuàng)建一個簡單的項目(跳過對原型模板的選擇),然后勾選“User default Workspace location”表示使用本地默認的工作空間之后,點擊【Next】按鈕,如圖2所示。
圖2 創(chuàng)建Maven工程配置
在圖2中,GroupID也就是項目組織唯一的標識符,實際對應Java的包結構,這里輸入com.itcast。ArtifactID就是項目的唯一標識符,實際對應項目的名稱,就是項目根目錄的名稱,這里輸入HadoopDemo,打包方式這里選擇Jar包方式即可,后續(xù)創(chuàng)建Web工程選擇War包。
此時Maven工程已經(jīng)被創(chuàng)建好了,會發(fā)現(xiàn)在Maven項目中,有一個pom.xml的配置文件,這個配置文件就是對項目進行管理的核心配置文件。
使用Java API操作HDFS需要用到hadoop-common、hadoop-hdfs、hadoop-client三種依賴,同時為了進行單元測試,還要引入junit的測試包,具體代碼如文件所示。
文件 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>``` 當添加依賴完畢后,Hadoop相關Jar包就會自動下載,部分Jar包如圖3所示。 ![img](uploads/course/bigData/images/3.4.2/clip_image006-1591775346489.jpg) > 圖3 成功導入Jar包 從圖3可以看出,所需要的Hadoop的Jar包所在路徑就是setting.xml中配置的本地倉庫位置。 **2****.初始化客戶端對象** 首先在項目src文件夾下創(chuàng)建com.itcast.hdfsdemo包,并在該包下創(chuàng)建HDFS_CRUD.java文件,編寫Java測試類,構建Configuration和FileSystem對象,初始化一個客戶端實例進行相應的操作,具體代碼如文件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 { // 構造一個配置參數(shù)對象,設置一個參數(shù):我們要訪問的hdfs的URI Configuration conf = new Configuration(); // 這里指定使用的是HDFS文件系統(tǒng) **conf.set("fs.defaultFS", "hdfs://hadoop01:9000")**; // 通過如下的方式進行客戶端身份的設置 **System.setProperty("HADOOP_USER_NAME", "root")**; // 通過FileSystem的靜態(tài)方法獲取文件系統(tǒng)客戶端對象 fs = FileSystem.get(conf); } }
在上述代碼中,@Before是一個用于在Junit單元測試框架中控制程序最先執(zhí)行的注解,這里可以保證init()方法在程序中最先執(zhí)行。
小提示:
FileSystem.get()方法從conf中的設置的參數(shù) fs.defaultFS的配置值,用來設置文件系統(tǒng)類型。如果代碼中沒有指定為fs.defaultFS,并且工程classpath下也沒有給定相應的配置,則conf中的默認值就來自于hadoop-common-2.7.4.jar包中的core-default.xml,默認值為:“file:/// ”,這樣獲取的不是DistributedFileSystem實例,而是一個本地文件系統(tǒng)的客戶端對象。
3.上傳文件到HDFS
初始化客戶端對象后,接下來實現(xiàn)上傳文件到HDFS的功能。由于采用Java測試類來實現(xiàn)JavaApi對HDFS的操作,因此可以在HDFS_CRUD.java文件中添加一個testAddFileToHdfs()方法來演示本地文件上傳到HDFS的示例,具體代碼如下:
@Test public void testAddFileToHdfs() throws IOException { // 要上傳的文件所在本地路徑 Path src = new Path("D:/test.txt"); // 要上傳到hdfs的目標路徑 Path dst = new Path("/testFile"); // 上傳文件方法 fs.copyFromLocalFile(src, dst); // 關閉資源 fs.close(); }
從上述代碼可以看出,可以通過FileSystem對象的copyFromLocalFile()方法,將本地數(shù)據(jù)上傳至HDFS中。copyFromLocalFile()方法接收兩個參數(shù),第一個參數(shù)是要上傳的文件所在的本地路徑(需要提前創(chuàng)建),第二個參數(shù)是要上傳到HDFS的目標路徑。
4.從HDFS下載文件到本地
在HDFS_CRUD.java文件中添加一個testDownloadFileToLocal()方法,來實現(xiàn)從HDFS中下載文件到本地系統(tǒng)的功能,具體代碼如下:
// 從hdfs中復制文件到本地文件系統(tǒng) @Test public void testDownloadFileToLocal() throws IllegalArgumentException, IOException { // 下載文件 fs.copyToLocalFile(new Path("/testFile"), new Path("D:/")); fs.close(); }
從上述代碼可以看出,可以通過FileSystem對象的copyToLocalFile()方法從HDFS上下載文件到本地。copyToLocalFile()方法接收兩個參數(shù),第一個參數(shù)是HDFS上的文件路徑,第二個參數(shù)是下載到本地的目標路徑。
注意:
在Windows平臺開發(fā)HDFS項目時,若不設置Hadoop開發(fā)環(huán)境,則會報以下的錯誤:
java.io.IOException: (null) entry in command string: null chmod 0644 D:\testFile
解決方式:
(1)根據(jù)教材提示,安裝配置windows平臺hadoop(注意,配置后必須重啟電腦),運行沒有問題。
(2)直接使用下載的hadoop linux平臺下的壓縮包進行解壓,然后在解壓包bin目錄下額外添加windows相關依賴文件(winutils.exe、winutils.pdb、hadoop.dll),然后進行hadoop環(huán)境變量配置(注意,配置后必須重啟電腦),運行同樣沒有問題。
(3)使用FileSystem自帶的方法即使不配置windows平臺hadoop也可以正常運行(這種方法下載后就是沒有附帶一個類似.testFile.crc的校驗文件):
fs.copyToLocalFile(false,new Path("/testFile"), new Path("D:/"),true);
5.目錄操作
在HDFS_CRUD.java文件中添加一個testMkdirAndDeleteAndRename()方法,實現(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); }
從上述代碼可以看出,可以通過調(diào)用FileSystem的mkdirs()方法創(chuàng)建新的目錄;調(diào)用delete()方法可以刪除文件夾,delete()方法接收兩個參數(shù),第一個參數(shù)表示要刪除的文件夾路徑,第二個參數(shù)用于設置是否遞歸刪除目錄,其值為true或false,true表示遞歸刪除,false表示非遞歸刪除;調(diào)用rename()方法可以對文件或文件夾重命名,rename()接收兩個參數(shù),第一個參數(shù)代表需要修改的目標路徑,第二個參數(shù)代表新的命名。
6.查看目錄中的文件信息
在HDFS_CRUD.java文件中添加一個testListFiles()方法,實現(xiàn)查看目錄中所有文件的詳細信息的功能,代碼如下:
// 查看目錄信息,只顯示文件 @Test public void testListFiles() throws FileNotFoundException, IllegalArgumentException, IOException { // 獲取迭代器對象 RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles( new Path("/"), true); while (listFiles.hasNext()) { LocatedFileStatus fileStatus = listFiles.next(); // 打印當前文件名 System.out.println(fileStatus.getPath().getName()); // 打印當前文件塊大小 System.out.println(fileStatus.getBlockSize()); // 打印當前文件權限 System.out.println(fileStatus.getPermission()); // 打印當前文件內(nèi)容長度 System.out.println(fileStatus.getLen()); // 獲取該文件塊信息(包含長度,數(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()方法獲取文件列表,其中第一個參數(shù)表示需要獲取的目錄路徑,第二個參數(shù)表示是否遞歸查詢,這里傳入?yún)?shù)為true,表示需要遞歸查詢。
猜你喜歡: