標籤:hadoop-2.4.1 swift hdfs filesystem distributedfilesyste
一提到hadoop檔案系統,通常想到的就是HDFS,即Hadoop Distributed File System,但除了HDFS外,hadoop還支援其它類型的檔案系統,比如Amazon S3、Swift檔案系統等,而這些檔案系統都擴充自抽象基礎類FileSystem,該類提供了豐富的方法用於對檔案系統進行操作,比如建立目錄、刪除檔案、重新命名等。無論使用的是HDFS還是Swift檔案系統,或者其它所支援的檔案系統,推薦在應用程式使用FileSystem對象引用實際的檔案系統,比如FileSystem local= FileSystem.getLocal(Configuration conf),該語句返回LocalFileSystem。FileSystem的類層次關係如所示,其中將重點學習紅色標記的DistributedFileSystem,其它檔案系統只進行簡要的概述。
FTPFileSystem,由Apache Commons Net提供的由FTP用戶端支援的檔案系統。S3FileSystem,由Amazon S3支援的基於block的檔案系統。NativeS3FileSystem,用於讀寫儲存在Amazon S3中檔案的檔案系統,與S3FileSystem不同的是,該實現將檔案按照原始格式儲存在S3,這樣其它S3工具可以讀取檔案。RawLocalFileSystem,原始的本地檔案系統,而繼承自ChecksumFileSystem的LocalFileSystem則為要計算校正和的檔案系統。ChecksumFileSystem實現了一個用戶端掛載表,該類的規則和實現和ViewFs是相同的,詳細內容可以參考《Hadoop-2.4.1學習之ViewFs》。HarFileSystem,Hadoop歸檔檔案系統,該歸檔檔案系統有形如_index*的索引檔案和形如part-*的內容檔案。HttpFSFileSystem允許使用者通過基於HTTP的HttpFSServer訪問HDFS。HftpFileSystem為基於HTTP訪問檔案系統的實現。WebHdfsFileSystem為HDFS在web上的檔案系統。SwiftNativeFileSystem為Swift(OpenstackObject Storage Service)檔案系統的實現。最後一個也是最常用的檔案系統為DistributedFileSystem,該類實現了DFS系統,通過該類使用者代碼與HDFS互動。
在簡要概述了FileSystem及其子類後,回過頭再詳細學習一下該類的重要方法。由於該類為抽象類別,故沒有辦法直接建立該類的對象,但該類提供了靜態方法用於建立對象,分別為:
|
方法 |
描述 |
|
get(Configuration conf) |
根據conf擷取具體的檔案系統對象 |
|
get(URI uri, Configuration conf) |
基於uri和conf建立檔案系統對象 |
|
get(URI uri, Configuration conf, String user) |
基於uri,conf和user擷取檔案系統 |
|
getLocal(Configuration conf) |
擷取本地檔案系統 |
|
newInstance(Configuration conf) |
返回唯一的檔案系統對象,該方法總是返回新的對象 |
|
newInstance(URI uri, Configuration conf) |
基於uri返回新的檔案系統對象 |
|
newInstance(URI uri, Configuration conf, String user) |
基於uri,conf和user擷取檔案系統 |
|
newInstanceLocal(Configuration conf) |
返回新的本地檔案系統對象 |
同樣為擷取檔案系統對象的方法,get和newInstance有什麼不同呢?從描述可知,newInstance總是返回新的檔案系統對象,那get呢?要想瞭解其中的具體區別,最好的方法莫過於查看原始碼了,首先查看get(URI uri, Configuration conf)的原始碼:
public static FileSystem get(URI uri, Configuration conf) throws IOException { String scheme = uri.getScheme(); String authority = uri.getAuthority(); if (scheme == null && authority == null) {// use default FS //根據fs.defaultFS的值擷取檔案系統,若未設定該參數則根據file:///返迴文件系統 return get(conf); } if (scheme != null && authority == null) {// no authority //根據fs.defaultFS的值建立URI,若未設定則使用file:///建立URI URI defaultUri = getDefaultUri(conf); if (scheme.equals(defaultUri.getScheme()) // if scheme matches default && defaultUri.getAuthority() != null) { // & default has authority return get(defaultUri, conf); // return default } } String disableCacheName = String.format("fs.%s.impl.disable.cache", scheme); if (conf.getBoolean(disableCacheName, false)) { //根據uri和conf建立FileSystem return createFileSystem(uri, conf);}//若未設定緩衝參數為true,則預設從CACHE中擷取檔案系統對象 return CACHE.get(uri, conf); }
從上面的代碼可以得知,get方法不是每次都建立FileSystem對象,會從緩衝中擷取FileSystem對象,而newInstance方法則會每次都建立新對象。所以在使用該對象的API編程時,推薦使用get方法。在FileSystem中除了上述擷取對象的靜態方法外,還有一些其它方法,比如用於建立目錄的mkdirs,移動檔案的moveFromLocalFile和moveToLocalFile,複製檔案的copyToLocalFile和copyFromLocalFile,建立檔案的create等,這些方法都多個重載方法,可以根據需要選擇合適的方法。需要注意的是create方法並未建立檔案,而是返回了FSDataOutputStream對象,使用該對象就可以向檔案中寫入資料。
除了FileSystem外,還有幾個類需要瞭解,分別為Path、FileStatus、FsStatus。其中FsStatus用於表示檔案系統的容量,已用和未用空間,方法分別為getCapacity、getUse和getRemaining。FileStatus用於擷取檔案系統的中繼資料,比如檔案大小,塊大小,檔案所有者,是否為目錄或者檔案等。Path表示檔案系統的一個檔案或者目錄,也就是Path對象對應了檔案系統的一個路徑,該路徑既可以是檔案也可以是目錄,如果以/開頭,那麼Path所表達的為絕對路徑。Path提供了一些用於判斷是否為根路徑、是否絕對路徑的方法,還有用於getName和toUri等方法。
最後綜合上述知識,編寫一小段簡單的代碼,該代碼示範了部分方法的使用方式,更多內容可以參考官方API:
public class FileSystemTest {public static void main(String[] args) {Configuration conf = new Configuration();try {FileSystem local = FileSystem.getLocal(conf);FileSystem hdfs = FileSystem.get(URI.create("hdfs://localhost:9000"),conf);FsStatus fsLocal = local.getStatus();FsStatus fsHdfs = hdfs.getStatus();System.out.println("Capacity: " + fsLocal.getCapacity()/1024/1024/1024 +"GB");System.out.println("Remaining :" + fsLocal.getRemaining()/1024/1024/1024 +"GB");System.out.println("Used: " + fsLocal.getUsed()/1024/1024/1024 +"GB");System.out.println();System.out.println("Capacity: " + fsHdfs.getCapacity()/1024/1024/1024 +"GB");System.out.println("Remaining :" + fsHdfs.getRemaining()/1024/1024/1024 +"GB");System.out.println("Used: " + fsHdfs.getUsed()/1024/1024/1024 +"GB");Path hdfsPath = new Path("/user/hadoop/");lsFile(hdfsPath,hdfs);} catch (IOException e) {e.printStackTrace();}}public static void lsFile(Path path,FileSystem fsystem) throws IOException{FileStatus fs = fsystem.getFileStatus(path);if(fs.isDirectory()){System.out.println("Directory: " + fs.getPath().toString());FileStatus[] fss = fsystem.listStatus(path);for(FileStatus f : fss){lsFile(f.getPath(),fsystem);}}else{System.out.println("File Name is: " + fs.getPath().toString() +",Size is: " + fs.getLen()/1024 + "KB");}}}
Hadoop-2.4.1學習之FileSystem及實戰