分享知識-快樂自己:揭祕HDFS
揭祕HDFS:
ofollow,noindex"> 一):大資料(hadoop)初始化環境搭建
=====================================================
HDFS基礎模型:
1、分散式儲存系統HDFS(Hadoop Distributed File System)分散式儲存層
2、資源管理系統YARN(Yet Another Resource Negotiator)叢集資源管理層
3、分散式計算框架MapReduce分散式計算層
1):模式分類
1、單機模式(Standalone)
單機模式是Hadoop的預設模式。當首次解壓Hadoop的原始碼包時,Hadoop無法瞭解硬體安裝環境,便保守地選擇了最小配置。
在這種預設模式下所有3個XML檔案均為空。當配置檔案為空時,Hadoop會完全執行在本地。
因為不需要與其他節點互動,單機模式就不使用HDFS,也不載入任何Hadoop的守護程序。該模式主要用於開發除錯MapReduce程式的應用邏輯。
2、偽分佈模式(Pseudo-Distributed Mode)
偽分佈模式在“單節點叢集”上執行Hadoop,其中所有的守護程序都執行在同一臺機器上。
該模式在單機模式之上增加了程式碼除錯功能,允許你檢查記憶體使用情況,HDFS輸入輸出,以及其他的守護程序互動。
5個程序的介紹http://www.aboutyun.com/thread-7088-1-1.html
3、全分佈模式(Fully Distributed Mode)
Hadoop守護程序執行在一個叢集上。
評論:意思是說 master 上看到 namenode,jobtracer,secondarynamenode 可以安裝在master節點,也可以單獨安裝。
slave節點能看到 datanode 和 nodeManage
HDFS 的起源:
源於Google的GFS論文 發表於2003年10月 HDFS是GFS的克隆版!
什麼是GFS? 詳細參考地址
GFS是一個可擴充套件的分散式檔案系統,用於大型的、分散式的、對大量資料進行訪問的應用。
它運行於廉價的普通硬體上,並提供容錯功能。
它可以給大量的使用者提供總體效能較高的服務。
GFS 也就是 google File System,Google公司為了儲存海量搜尋資料而設計的專用檔案系統。
HDFS 簡介:
HDFS(Hadoop Distributed File System,Hadoop 分散式檔案系統)是一個高度容錯性的系統,適合部署在廉價的機器上。
HDFS 能提供高吞吐量的資料訪問,適合那些有著超大資料集(largedata set)的應用程式。
核心:
NameNode:主機器上
DataNode:子機器上
SecondaryNameNode:(NameNode的快照)
可以在master機器上也可以是單獨一臺機器
HDFS是一個主從結構(master/slave),一個HDFS叢集由一個名位元組點(NameNode)和多個數據節點(DataNode)組成。
這兩個檔案和 VERSION 存在安裝目錄下的 hdfs/name/current 資料夾下:
#Mon Feb 06 23:54:55 CST 2017
namespaceID=457699475 #名稱空間,hdfs格式化會改變名稱空間id,當首次格式化的時候datanode和namenode會產生一個相同的namespaceID,
然後讀取資料就可以,如果你重新執行格式化的時候,namenode的namespaceID改變了,
但是datanode的namespaceID沒有改變,兩邊就不一致了,如果重新啟動或進行讀寫hadoop就會掛掉。
解決方案:
1、推薦方式
hdfs namenode -format -force 進行強制的格式化會同時格式化 namenode 和 datanode
2、不推薦但是也可以實現
進入每個子機器,之後刪除HDFS和tmp檔案! 刪除之前舊版本!
HDFS的優點(設計思想):
1、高容錯性
HDFS 認為所有計算機都可能會出問題,為了防止某個主機失效讀取不到該主機的塊檔案,它將同一個檔案塊副本分配到其它某幾個主機上,如果其中一臺主機失效,可以迅速找另一塊副本取檔案。
副本存放策略:
資料自動儲存多個節點;
備份丟失後,自動恢復。
2、海量資料的儲存
非常適合上T B級別的大檔案或者一堆大資料檔案的儲存
3、檔案分塊儲存
HDFS 將一個完整的大檔案平均分塊(通常每塊(block)128M)儲存到不同計算機上,這樣讀取檔案可以同時從多個主機取不同區塊的檔案,多主機讀取比單主機讀取效率要高得多得多。
block的大小,我們實際可以自己控制!
4、移動計算
在資料儲存的地方進行計算,而不是把資料拉取到計算的地方,降低了成本,提高了效能!
5、 流式資料訪問
一次寫入,並行讀取。不支援動態改變檔案內容,而是要求讓檔案一次寫入就不做變化,要變化也只能在檔案末新增內容。
什麼是流式資料?
水庫中所有的水可以理解成一個批式資料!
水龍頭的水,是一股一股留下來的,我們可以理解成流式資料!
如果我們要統計某個檔案的資料,會有兩種方式:
1、把檔案中所有的資料 讀取到記憶體中,之後再進行計算,這樣就有個延遲,因為我們需要等待所有資料讀取完畢!
2、檔案中的資料讀取一點,計算一點!這樣就沒有了延遲,而且還提升了資料的吞吐量!
客戶端在寫入時,為保證最大吞吐量,客戶端會將資料先快取到本地檔案,當客戶端快取的資料超過一個block大小時,會向NN申請建立block,將資料寫到block裡。
在往block的多個副本寫入資料時,HDFS採用流水線複製的方式,比如block的三個副本在A、B、C上,客戶端將資料推送給最近的A;
A收到資料後立即推送給B、B推送給C,等所有副本寫入成功後,向客戶端返回寫入成功,當檔案所有的block都寫入成功後,客戶端向NS請求更新檔案的元資訊。
6、可構建在廉價的機器上
通過多副本提高可靠性,提供了容錯和恢復機制。
HDFS 可以應用在普通PC 機上,這種機制能夠讓一些公司用幾十臺廉價的計算機就可以撐起一個大資料叢集。
小例子:
比如有一個100G的檔案 需要存在HDFS中,那麼不可能存在一個節點上,因為儲存資料的這個節點一旦宕機,資料就會丟失!
那麼是不是可以把這個100G的檔案分幾份進行儲存!
比如:A節點存一份 B節點存一份 C節點存一份???
這樣每個節點的壓力都比較大,因為100G的檔案還是比較大的,需要佔用很大的頻寬!(網路IO)
這時候,HDFS就是採用了分塊儲存的方法!
把100G的這個檔案分成了很多塊,每個塊是128M,之後把每個塊存放在不同的節點上!
在我們的主機上會有兩份記錄:
01、一個儲存檔案被分成了幾塊
02、這幾塊都在那些節點上
HDFS 的核心元素:
NameNode:
檔案的真正儲存是在DataNode!子機器中!Master是管理者!
作用:
01、它是一個管理檔案的名稱空間
02、協調客戶端對檔案的訪問
03、記錄每個檔案資料在各個DataNode上的位置和副本資訊
檔案解析:
version :是一個properties檔案,儲存了HDFS的版本號。
editlog :任何對檔案系統資料產生的操作,都會被儲存!
fsimage /.md5:檔案系統元資料的一個永久性的檢查點,包括資料塊到檔案的對映、檔案的屬性等。
seen_txid :非常重要,是存放事務相關資訊的檔案
什麼是FSImage和EditsLog:
HDFS是一個分散式檔案儲存系統,檔案分散式儲存在多個DataNode節點上。
問題?
01、一個檔案儲存在哪些DataNode節點?
02、又存在DataNode節點的哪些位置?
這些描述了檔案儲存的節點,以及具體位置的資訊(元資料資訊(metadata))由NameNode節點來處理。隨著儲存檔案的增多,NameNode上儲存的資訊也會越來越多。
03、HDFS是如何及時更新這些metadata的呢?
FsImage 和 Editlog是HDFS 的核心資料結構。
這些檔案的損壞會導致整個叢集的失效。
因此,名位元組點可以配置成支援多個 FsImage 和 EditLog 的副本。任何 FsImage 和 EditLog 的更新都會同步到每一份副本中。
FsImage 檔案:
01、FsImage檔案包含檔案系統中所有的目錄和檔案inode的序列化形式,每個 Inode是一個檔案或目錄的元資料的內部表示,
幷包含此類資訊:檔案的複製等級、修改和訪問時間、訪問許可權、塊大小以及組成檔案的塊,對於目錄、則儲存修改時間、許可權和配額元資料
02、FsImage檔案沒有記錄塊儲存在哪個資料節點,而是由名稱節點把這些對映保留在記憶體中,當資料節點加入HDFS叢集中,資料節點會把自己所包含的塊列表告知名稱節點,此後會定期執行這種告知操作,以確保名稱節點的對映是最新的。
EditLog 檔案不斷變大的問題:
01、在名稱節點執行期間,HDFS的所有更新操作都是直接到EditLog,一段時間之後,EditLog檔案會變得很大
02、雖然這對名稱節點執行時候沒有什麼明顯影響,但是,當名稱節點重啟時候,名稱節點需要先將FsImage裡面的所有內容對映到記憶體,然後一條一條地執行EditLog中的記錄,當EditLog檔案非常大的時候,
會導致名稱節點啟動操作會非常的慢
解決方案:使用secondaryNameNode:
節點程序存在於叢集的master上,也可以是單獨一臺機器
作用:
1、NameNode的一個快照
2、週期性備份NameNode
3、記錄NameNode中的MateData以及其他資料
4、可以用來恢復NameNode,但是不能替換NameNode
工作原理:
執行流程:
01、SecondaryNameNode節點會定期和NameNode通訊,請求其停止使用EditLog,暫時將新的寫操作到一個新的檔案edit.new上來,這個操作是瞬間完成的。
02、SecondaryNameNode 通過HTTP Get方式從NameNode上獲取到FsImage和EditLog檔案並下載到本地目錄
03、將下載下來的FsImage 和EditLog載入到記憶體中這個過程就是FsImage和EditLog的合併(checkpoint)
04、合併成功之後,會通過post方式將新的FsImage檔案傳送NameNode上。
05、Namenode 會將新接收到的FsImage替換掉舊的,同時將edit.new替換EditLog,這樣EditLog就會變小。
CheckPoint:
什麼時候進行checkpoint由兩個引數dfs.namenode.checkpoint.preiod(預設值是3600,即1小時)和dfs.namenode.checkpoint.txns(預設值是1000000)來決定。
period引數表示,經過1小時就進行一次checkpoint,txns引數表示,hdfs經過100萬次操作後就要進行checkpoint了。
這兩個引數任意一個得到滿足,都會觸發checkpoint過程。進行checkpoint的節點每隔dfs.namenode.checkpoint.check.period(預設值是60)秒就會去統計一次hdfs的操作次數。
也可以去core-site.xml檔案中進行配置:
<property> <name>fs.checkpoint.period</name> <value>3600</value> <description>The number of seconds between two periodic checkpoints. </description> </property> <property> <name>fs.checkpoint.size</name> <value>67108864</value> <description>The size of the current edit log (in bytes) that triggers a periodic checkpoint even if the fs.checkpoint.period hasn't expired. </description> </property>
DataNode:
作用:
01、真實資料的儲存管理
02、一次寫入,並行讀取(不修改,僅支援append)
03、檔案由資料塊組成,Hadoop2.x的塊大小預設是128MB,可以自由設定
04、將資料塊儘量散佈到各個節點
檔案解析:
blk_<id>:HDFS的資料塊,儲存具體的二進位制資料
blk_<id>.meta:資料塊的屬性資訊:版本資訊、型別資訊
可以通過修改 hdfs-site.xml 的 dfs.replication 屬性設定產生副本的個數!預設是3!
寫入檔案的流程:
例如:客戶端傳送一個請求給NameNode,說它要將“zhou.log”檔案寫入到HDFS。那麼,其執行流程如圖1所示。具體為: HDFS寫 圖1 HDFS寫過程示意圖
第一步:
客戶端發訊息給NameNode,說要將“zhou.log”檔案寫入。(如圖1中的①)
第二步:
NameNode發訊息給客戶端,叫客戶端寫到DataNode A、B和D,並直接聯絡DataNode B。(如圖1中的②)
第三步:
客戶端發訊息給DataNode B,叫它儲存一份“zhou.log”檔案,並且傳送一份副本給DataNode A和DataNode D。(如圖1中的③)
第四步:
DataNode B發訊息給DataNode A,叫它儲存一份“zhou.log”檔案,並且傳送一份副本給DataNode D。(如圖1中的④)
第五步:
DataNode A發訊息給DataNode D,叫它儲存一份“zhou.log”檔案。(如圖1中的⑤)
第六步:
DataNode D發確認訊息給DataNode A。(如圖1中的⑤)
第七步:
DataNode A發確認訊息給DataNode B。(如圖1中的④)
第八步:
DataNode B發確認訊息給客戶端,表示寫入完成。(如圖1中的⑥)
在分散式檔案系統的設計中,挑戰之一是如何確保資料的一致性。對於HDFS來說,直到所有要儲存資料的DataNodes確認它們都有檔案的副本時,資料才被認為寫入完成。
因此,資料一致性是在寫的階段完成的。一個客戶端無論選擇從哪個DataNode讀取,都將得到相同的資料。
讀取檔案的流程:
為了理解讀的過程,可以認為一個檔案是由儲存在DataNode上的資料塊組成的。
客戶端檢視之前寫入的內容的執行流程如圖2所示,具體步驟為:HDFS讀寫圖2 HDFS讀過程
示意圖:
第一步:
客戶端詢問NameNode它應該從哪裡讀取檔案。(如圖2中的①)
第二步:
NameNode傳送資料塊的資訊給客戶端。(資料塊資訊包含了儲存著檔案副本的DataNode的IP地址,以及DataNode在本地硬碟查詢資料塊所需要的資料塊ID。) (如圖2中的②)
第三步:
客戶端檢查資料塊資訊,聯絡相關的DataNode,請求資料塊。(如圖2中的③)
第四步:
DataNode返回檔案內容給客戶端,然後關閉連線,完成讀操作。(如圖2中的④)
客戶端並行從不同的DataNode中獲取一個檔案的資料塊,然後聯結這些資料塊,拼成完整的檔案。
HDFS副本存放策略:
副本技術:
副本技術即分散式資料複製技術,是分散式計算的一個重要組成部分。該技術允許資料在多個伺服器端共享,一個本地伺服器可以存取不同物理地點的遠端伺服器上的資料,也可以使所有的伺服器均持有資料的拷貝。
通過副本技術可以有以下優點:
1、提高系統可靠性:系統不可避免的會產生故障和錯誤,擁有多個副本的檔案系統不會導致無法訪問的情況,從而提高了系統的可用性。另外,系統可以通過其他完好的副本對發生錯誤的副本進行修復,從而提高了系統的容錯性。
2、負載均衡:副本可以對系統的負載量進行擴充套件。多個副本存放在不同的伺服器上,可有效的分擔工作量,從而將較大的工作量有效的分佈在不同的站點上。
3、提高訪問效率:將副本建立在訪問頻度較大的區域,即副本在訪問節點的附近,相應減小了其通訊開銷,從而提高了整體的訪問效率。
副本存放策略:
HDFS 的副本放置策略是:
第一個副本放在本地節點,
第二個副本放到不同機架上的一個節點,
第三個副本放到第二個副本同機架上的另外一個節點。
如果還有其他的副本,隨機分佈在叢集中的其他節點!
=====
HDFS 執行在跨越大量機架的叢集之上。兩個不同機架上的節點是通過交換機實現通訊的,在大多數情況下,相同機架上機器間的網路頻寬優於在不同機架上的機器。
在開始的時候,每一個數據節點自檢它所屬的機架 id,然後在向名位元組點註冊的時候告知它的機架 id。
HDFS 提供介面以便很容易地掛載檢測機架標示的模組。
一個簡單但不是最優的方式就是將副本放置在不同的機架上,這就防止了機架故障時資料的丟失,並且在讀資料的時候可以充分利用不同機架的頻寬。
這個方式均勻地將複製分散在叢集中,這就簡單地實現了組建故障時的負載均衡。然而這種方式增加了寫的成本,因為寫的時候需要跨越多個機架傳輸檔案塊。
一般情況下複製因子(檔案的副本數)為 3。
HDFS 的副本放置策略是:
第一個副本放在本地節點,
第二個副本放到不同機架上的一個節點,
第三個副本放到第二個副本同機架上的另外一個節點。
這種方式減少了機架間的寫流量,從而提高了寫的效能。機架故障的機率遠小於節點故障。這種方式並不影響資料可靠性和可用性的限制,並且它確實減少了讀操作的網路聚合頻寬,因為檔案塊僅存在兩個不同的機架,而不是三個。
檔案的副本不是均勻地分佈在機架當中,1/3 副本在同一個節點上,1/3 副本在另一個機架上,另外 1/3 副本均勻地分佈在其他機架上。
這種方式提高了寫的效能,並且不影響資料的可靠性和讀效能。
HDFS 的 Shell 操作:
HDFS 的 API 操作:
Configuration:
Hadoop配置檔案的管理類! 我們之前在配置Hadoop叢集環境時,可以看到所有xml檔案的根節點都是configuration!
FileSystem:
針對於hdfs中檔案的一系列操作!比如:建立新檔案,刪除檔案,判斷檔案是否存在,將本地檔案copy到hdfs中等!
FileStatus:
獲取檔案或者資料夾的元資訊!比如:檔案路徑,檔案大小,檔案所有者,所在的塊大小,檔案修改時間,備份數量,許可權等!
FSDataInputStream:
輸入流物件! 可以將hdfs中的檔案或者資料夾讀取到本地!
FSDataOutputStream:
輸出流物件! 可以將本地的檔案或者資料夾上傳到hdfs中!
使用API對檔案的操作流程:
1、建立專案,引入需要的jar或者pom檔案
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.8.0</version> </dependency>
2、獲取Configuration==》Hadoop配置檔案的管理類!
3、獲取FileSystem ==》針對於hdfs中檔案的一系列操作!
4、進行檔案操作(讀寫、刪除、修改)
5、查詢HDFS指定目錄下檔案
查詢HDFS根目錄下的所有檔案:
public static void main(String[] args) throws IOException { selectFromPath("/"); //查詢HDFS跟目錄下 所有檔案 } /** * @param path使用者需要查詢的HDFS中的目錄 * @throws IOException */ public static void selectFromPath(String path) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //查詢 hdfs中根目錄下所有的檔案 FileStatus[] status = fileSystem.listStatus(new Path(path)); for (FileStatus s:status){ System.out.println("====>"+s); } /*獲取單個檔案的資訊 FileStatus status = fileSystem.getFileStatus(new Path(path)); System.out.println(status);*/ }
輸出內容對應的含義:
path=hdfs://master:9000/demo/demo.txt;檔案位置 isDirectory=false; 是否是資料夾 length=111; 檔案的大小 replication=2; 副本數量 blocksize=134217728; 所在塊大小 modification_time=1513047780762; 修改時間1970年到現在的毫秒數 access_time=1513047788225;最後一次訪問時間1970年到現在的毫秒數 owner=root; 檔案擁有者 group=supergroup; 檔案所屬組 permission=rw-r--r--; 檔案的許可權 isSymlink=false是否是連線
在HDFS中建立檔案:
public static void main(String[] args) throws IOException { ceateFile("/demo.txt"); //使用者需要建立的檔名稱以及路徑 } /** * @param fileName使用者需要建立的檔名稱 * @throws IOException */ public static void ceateFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立檔案 boolean flag = fileSystem.createNewFile(new Path(fileName)); if (flag){ System.out.println("檔案建立成功"); }else { System.out.println("檔案建立失敗"); } }
可能出現的問題:
如果建立檔案失敗且是許可權問題:
Permission denied: user=root, access=WRITE, inode="/":hdfs:supergroup:drwxr-xr-x
解決方案:
01.hadoop fs -chmod 777 / 02.修改hdfs-site.xml 檔案中的增加節點 <property> <name>dfs.permissions</name> <value>false</value> </property>
在HDFS中建立資料夾:
public static void main(String[] args) throws IOException { mkdirFile("/demo"); //使用者需要建立的資料夾名稱以及路徑 } /** * @param fileName使用者需要建立的資料夾名稱 * @throws IOException */ public static void mkdirFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立資料夾 boolean flag = fileSystem.mkdirs(new Path(fileName)); if (flag){ System.out.println("資料夾建立成功"); }else { System.out.println("資料夾建立失敗"); } }
在HDFS中重新命名檔案或者資料夾:
public static void main(String[] args) throws IOException { renameFile("/demo","/demo2"); //重新命名資料夾 renameFile("/demo.txt","/demo2.txt"); //重新命名檔案 } /** * @param oldName使用者需要重新命名的資料夾/檔名稱 * @param newName使用者需要重新命名的資料夾/檔名稱 * @throws IOException */ public static void renameFile(String oldName,String newName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //重新命名資料夾 boolean flag = fileSystem.rename(new Path(oldName),new Path(newName)); if (flag){ System.out.println("重新命名成功"); }else { System.out.println("重新命名失敗"); } }
在HDFS中刪除檔案或者資料夾:
public static void main(String[] args) throws IOException { deleteFile("/demo2"); //刪除資料夾 deleteFile("/demo2.txt"); //刪除名檔案 } /** * @param fileName使用者需要刪除的資料夾/檔名稱 * @throws IOException */ public static void deleteFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //刪除資料夾/檔案 boolean flag = fileSystem.deleteOnExit(new Path(fileName)); if (flag){ System.out.println("刪除成功"); }else { System.out.println("刪除失敗"); } }
本地檔案上傳到HDFS中:
public static void main(String[] args) throws IOException { uploadFile("D:/hadoop.txt","/hadoop.txt"); //上傳本地檔案,也可以改名 uploadFile("D:/hadoop","/hadoop"); //上傳本地資料夾,也可以改名 } /** * @param localFile使用者需要上傳的資料夾/檔名稱 * @param desFile使用者需要上傳到HDFS中的資料夾/檔名稱 * @throws IOException */ public static void uploadFile(String localFile,String desFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //上傳資料夾/檔案 fileSystem.copyFromLocalFile(new Path(localFile),new Path(desFile)); //關閉流 fileSystem.close(); }
從HDFS中下載檔案或者資料夾到本地:
public static void main(String[] args) throws IOException { downloadFile("/hadoop.txt","D:/hadoop.txt"); //下載到本地,也可以改名 downloadFile("/hadoop","D:/hadoop"); //下載到本地,也可以改名 } /** * @param localFile使用者需要下載到本地的資料夾/檔名稱 * @param hdfsFile使用者需要下載的HDFS中的資料夾/檔名稱 * @throws IOException */ public static void downloadFile(String hdfsFile,String localFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //下載資料夾/檔案 fileSystem.copyToLocalFile(new Path(hdfsFile),new Path(localFile)); //關閉流 fileSystem.close(); }
下面的這種方式只能下載檔案!不能下載資料夾!
public static void main(String[] args) throws IOException { downloadFile("/hadoop.txt","D:/hadoop.txt"); //下載到本地,也可以改名 } /** * @param localFile使用者需要下載到本地的檔名稱 * @param hdfsFile使用者需要下載的HDFS中的檔名稱 * @throws IOException */ public static void downloadFile(String hdfsFile,String localFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立輸入流物件 FSDataInputStream inputStream = fileSystem.open(new Path(hdfsFile)); //建立輸出流物件 OutputStream outputStream=new FileOutputStream(localFile); //下載檔案並且關閉流 IOUtils.copyBytes(inputStream,outputStream,1024,true);
讀取檔案內容:
public static void main(String[] args) throws IOException { readFile("/eclipsePut/file1.txt"); //需要讀取的檔案路徑以及名稱 } /** * @param readFile需要讀取的檔名稱 * @throws IOException */ public static void readFile(String readFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //例項化配置檔案物件 Configuration config=new Configuration(); //建立檔案系統物件 實現對檔案的操作 FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立輸入流物件 FSDataInputStream inputStream = fileSystem.open(new Path(readFile)); //解決中文亂碼問題 BufferedReader br=new BufferedReader(new InputStreamReader(inputStream)); String line=""; while ((line=br.readLine())!=null){ System.out.println(line); } //關閉流 br.close(); inputStream.close(); fileSystem.close(); }