標籤:
在本地檔案上傳至HDFS過程中,很多情況下一個目錄包含很多個檔案,而我們需要對這些檔案進行篩選,選出符合我們要求的檔案,上傳至HDFS。這時就需要我們用到檔案模式。 在項目開始前,我們先掌握檔案模式
1、檔案模式
在某個單一操作中處理一系列檔案是很常見的。例如一個Tlog的MapReduce作業可能要分析一個月的日誌量。如果一個檔案一個檔案或者一個目錄一個目錄的聲明那就太麻煩了,我們可以使用萬用字元(wild card)來匹配多個檔案(這個操作也叫做globbing)。
Hadoop提供了兩種方法來處理檔案組:
1 public FileStatus[] globStatus(Path pathPattern) throws IOException;2 3 public FileStatus[] globStatus(Path pathPattern, PathFilter filter) throws IOException;
使用檔案模式有時候並不能有效描述你想要的一系列檔案,例如如果你想排除某個特定檔案就很難。所以FileSystem的listStatus()和globStatus()方法就提供了一個選擇性參數:PathFilter——它允許你一些更細化的控制匹配:
1 package org.apache.hadoop.fs;2 3 public interface PathFilter4 {5 boolean accept(Path path);6 }
- Hadoop中的匹配符與Unix中bash相同,如所示:、
2、資料
我們利用萬用字元和PathFilter 對象,將本地多種格式的檔案上傳至 HDFS,並過濾掉txt文字格式設定以外的檔案
資料我隨便造了些,如下
3、分析
基於需求,我們通過以下兩步完成:
1、首先使用globStatus(Path pathPattern, PathFilter filter),完成檔案格式過濾,擷取所有 txt 格式的檔案。
2、然後使用 Java API 介面 copyFromLocalFile,將所有 txt 格式的檔案上傳至 HDFS
4、實現
首先定義一個類 RegexAcceptPathFilter實現 PathFilter,過濾掉 txt 文字格式設定以外的檔案。
1 /** 2 * @ProjectName PathFilter 3 * @PackageName com.buaa 4 * @ClassName RegexAcceptPathFilter 5 * @Description 只接受符合regex的檔案 6 * @Author 劉吉超 7 * @Date 2016-04-15 20:39:21 8 */ 9 public static class RegexAcceptPathFilter implements PathFilter {10 private final String regex;11 12 public RegexAcceptPathFilter(String regex) {13 this.regex = regex;14 }15 16 @Override17 public boolean accept(Path path) {18 boolean flag = path.toString().matches(regex);19 // 只接受符合regex的檔案20 return flag;21 }22 }
如果要接收 regex格式的檔案,則accept()方法就return flag; 如果想要過濾掉regex格式的檔案,則accept()方法就return !flag。
接下來在 uploadFile方法中,使用globStatus方法擷取所有txt檔案,然後通過copyFromLocalFile方法將檔案上傳至HDFS。
1 /** 2 * 過濾檔案格式 將多個檔案上傳至 HDFS 3 * 4 * @param srcPath 源路徑 5 * @param destPath 目標路徑 6 * @param filter 正則 7 * @throws URISyntaxException 8 * @throws IOException 9 */10 public static void uploadFile(String srcPath,String destPath,String filter) throws URISyntaxException, IOException {11 // 讀取設定檔12 Configuration conf = new Configuration();13 // 遠端檔案系統14 URI uri = new URI(HDFSUri.trim());15 FileSystem remote = FileSystem.get(uri,conf);;16 // 獲得本地檔案系統17 FileSystem local = FileSystem.getLocal(conf);18 19 // 只上傳srcPath目錄下符合filter條件的檔案20 FileStatus[] localStatus = local.globStatus(new Path(srcPath), new RegexAcceptPathFilter(filter));21 // 獲得所有檔案路徑22 Path[] listedPaths = FileUtil.stat2Paths(localStatus);23 24 if(listedPaths != null){25 for(Path path : listedPaths){26 // 將本地檔案上傳到HDFS27 remote.copyFromLocalFile(path, new Path(HDFSUri + destPath));28 }29 }30 }
在 main() 方法在調用 uploadFile,執行多檔案上傳至 HDFS
1 public static void main(String[] args) throws IOException,URISyntaxException {2 // 第一個參數:代表是源路徑3 // 第二個參數:代表是目錄路徑4 // 第三個參數:代表是正則,這裡我們只有上傳txt檔案,所以正則是^.*txt$5 uploadFile("D:\\data\\*","/buaa/data","^.*txt$");6 }
如果,您認為閱讀這篇部落格讓您有些收穫,不妨點擊一下右下角的【推薦】。
如果,您希望更容易地發現我的新部落格,不妨點擊一下左下角的【關注我】。
如果,您對我的部落格所講述的內容有興趣,請繼續關注我的後續部落格,我是【劉超★ljc】。
本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。
地址:下載
利用Java API通過路徑過濾上傳多檔案至HDFS