1. 程式人生 > >FSDataOutputStream (淺析hadoop寫入資料api)

FSDataOutputStream (淺析hadoop寫入資料api)

對於一般檔案,都有滿足隨機讀寫的api。而hadoop中的讀api很簡單用FSDataInputStream類就可以滿足一般要求,而hadoop中的寫操作卻是和普通java操作不一樣。

Hadoop對於寫操作提供了一個類:FSDataOutputStream,這個類過載了很多write方法,用於寫入很多型別的資料:比如位元組陣列,long,int,char等等。像FSDataInputStream一樣,要獲得FSDataOutputStream的例項,必須通過FileSystem該類來和HDFS建立連線,然後通過路徑返回FSDataOutputStream例項。FileSystem返回FSDataOutputStream例項的方法有兩組:
1、create(Path p)函式,建立一個空檔案,然後可以向該檔案順序寫入
2、append(Path p)函式,開啟一個已有檔案,並最做檔案末尾追加資料
以上兩組函式都有多個過載版本,可以查閱手冊。FSDataOutputStream不允許在檔案中定位(而FSDataInputStream可以),這是因為hadoop只允許在一個已開啟檔案順序寫入或在檔案尾追加資料,不允許在結尾之外其他檔案寫入資料。

在使用append的操作時可能返回異常dfs.support.append未設定為true,只要才hdfs-site.xml中把該屬性設定為true

<property>  
  <name>dfs.support.append</name>  
  <value>false</value>  
  <description>Does HDFS allow appends to files?  
               This is currently set to false because there are bugs in the  
               "append code" and is not supported in any prodction cluster.  
  </description>  
</property>  

而且0.20的早起版本也不支援append操作,官方文件的建議是如果追加資料就重新create一個檔案。使用的時候應該謹慎一點。

當讀取檔案時若要返回檔案的大小,用下列程式碼:

FileStatus status=hdfs.getFileStatus(p);  
            return status.getLen(); 

但是當對檔案寫入時,FileStatus的getLen函式返回的不是當前的大小,因為FSDataInputStream在寫入資料時,資料會快取,只有當寫入的資料滿64M(塊大小)時或者關閉檔案時,才會把資料寫入到檔案中去。連續寫入資料時,為了實時獲取當前檔案大小,如果連續關閉開啟檔案勢必會影響效率。可以這樣解決:
long result;  
if(outFsData!=null){//FSDataInputStream物件例項  
result=writeInitSize+outFsData.size()//檔案開啟時的長度  
}  
else{  
FileStatus status=hdfs.getFileStatus(p);  
result=status.getLen();//這個getLen()返回的是int型,最大也就是4G,要注意  
}  
return result; 

FSDataOutputStream該類的size函式就是返回的緩衝區寫入的資料的大小。

參考:http://blog.csdn.net/qiuchenl/article/details/8617990