一、搭建Hadoop 開發環境
我們在工作中寫完的各種代碼是在服務器中運行的,HDFS 的操作代碼也不例外。在開發階段,我們使用windows 下的eclipse 作為開發環境,訪問運行在虛擬機中的HDFS。也就是通過在本地的eclipse 中的java 代碼訪問遠程linux 中的hdfs。
要使用宿主機中的java 代碼訪問客戶機中的hdfs,需要保證以下幾點:
(1)確保宿主機與客戶機的網絡是互通的
(2)確保宿主機和客戶機的防火牆都關閉,因為很多端口需要通過,為了減少防火牆配置,直接關閉.
(3)確保宿主機與客戶機使用的jdk 版本一致。如果客戶機為jdk6,宿主機為jdk7,那么代碼運行時會報不支持的版本的錯誤。
(4)宿主機的登錄用戶名必須與客戶機的用戶名一直。比如我們linux 使用的是root 用戶,那么windows 也要使用root 用戶,否則會報權限異常
在eclipse 項目中覆蓋hadoop 的org.apache.hadoop.fs.FileUtil 類的checkReturnValue 方法,如圖1.1,目的是為了避免權限錯誤。
圖1.1
如果讀者在開發過程中出現權限等問題,請按照本節的提示檢查自己的環境。
二、使用FileSystem api 讀寫數據
在hadoop 的HDFS 操作中,有個非常重要的api,是org.apache.hadoop.fs.FileSystem,這是我們用戶代碼操作HDFS 的直接入口,該類含有操作HDFS 的各種方法,類似於jdbc 中操作數據庫的直接入口是Connection 類。
那我們怎么獲得一個FileSystem 對象?

1 String uri = "hdfs://10.1.14.24:9000/"; 2 Configuration conf = new Configuration(); 3 FileSystem fs = FileSystem.get(URI.create(uri), conf);
以上代碼中,要注意調用的是FileSystem 的靜態方法get,傳遞兩個值給形式參數,第一個訪問的HDFS 地址,該地址的協議是hdfs,ip 是10.1.14.24,端口是9000。這個地址的完整信息是在配置文件core-site.xml 中指定的,讀者可以使用自己環境的配置文件中的設置。第二個參數是一個配置對象。
1. 創建文件夾
使用HDFS 的shell 命令查看一下根目錄下的文件情況,如圖2.1所示。
圖2.1
我們在HDFS 的根目錄下創建文件夾,代碼如下
------------------------------------------------------------------------------------------------------
final String pathString = "/d1";
boolean exists = fs.exists(new Path(pathString));
if(!exists){
boolean result = fs.mkdirs(new Path(pathString));
System.out.println(result);
}
------------------------------------------------------------------------------------------------------
以上代碼中要放在Main函數中,
- 第一行決定創建的文件夾完整路徑是“/d1”。
- 第二行代碼是使用方法exitst判斷文件夾是否存在;如果不存在,執行創建操作。
- 第三行創建文件夾,調用的是mkdirs 方法,返回值是布爾值,如果是true,表示創建成功;如果是false,表示創建失敗。
現在查看一下是否成功了,如圖3.2,3.3可見創建成功了。
圖 3.3
2. 寫文件
我們可以向HDFS 寫入文件,代碼如下:
-----------------------------------------------------------------------------------------------------
final String pathString = "/d1/f1";
final FSDataOutputStream fsDataOutputStream = fs.create(new Path(pathString));//寫出去
IOUtils.copyBytes(new ByteArrayInputStream("my name is Sunddenly".getBytes()),
fsDataOutputStream, conf, true);
------------------------------------------------------------------------------------------------------
第一行代碼表示創建的文件是在剛才創建的d1 文件夾下的文件f1;
第二行是調用create 方法創建一個通向HDFS 的輸出流;
第三行是通過調用hadoop 的一個工具類IOUtils 的靜態方法copyBytes 把一個字符串發送給輸出流中。
該靜態方法有四個參數:
- 第一個參數輸入流。
- 第二個參數是輸出流。
- 第三個參數是配置對象。
- 第四個參數是布爾值,如果是true 表示數據傳輸完畢后關閉流。
現在看一下是否創建成功了,如圖3.4所示。
圖3.4
3. 讀文件
現在我們把剛才寫入到HDFS 的文件“/d1/f1”讀出來,代碼如下:
------------------------------------------------------------------------------------------------------
final String pathString = "/d1/f1";
final FSDataInputStream fsDataInputStream = fs.open(new Path(pathString));//讀進來
IOUtils.copyBytes(fsDataInputStream, System.out, conf, true);
-------------------------------------------------------------------------------------------------------
- 第一行指定所讀文件的路徑。
- 第二行表示調用方法open 打開一個指定的文件,返回值是一個通向該文件的輸入流;
- 第三行還是調用IOUtils.copyBytes 方法,輸出的目的地是控制台。
見圖3.5
4. 查看目錄列表和文件詳細信息
我們可以把根目錄下的所有文件和目錄顯示出來,代碼如下
--------------------------------------------------------------------------------------------------------
final String pathString = "/";
final FileStatus[] listStatus = fs.listStatus(new Path(pathString));
for (FileStatus fileStatus : listStatus) {
final String type = fileStatus.isDir()?"目錄":"文件";
final short replication = fileStatus.getReplication();
final String permission = fileStatus.getPermission() .toString();
final long len = fileStatus.getLen();
final Path path = fileStatus.getPath();
System.out.println(type+"\t"+permission+"\t"+replication+"\t"+len+"\t"+path);
}
-----------------------------------------------------------------------------------------------------------
調用listStatus方法會得到一個指定路徑下的所有文件和文件夾,每一個用FileStatus表示。我們使用for循環顯示每一個FileStatus對象。FileStatus對象表示文件的詳細信息,里面含有類型、副本數、權限、長度、路徑等很多信息,我們只是顯示了一部分。結果如圖3.6所示。
5. 刪除文件或目錄
我們可以刪除某個文件或者路徑,代碼如下
-----------------------------------------------------------------------------------------------------
final String pathString = "/d1/f1";
//fs.delete(new Path("/d1"), true);
fs.deleteOnExit(new Path(pathString));
-----------------------------------------------------------------------------------------------------
第三行代碼表示刪除文件“/d1/f1”,注釋掉的第二行代碼表示遞歸刪除目錄“/d1”及下面的所有內容。除了上面列出的fs 的方法外,還有很多方法,請讀者自己查閱api。