大數(shù)據(jù) | Java 操作 HDFS 常用 API
早期文章

? ? ? ? 上篇文章介紹了關(guān)于 HDFS 的常用命令,其常用的命令都有相應(yīng)的 API,用命令可以完成的功能,使用 Java API 也可以完成。本文介紹關(guān)于 HDFS 常用的 Java API。
一、回顧常用的命令
? ? ? ? 在上篇文章中整理了 HDFS 常用的命令,這里進(jìn)行簡單的回顧。
? ? ? ? ls 命令用來查看 HDFS 系統(tǒng)中的目錄和文件,命令如下:
$?hadoop?fs?-ls?/? ? ? ? put 命令用來將本地文件上傳到 HDFS 系統(tǒng)中,命令如下:
$?hadoop?fs?-put?test.txt?/? ? ? ? moveFromLocal 命令將本地文件移動(dòng)到 HDFS 文件系統(tǒng)中,并將本地的文件進(jìn)行刪除,命令如下:
$ hadoop fs -moveFromLocal abc.txt /? ? ? ? get 命令用來將 HDFS 文件系統(tǒng)中的文件下載到本地,命令如下:
$ hadoop fs -get /abc.txt /home/hadoop/? ? ? ? rm 命令用來刪除 HDFS?系統(tǒng)中的文件或文件夾,命令如下
$ hadoop fs -rm /test.txt? ? ? ? mkdir 命令用來在 HDFS 系統(tǒng)中創(chuàng)建目錄,命令如下:
$ hadoop fs -mkdir /test? ? ? ? cp 命令在 HDFS 系統(tǒng)中用于文件的復(fù)制,命令如下:
$ hadoop fs -ls /? ? ? ? mv 命令在 HDFS 系統(tǒng)中用于完成文件移動(dòng)的功能,也可以用來進(jìn)行文件的重命名功能,命令如下:
$ hadoop?fs?-mv?/abc/abc.txt?/test/$ hadoop fs -mv /test/abc.txt /test/abcabc.txt
? ? ? ? cat 命令在 HDFS 文件系統(tǒng)中用于輸出某個(gè)文件的內(nèi)容,命令如下:
$?hadoop?fs?-cat?/test/abcabc.txt? ? ? ? appendToFile 命令將單個(gè)或多個(gè)文件的內(nèi)容從本地系統(tǒng)中追加到 HDFS 系統(tǒng)的文件中,命令如下:
hadoop fs -appendToFile abc.txt /abc.txt? ? ? ? 上面的內(nèi)容簡單的對 HDFS 文件系統(tǒng)的常用命令進(jìn)行了回顧,接下來,我們來整理一下關(guān)于 HDFS 常用的 Java API。
二、引入依賴
? ? ? ??使用 HDFS 的 Java API 可以操作 HDFS 文件系統(tǒng)中的文件,比如文件的新建、刪除、讀取等。創(chuàng)建一個(gè) Maven 的項(xiàng)目,然后引入其依賴,準(zhǔn)備工作就算是完成了,依賴如下:
org.apache.hadoop hadoop-client 2.8.2
? ? ? ? 引入該依賴后,在 HDFS 的 Java API 中使用 FileSystem 工具類,它可以完成我們的操作,下面我們來進(jìn)行了解。
三、文件列表
? ? ? ?代碼非常的簡單,因此這里直接上代碼,代碼如下:
public static void main(String[] args) throws IOException {Configuration conf = new Configuration();// 設(shè)置 HDFS 訪問地址conf.set("fs.default.name", "hdfs://centos01:9000");// 取得 FileSystem 文件系統(tǒng)實(shí)例FileSystem fs = FileSystem.get(conf);ListfilesUnderFolder = HdfsFileSystem.getFileList(fs, new Path("hdfs:/")); filesUnderFolder.forEach(System.out::println);}public static ListgetFileList(FileSystem fs, Path folderPath) throws IOException { Listpaths = new ArrayList(); if (fs.exists(folderPath)) {FileStatus[] fileStatus = fs.listStatus(folderPath);for (int i = 0; i < fileStatus.length; i++) {FileStatus fileStatu = fileStatus[i];paths.add(fileStatu.getPath().toString());}}return paths;}
? ? ? ? 上面的代碼中,在自定義的方法 getFileList 中通過 FileSystem 類的 listStatus() 方法返回了 HDFS 文件系統(tǒng) /?目錄下的所有文件和目錄,輸出內(nèi)容如下:
hdfs://centos01:9000/abchdfs://centos01:9000/abc.txthdfs://centos01:9000/depInputhdfs://centos01:9000/depOutputhdfs://centos01:9000/inputhdfs://centos01:9000/outputhdfs://centos01:9000/scoreInputhdfs://centos01:9000/scoreOutputhdfs://centos01:9000/secondInputhdfs://centos01:9000/secondOutputhdfs://centos01:9000/testhdfs://centos01:9000/tmp
? ? ? ??上面的輸出則是我虛擬機(jī)中 HDFS 中的文件列表。如果需要顯示其他目錄下的文件和目錄列表,只需要傳入相應(yīng)的路徑即可。如果要顯示全部文件,只需要判斷是否為目錄,如果為目錄直接遞歸調(diào)用就可以了。
四、創(chuàng)建目錄
? ? ? ? 創(chuàng)建目錄使用 FileSystem 類的 mkdirs 方法即可完成,代碼如下:
public static void main(String[] args) throws IOException {String path = "hdfs:/hdfsDir";HdfsFileSystem.createDir(path);}/*** 創(chuàng)建 HDFS 目錄 mydir*/public static void createDir(String pathString) throws IOException {Configuration conf = new Configuration();conf.set("fs.default.name", "hdfs://centos01:9000");org.apache.hadoop.fs.FileSystem fs = org.apache.hadoop.fs.FileSystem.get(conf);// 創(chuàng)建目錄boolean created = fs.mkdirs(new Path(pathString));if (created) {System.out.println("創(chuàng)建目錄成功");} else {System.out.println("創(chuàng)建目錄失敗");}fs.close();}
? ? ? ? mkdirs 方法的返回類型是 boolean 類型,返回 true 表示創(chuàng)建成功,返回 false 表示創(chuàng)建失敗。使用 HDFS 的命令來進(jìn)行查看,命令如下:
$ hadoop fs -ls / | grep hdfsDirdrwxr-xr-x - Administrator supergroup 0 2021-11-12 10:09 /hdfsDir
? ? ? ? 可以看到,/hdfsDir 目錄被創(chuàng)建成功。
五、文件的創(chuàng)建
? ? ? ? 文件的創(chuàng)建使用 FileSystem 類的 create 方法即可完成文件的創(chuàng)建,代碼如下:
public static void main(String[] args) throws IOException {String path = "hdfs:/fileAbc.txt";String context = "1234";HdfsFileSystem.createFile(path, context);}/*** 定義創(chuàng)建文件方法*/public static void createFile(String pathString, String context) throws IOException {Configuration conf = new Configuration();conf.set("fs.default.name", "hdfs://centos01:9000");FileSystem fs = FileSystem.get(conf);// 打開一個(gè)輸出流FSDataOutputStream outputStream = fs.create(new Path(pathString));// 寫入文件內(nèi)容outputStream.write(context.getBytes());outputStream.close();fs.close();System.out.println("文件創(chuàng)建成功");}
? ? ? ??上面的代碼在 HDFS 的根目錄下創(chuàng)建了一個(gè)名為 fileAbc.txt 的文件,并向文件內(nèi)寫入了 1234 這樣的內(nèi)容,通過命令來查看該文件是否創(chuàng)建成功,內(nèi)容是否寫入成功,命令如下:
$ hadoop fs -ls / | grep fileAbc-rw-r--r-- 3 Administrator supergroup 4 2021-11-12 10:17 /fileAbc.txt$ hadoop fs -cat /fileAbc.txt1234
六、文件內(nèi)容的輸出
? ? ? ? 文件內(nèi)容的輸出使用 FileSystem 類的 open 方法,使用輸入流進(jìn)行讀取即可。代碼如下:
public static void main(String[] args) throws IOException {String path = "hdfs:/fileAbc.txt";????HdfsFileSystem.fileSystemCat(path);}/*** 查詢 HDFS 文件內(nèi)容并輸出*/public static void fileSystemCat(String pathString) throws IOException {Configuration conf = new Configuration();// 設(shè)置 HDFS 訪問地址conf.set("fs.default.name", "hdfs://centos01:9000");// 取得 FileSystem 文件系統(tǒng)實(shí)例FileSystem fs = FileSystem.get(conf);// 打開文件輸入流InputStream in = fs.open(new Path(pathString));// 輸出文件內(nèi)容IOUtils.copyBytes(in, System.out, 4096, false);// 關(guān)閉輸入流IOUtils.closeStream(in);}
? ? ? ? 運(yùn)行代碼即可看到文件的內(nèi)容被輸出,輸出如下:
1234七、刪除文件
? ? ? ? 文件的刪除使用 FileSystem 類的 deleteOnExit 方法,代碼如下:
public static void main(String[] args) throws IOException {String path = "hdfs:/fileAbc.txt";HdfsFileSystem.deleteFile(path);}/*** 刪除文件*/public static void deleteFile(String pathString) throws IOException {Configuration conf = new Configuration();conf.set("fs.default.name", "hdfs://centos01:9000");FileSystem fs = FileSystem.get(conf);Path path = new Path(pathString);// 刪除文件boolean isok = fs.deleteOnExit(path);if (isok) {System.out.println("刪除成功");} else {System.out.println("刪除失敗");}fs.close();}
? ? ? ? 通過命令進(jìn)行查看,文件已經(jīng)被刪除了。
八、讀取文件/目錄的元數(shù)據(jù)
? ? ? ??讀取文件/目錄的元數(shù)據(jù)使用 FileSystem 類的 getFileStatus 方法即可完成,代碼如下:
public static void main(String[] args) throws IOException {String path = "hdfs:/fileAbc.txt";String context = "1234";HdfsFileSystem.createFile(path, context);HdfsFileSystem.fileStatusCat(path);}/*** 獲取文件或目錄的元數(shù)據(jù)信息*/public static void fileStatusCat(String pathString) throws IOException {// 創(chuàng)建 Configuration 對象Configuration conf = new Configuration();// 設(shè)置 HDFS 訪問地址conf.set("fs.default.name", "hdfs://centos01:9000");// 取得 FileSystem 文件系統(tǒng)實(shí)例FileSystem fs = FileSystem.get(conf);FileStatus fileStatus = fs.getFileStatus(new Path(pathString));// 判斷是文件夾還是文件if (fileStatus.isDirectory()) {System.out.println("這是一個(gè)文件夾");} else {System.out.println("這是一個(gè)文件");}// 輸出元數(shù)據(jù)信息System.out.println("文件路徑:" + fileStatus.getPath());System.out.println("文件修改日期:" + new Timestamp(fileStatus.getModificationTime()).toString());System.out.println("文件上次訪問日期:" + new Timestamp(fileStatus.getAccessTime()).toString());System.out.println("文件長度:" + fileStatus.getLen());System.out.println("文件備份數(shù):" + fileStatus.getReplication());System.out.println("文件塊大小:" + fileStatus.getBlockSize());System.out.println("文件所有者:" + fileStatus.getOwner());System.out.println("文件所在分組:" + fileStatus.getGroup());System.out.println("文件的權(quán)限:" + fileStatus.getPermission().toString());}
? ? ? ? 通過 FileStatus 可以得到文件的各種信息,上面的輸出內(nèi)容如下:
這是一個(gè)文件文件路徑:hdfs://centos01:9000/fileAbc.txt文件修改日期:2021-11-12 11:02:12.797文件上次訪問日期:2021-11-12 11:02:12.438文件長度:4文件備份數(shù):3文件塊大小:134217728文件所有者:Administrator文件所在分組:supergroup文件的權(quán)限:rw-r--r--
? ? ? ? 這里,我們獲取了文件的路徑、修改日期、上次訪問日期、文件長度等信息。
九、上傳本地文件到 HDFS
? ? ? ??上傳文件使用?FileSystem 類的?copyFromLocalFile 即可完成,代碼如下:
public static void main(String[] args) throws IOException {HdfsFileSystem.uploadFileToHDFS("d:/mysql.docx", "hdfs:/");}/*** 上傳本地文件到 HDFS*/public static void uploadFileToHDFS(String srcPath, String dstPath) throws IOException {// 創(chuàng)建配置器Configuration conf = new Configuration();conf.set("fs.default.name", "hdfs://centos01:9000");// 取得 FileSystem 文件系統(tǒng)實(shí)例FileSystem fs = FileSystem.get(conf);// 創(chuàng)建可供 hadoop 使用的文件系統(tǒng)路徑// 本地目錄/文件Path src = new Path(srcPath);// HDFS 目錄/文件Path dst = new Path(dstPath);// 復(fù)制上傳文帝文件至 HDFS 文件系統(tǒng)中fs.copyFromLocalFile(src, dst);System.out.println("文件上傳成功");}
? ? ? ? 通過命令來查看上傳的情況,命令如下:
hadoop fs -ls / | grep mysql-rw-r--r-- 3 Administrator supergroup 1470046 2021-11-12 11:06 /mysql.docx
十、下載 HDFS 文件到本地
? ? ? ??下載 HDFS 文件到本地使用 FileSystem 類的?copyToLocalFile 方法即可,代碼如下:
public static void main(String[] args) throws IOException {HdfsFileSystem.downloadFileToLocal("hdfs:/mysql.docx", "d:/test.docx");}/*** 下載文件到本地*/public static void downloadFileToLocal(String srcPath, String dstPath) throws IOException {// 創(chuàng)建配置器Configuration conf = new Configuration();conf.set("fs.default.name", "hdfs://centos01:9000");// 取得 FileSystem 文件系統(tǒng)實(shí)例FileSystem fs = FileSystem.get(conf);// 創(chuàng)建可供 hadoop 使用的文件系統(tǒng)路徑Path src = new Path(srcPath);Path dst = new Path(dstPath);// 從 HDFS 文件系統(tǒng)中復(fù)制下載文件至本地fs.copyToLocalFile(false, src, dst, true);System.out.println("文件下載成功");}
? ? ? ? 到本地的 D 盤進(jìn)行查看,文件已經(jīng)下載成功。
十一、總結(jié)
? ? ? ? HDFS 是 Hadoop 項(xiàng)目中的核心模塊,使用 HDFS 的 Java API 操作 HDFS 非常的方便也比較簡單。不知道大家注意到了么,HDFS 作為文件系統(tǒng),它可以完成對 文件的 增加、追加、刪除、查看 等功能,但是,竟然沒有對文件進(jìn)行修改的功能。這是 HDFS 有別于其他文件系統(tǒng)的一個(gè)特點(diǎn),HDFS 的作者是出于什么樣的目的如此設(shè)計(jì)呢?留著以后討論吧!

公眾號內(nèi)回復(fù)?【mongo】 下載 SpringBoot 整合操作 MongoDB 的文檔。
? ? ? ? 之前整理的關(guān)于 Redis 的文章:
Redis | Redis Pub/Sub相關(guān)命令
Redis | 基礎(chǔ)數(shù)據(jù)類型應(yīng)用場景
