HDFS文件操做java
你能夠把一個大數據集(100TB)在HDFS中存儲爲單個文件,而大多數其餘的文件系統無力實現這一點。雖然該文件存在多個副本分佈在多臺機器上來支持並行處理,你也沒必要考慮這些細節。apache
HDFS (Hadoop Distribution File System)文件系統究竟是一個怎樣的文件系統?編程
並非一個Unix文件系統,不支持像ls和cp這種標準的Unix文件命令,也不支持如fopen()和fread()這樣的標準文件讀寫操做。可是Hadoop提供了一套與Linux文件命令相似的命令行工具。數組
一個典型的Hadoop工做流是指?服務器
1、在別的地方生成數據文件(如日誌文件)再將其複製到HDFS中。架構
2、由MapReduce程序處理這個數據,讀取HDFS文件並將之解析爲獨立的記錄(鍵/值對)分佈式
3、除非要定製數據的導入與導出,不然你幾乎沒必要編程來讀寫HDFS文件。工具
Hadoop文件命令採起的形式是?oop
hadoop fs -cmd <args>學習
cmd是具體的文件命令,而<args>是一組數目可變的參數。cmd的命名一般與UNIX對應的命令名相同。如,文件列表的命令爲:hadoop fs -ls
Hadoop最經常使用的文件管理任務包括?
1、添加文件和目錄
2、獲取文件
3、刪除文件
Hadoop文件命令能夠和本地文件系統交互嗎?
Hadoop的文件命令既能夠與HDFS文件系統交互,也能夠和本地文件系統交互。
URI定位是指?完整的URL格式是?
URL精確地定位一個特定文件或目錄的位置。
完整的URL格式爲scheme://authority/path. Scheme相似於一個協議它能夠是hdfs或file、來分別指定HDFS文件系統或本地文件系統。
對於HDFS,authority是NameNode的主機名,而path是文件或者目錄的路徑。
對於在本地機器的9000端口上,以標準僞分佈式模型運行的HDFS,訪問用戶目錄user/chuck中文件example.txt的URI是什麼?
hdfs://localhost:9000/user/chuck/example.txt
hadoop fs -cat hdfs://localhost:9000/user/chuck/example.txt
可是一般咱們在使用Hadoop文件命令時沒有指定URI中的scheme://authority部分
是怎麼回事?
是的,大多數設置不須要指定URI中的scheme://authority部分
例如,當在本地文件系統和HDFS之間複製文件時
1、put命令將本地文件複製到HDFS中,源是本地文件,目的是HDFS文件
2、get命令將HDFS中文件複製到本地,源是HDFS文件,目的是本地文件。
若是未設置URI中的scheme://authority部分,就會採用Hadoop的默認配置fs.default.name屬性的配置。
例如:conf/core-site.xml文件配置是:
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
在此配置下,URI hdfs://localhost:9000/user/chuck/example.txt縮短爲/user/chuck/example.txt
注:有些更早的文檔以hadoop dfs -cmd <args>的形式表示文件工具。dfs和fs是等價的,但如今都是用fs
HDFS默認當前工做目錄是?
HDFS默認當前工做目錄爲/user/$USER,其中$USER是你的登陸用戶名。
例:若是你做爲chuck登陸,則URI hdfs://localhost:9000/user/chuck/example.txt就縮短爲example.txt。顯示文件內容的Hadoop cat命令可寫爲:
hadoop fs -cat example.txt
如何在HDFS上添加文件和目錄?
首先必須確保幾點:
1、必須先進行格式化
2、出於學習目的,建議使用僞分佈式
3、默認工做目錄是/user/$USER,但這個目錄不會自動建立,須要手動建立先
手動建立默認工做目錄
hadoop fs -mkdir /user/chuck
Hadoop的mkdir命令會自動建立父目錄,相似於UNIX中使用-p選項的mkdir命令,所以上述命令還會建立/user目錄。
hadoop fs -ls / 該命令列出根目錄下的全部文件和目錄
hadoop fs -lsr / 該命令列出根目錄下全部文件和子目錄
hadoop fs -put example.txt . 將本地文件example.txt放入HDFS中。
後面的(.),意味着把文件放入默認的工做目錄,等價於
hadoop fs -put example.txt /user/chuck
hadoop fs -ls 列出工做目錄下的全部文件和目錄
使用hadoop fs -ls命令列出內容和複製因子
一般狀況下會列出以下面這樣的view
Found 1 items
-rw-r--r-- 1 chuck supergroup 264 2009-01-14 11:02 /user/chuck/example.txt
顯示屬性信息,其餘的不解釋和UNIX的概念相似。主要說一下"1"列出文件的複製因子。僞分佈式下它永遠爲1,對於生產環境中的集羣,複製因子一般爲3,也能夠是任何正整數,複製因子不適用於目錄,因此該列會顯示一個(-)
如何檢索文件?
Hadoop的get命令與put命令相反,從HDFS中複製文件到本地文件系統。
好比hadoop fs -get example.txt 將它複製帶本地的當前工做目錄中。
hadoop fs -cat example.txt 也可使用cat命令顯示數據。
也可使用管道命令 hadoop fs -cat example.txt | head
可使用tail命令來查看最後的一千字節:
hadoop fs -tail example.txt
如何刪除文件?
刪除文件和空目錄使用rm命令
hadoop fs -rm example.txt
如何查閱幫助?
hadoop fs (無參數) 來獲取所用版本Hadoop的一個完整命令列表。
hadoop fs -help ls 顯示每一個命令的用法及簡短描述。
HDFS的Java API?
雖然,命令行工具足以知足大多數與HDFS文件系統交互的需求,可是有些需求只能用Java API去訪問,好比開發一個PutMerge程序,用於合併文件後放入HDFS中,命令行工具並不支持這個操做。
合併文件後放入HDFS中,何時會這樣作呢?
考慮這樣一個場景,須要分析來自許多Web服務器的Apache日誌文件時,就有了創建這個例程的動機,雖然咱們能夠把每一個日誌文件都複製到HDFS中,但一般而言,Hadoop處理單個大文件會比處理許多個小文件更有效率。
爲何會日誌數據會分散在多個文件?
這是因爲Web服務器採用分佈式架構所形成的。
一種解決辦法是?爲何不直接合並?
一種解決辦法是先將全部的文件合併,而後再複製到HDFS。但是,文件合併須要佔用本地計算機的大量磁盤空間。若是咱們可以在向HDFS複製的過程當中合併它們就行了。
Hadoop命令行工具getmerge命令。
getmerge命令,用於把一組HDFS文件在複製到本地計算機以前進行合併,但咱們想要的截然相反。咱們是要putmerge命令。
Hadoop文件操做API是?
Hadoop中用做文件操做的主類位於org.apache.hadoop.fs軟件包中,Hadoop的基本文件操做包括open、read、write和close,Hadoop的文件API也能夠用於HDFS之外的其餘文件系統。
Hadoop文件API的起點是FileSystem類,這是一個與文件系統交互的抽象類,存在不一樣的具體實現子類用於處理HDFS和本地文件系統。你能夠經過調用factory方法FileSystem.get(Configuration conf)來獲得所需的FileSystem實例。Configuration類是用於保留鍵/值配置參數的特殊類。它的默認實例化方法是以HDFS系統的資源配置爲基礎的。
如何獲得一個FileSystem對象?
Configuration conf = new Configuration();
FileSystem hdfs = FileSystem.get(conf);
要獲得一個專用於本地文件系統的FileSystem對象,可使用factory方法的FileSystem.getLocal(Configuration conf);
FileSystem local = FileSystem.getLocal(conf);
其餘說明:
Hadoop文件API使用Path對象來編制文件和目錄名,使用FileStatus對象來存儲文件和目錄的元數據。PutMerge程序將合併一個本地目錄中的全部文件。咱們使用FileSystem的listStatus()方法來獲得一個目錄中的文件列表:
Path inputDir = new Path(args[0]);
FileStatus[] inputFiles = local.listStatus(inputDir);
數組inputFiles的長度等於指定目錄中的文件個數。在inputFiles中每個FileStatus對象均有元數據信息,如文件長度、權限、修改時間等。PutMerge程序所關心的是每一個文件的Path,即inputFiles[i].getPath()。咱們能夠經過FSDataInputStream對象訪問這個Path來讀取文件。
FSDataInputStream in = local.open(inputFiles[i].getPath());
byte buffer[] = new byte[256];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) > 0) {
...
}
in.close();
FSDataInputStream是Java標準類java.io.DataInputStream的一個子類,增長了對隨機訪問的支持。相似地有一個FSDataOutputStream對象用於將數據寫入HDFS文件:
Path hdfsFile = new Path(args[1]);
FSDataOutputStream out = hdfs.create(hdfsFile);
out.write(buffer, 0, bytesRead);
out.close();