Hadoop基礎-HDFS的API實現增刪改查
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
本篇博客開發IDE使用的是Idea,如果沒有安裝Idea軟件的可以去下載安裝,如何安裝IDE可以參考我的筆記:https://www.cnblogs.com/yinzhengjie/p/9080387.html。當然如果有小伙伴已經有自己使用習慣的IDE就不用更換了,只是配置好相應的Maven即可,我這里配置Maven是針對idea界面進行說明的。
一.將模塊添加maven框架支持
1>.點擊"Add Frameworks Support"
2>.添加Maven框架的支持
3>.在pom.xml中添加以下依賴關系
4>.啟用自動導入
5>.等待下載完成
6>.手動刷新Maven項目
二.將Linux服務器端的HDFS文件到項目中的resources目錄
1>.查看服務端配置文件
[yinzhengjie@s101 ~]$ more /soft/hadoop/etc/hadoop/core-site.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://s101:8020</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/yinzhengjie/hadoop</value> </property> </configuration> <!-- core-site.xml配置文件的作用: 用於定義系統級別的參數,如HDFS URL、Hadoop的臨時 目錄以及用於rack-aware集群中的配置文件的配置等,此中的參 數定義會覆蓋core-default.xml文件中的默認配置。 fs.defaultFS 參數的作用: #聲明namenode的地址,相當於聲明hdfs文件系統。 hadoop.tmp.dir 參數的作用: #聲明hadoop工作目錄的地址。 --> [yinzhengjie@s101 ~]$ sz /soft/hadoop/etc/hadoop/core-site.xml rz zmodem trl+C ȡ 100% 850 bytes 85 bytes/s 00:00:10 0 Errors [yinzhengjie@s101 ~]$
2>.將下載的文件拷貝到項目中resources目錄下
3>.查看下載的core-site.xml 文件內容
三.HDFS的API實現增刪改查
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.day01.note1; 7 8 import org.apache.hadoop.conf.Configuration; 9 import org.apache.hadoop.fs.FSDataInputStream; 10 import org.apache.hadoop.fs.FSDataOutputStream; 11 import org.apache.hadoop.fs.FileSystem; 12 import org.apache.hadoop.fs.Path; 13 import java.io.IOException; 14 15 public class HdfsDemo { 16 public static void main(String[] args) throws IOException { 17 insert(); 18 update(); 19 read(); 20 delete(); 21 } 22 23 //刪除文件 24 private static void delete() throws IOException { 25 //由於我的Hadoop完全分布式根目錄對yinzhengjie以外的用戶(盡管是root用戶也沒有寫入權限喲!因為是hdfs系統,並非Linux系統!)沒有寫入 26 // 權限,所以需要手動指定當前用戶權限。使用“HADOOP_USER_NAME”屬性就可以輕松搞定! 27 System.setProperty("HADOOP_USER_NAME","yinzhengjie"); 28 //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) 29 Configuration conf = new Configuration(); 30 //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 31 FileSystem fs = FileSystem.get(conf); 32 //這個path是指是需要在文件系統中寫入的數據,里面的字符串可以寫出“hdfs://s101:8020/yinzhengjie.sql”,但由於core-site.xml配置 33 // 文件中已經有“hdfs://s101:8020”字樣的前綴,因此我們這里可以直接寫文件名稱 34 Path path = new Path("/yinzhengjie.sql"); 35 //通過fs的delete方法可以刪除文件,第一個參數指的是刪除文件對象,第二參數是指遞歸刪除,一般用作刪除目錄 36 boolean res = fs.delete(path, true); 37 if (res == true){ 38 System.out.println("===================="); 39 System.out.println(path + "文件刪除成功!"); 40 System.out.println("===================="); 41 } 42 //釋放資源 43 fs.close(); 44 } 45 46 //將數據追加到文件內容中 47 private static void update() throws IOException { 48 //由於我的Hadoop完全分布式根目錄對yinzhengjie以外的用戶(盡管是root用戶也沒有寫入權限喲!因為是hdfs系統,並非Linux系統!)沒有寫入 49 // 權限,所以需要手動指定當前用戶權限。使用“HADOOP_USER_NAME”屬性就可以輕松搞定! 50 System.setProperty("HADOOP_USER_NAME","yinzhengjie"); 51 52 //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) 53 Configuration conf = new Configuration(); 54 //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 55 FileSystem fs = FileSystem.get(conf); 56 //這個path是指是需要在文件系統中寫入的數據,里面的字符串可以寫出“hdfs://s101:8020/yinzhengjie.sql”,但由於core-site.xml配置 57 // 文件中已經有“hdfs://s101:8020”字樣的前綴,因此我們這里可以直接寫文件名稱 58 Path path = new Path("/yinzhengjie.sql"); 59 //通過fs的append方法實現對文件的追加操作 60 FSDataOutputStream fos = fs.append(path); 61 //通過fos寫入數據 62 fos.write("\nyinzhengjie".getBytes()); 63 //釋放資源 64 fos.close(); 65 fs.close(); 66 67 } 68 69 //將數據寫入HDFS文件系統 70 private static void insert() throws IOException { 71 //由於我的Hadoop完全分布式根目錄對yinzhengjie以外的用戶(盡管是root用戶也沒有寫入權限喲!因為是hdfs系統,並非Linux系統!)沒有寫入 72 // 權限,所以需要手動指定當前用戶權限。使用“HADOOP_USER_NAME”屬性就可以輕松搞定! 73 System.setProperty("HADOOP_USER_NAME","yinzhengjie"); 74 75 //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) 76 Configuration conf = new Configuration(); 77 //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 78 FileSystem fs = FileSystem.get(conf); 79 //這個path是指是需要在文件系統中寫入的數據,里面的字符串可以寫出“hdfs://s101:8020/yinzhengjie.sql”,但由於core-site.xml配置 80 // 文件中已經有“hdfs://s101:8020”字樣的前綴,因此我們這里可以直接寫文件名稱 81 Path path = new Path("/yinzhengjie.sql"); 82 //通過fs的create方法創建一個文件輸出對象,第一個參數是hdfs的系統路徑,第二個參數是判斷第一個參數(也就是文件系統的路徑)是否存在,如果存在就覆蓋! 83 FSDataOutputStream fos = fs.create(path,true); 84 //通過fos寫入數據 85 fos.writeUTF("尹正傑"); 86 //釋放資源 87 fos.close(); 88 fs.close(); 89 } 90 91 //在HDFS文件系統中讀取數據 92 private static void read() throws IOException { 93 //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) 94 Configuration conf = new Configuration(); 95 //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 96 FileSystem fs = FileSystem.get(conf); 97 //這個path是指NameNode中的HDFS分布式系統中的路徑映射(注意,我這里寫的是主機名,你可以寫IP,如果是測試環境的話需要在hosts文件中添加主機名映射喲!) 98 Path path = new Path("hdfs://s101:8020/yinzhengjie.sql"); 99 //通過fs讀取數據 100 FSDataInputStream fis = fs.open(path); 101 int len = 0; 102 byte[] buf = new byte[4096]; 103 while ((len = fis.read(buf)) != -1){ 104 System.out.println(new String(buf, 0, len)); 105 } 106 } 107 } 108 109 110 /* 111 以上代碼執行結果如下: 112 尹正傑 113 yinzhengjie 114 ==================== 115 /yinzhengjie.sql文件刪除成功! 116 ==================== 117 */
四.HDFS的API實現文件拷貝(不需要我們自己實現數據流的拷貝,而是使用Hadoop自帶的IOUtils類實現)
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.day01.note1; 7 8 import org.apache.hadoop.conf.Configuration; 9 import org.apache.hadoop.fs.FSDataInputStream; 10 import org.apache.hadoop.fs.FileSystem; 11 import org.apache.hadoop.fs.Path; 12 import org.apache.hadoop.io.IOUtils; 13 14 import java.io.FileOutputStream; 15 import java.io.IOException; 16 17 public class HdfsDemo1 { 18 public static void main(String[] args) throws IOException { 19 get(); 20 } 21 22 //定義方法下載文件到本地 23 private static void get() throws IOException { 24 //由於我的Hadoop完全分布式根目錄對yinzhengjie以外的用戶(盡管是root用戶也沒有寫入權限喲!因為是hdfs系統,並非Linux系統!)沒有寫入 25 // 權限,所以需要手動指定當前用戶權限。使用“HADOOP_USER_NAME”屬性就可以輕松搞定! 26 System.setProperty("HADOOP_USER_NAME","yinzhengjie"); 27 //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) 28 Configuration conf = new Configuration(); 29 //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 30 FileSystem fs = FileSystem.get(conf); 31 //這個path是指是需要在文件系統中寫入的數據,里面的字符串可以寫出“hdfs://s101:8020/xrsync.sh”,但由於core-site.xml配置 32 // 文件中已經有“hdfs://s101:8020”字樣的前綴,因此我們這里可以直接寫相對路徑 33 Path path = new Path("/xrsync.sh"); 34 //通過fs的open方法獲取一個對象輸入流 35 FSDataInputStream fis = fs.open(path); 36 //創建一個對象輸出流 37 FileOutputStream fos = new FileOutputStream("yinzhengjie.sql"); 38 //通過Hadoop提供的IOUtiles工具類的copyBytes方法拷貝數據,第一個參數是需要傳一個輸入流,第二個參數需要傳入一個輸出流,第三個指定傳輸數據的緩沖區大小。 39 IOUtils.copyBytes(fis,fos,4096); 40 System.out.println("文件拷貝成功!"); 41 //別忘了釋放資源喲 42 fis.close(); 43 fos.close(); 44 fs.close(); 45 } 46 } 47 48 /* 49 以上代碼執行結果如下: 50 文件拷貝成功! 51 */
五.自定義塊大小寫入文件
配置Hadoop的最小blocksize,必須是512的倍數,有可能你會問為什么要設置大小是512的倍數呢?因為hdfs在寫入的過程中會進行校驗,每512字節進行依次校驗,因此需要設置是512的倍數。編輯“hdfs-site.xml”配置文件。
1>.服務器端hdfs的配置文件,修改默認的塊大小,默認塊大小是1048576字節,我們手動改為1024字節,配合過程如下:(別忘記重啟服務,修改配置文件一般都是需要重啟服務的喲)
[yinzhengjie@s101 ~]$ more `which xrsync.sh` #!/bin/bash #@author :yinzhengjie #blog:http://www.cnblogs.com/yinzhengjie #EMAIL:y1053419035@qq.com #判斷用戶是否傳參 if [ $# -lt 1 ];then echo "請輸入參數"; exit fi #獲取文件路徑 file=$@ #獲取子路徑 filename=`basename $file` #獲取父路徑 dirpath=`dirname $file` #獲取完整路徑 cd $dirpath fullpath=`pwd -P` #同步文件到DataNode for (( i=102;i<=104;i++ )) do #使終端變綠色 tput setaf 2 echo =========== s$i %file =========== #使終端變回原來的顏色,即白灰色 tput setaf 7 #遠程執行命令 rsync -lr $filename `whoami`@s$i:$fullpath #判斷命令是否執行成功 if [ $? == 0 ];then echo "命令執行成功" fi done [yinzhengjie@s101 ~]$ [yinzhengjie@s101 ~]$ more /soft/hadoop/etc/hadoop/hdfs-site.xml <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>dfs.replication</name> <value>3</value> </property> <property> <name>dfs.namenode.fs-limits.min-block-size</name> <value>1024</value> </property> </configuration> <!-- hdfs-site.xml 配置文件的作用: #HDFS的相關設定,如文件副本的個數、塊大小及是否使用強制權限 等,此中的參數定義會覆蓋hdfs-default.xml文件中的默認配置. dfs.replication 參數的作用: #為了數據可用性及冗余的目的,HDFS會在多個節點上保存同一個數據 塊的多個副本,其默認為3個。而只有一個節點的偽分布式環境中其僅用 保存一個副本即可,這可以通過dfs.replication屬性進行定義。它是一個 軟件級備份。
dfs.namenode.fs-limits.min-block-size 參數的作用:
#該參數是用指定hdfs最小塊存儲設置 --> [yinzhengjie@s101 ~]$ xrsync.sh /soft/hadoop/etc/full/hdfs-site.xml =========== s102 %file =========== 命令執行成功 =========== s103 %file =========== 命令執行成功 =========== s104 %file =========== 命令執行成功 [yinzhengjie@s101 ~]$
2>.客戶端編寫API代碼如下
/* @author :yinzhengjie Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ EMAIL:y1053419035@qq.com */ package cn.org.yinzhengjie.day01.note1; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org.apache.hadoop.io.IOUtils; import java.io.FileInputStream; import java.io.IOException; public class HdfsDemo4 { public static void main(String[] args) throws IOException { String path = "F:/yinzhengjie.sql"; customWrite(path); } //定制化寫入副本數和塊大小(blocksize) private static void customWrite(String path) throws IOException { //由於我的Hadoop完全分布式根目錄對yinzhengjie以外的用戶(盡管是root用戶也沒有寫入權限喲!因為是hdfs系統,並非Linux系統!)沒有寫入 // 權限,所以需要手動指定當前用戶權限。使用“HADOOP_USER_NAME”屬性就可以輕松搞定! System.setProperty("HADOOP_USER_NAME","yinzhengjie"); //實例化一個Configuration,它會自動去加載本地的core-site.xml配置文件的fs.defaultFS屬性。(該文件放在項目的resources目錄即可。) Configuration conf = new Configuration(); //代碼的入口點,初始化HDFS文件系統,此時我們需要把讀取到的fs.defaultFS屬性傳給fs對象。 FileSystem fs = FileSystem.get(conf); //這個path是指是需要在文件系統中寫入的數據,里面的字符串可以寫出“hdfs://s101:8020/yinzhengjie.sql”,但由於core-site.xml配置文件中已經有“hdfs://s101:8020”字樣的前綴,因此我們這里可以直接寫相對路徑 Path hdfsPath = new Path("/yinzhengjie.sql"); //通過fs的create方法創建一個文件輸出對象,第一個參數是hdfs的系統路徑,第二個參數是判斷第一個參數(也就是文件系統的路徑)是否存在,如果存在就覆蓋!第三個參數是指定緩沖區大小,第四個參數是指定存儲的副本數(規定數據類型必須為short類型),第五個參數是指定塊大小。 FSDataOutputStream fos = fs.create(hdfsPath,true,1024,(short) 8,2048); //創建出本地的文件輸入流,也就是我們真正想要上傳的文件。 FileInputStream fis = new FileInputStream(path); //拷貝文件 IOUtils.copyBytes(fis,fos,1024); //釋放資源 fos.close(); fis.close(); } }
3>.客戶端通過瀏覽器訪問NameNode的WEBUI
看完上面的信息發現和API設置的幾乎一致呢,那必定得一致啊,由於塊大小是2KB,而上傳的文件是19.25kb,最少得10個塊進行存儲,我們也可以通過WEBUI來查看。