跳到主要內容

HDFS SequenceFile



SequenceFile是Hadoop API提供的一種二進制儲存文件,可以將它看成是一個大容器,裡面包含許多小文件,只是它像資料結構中的鏈結串列將小文件串接,而每個節點都是一個key/value的形式,通常key為fileName,value為文件內容,另外sequenceFile也支持壓縮,壓縮有利於節省空間及傳輸時間。
一、由於SequenceFile並沒有建立小文件對應到大文件的索引,所以在查詢小文件時就必須進行遍歷,降低讀取效率。
二、具有壓縮功能,包含三種壓縮方式,可以透過API也可以透過Config來設定
     (一)NONE:無壓縮
     (二)RECORD:僅壓縮value部分
     (三)BLOCK:key/value皆壓縮

SequenceFile.setDefaultCompressionType(conf, SequenceFile.CompressionType.BLOCK);//JAVA API
conf.set("io.seqfile.compression.type", "BLOCK");//Config

三、使用SequenceFile來實際撰寫「某一目錄下所有檔案」以seq方式上傳到HDFS。
     (一)首先撰寫一個SequenceFileOperation的類,並包含建構子,設定HDFS的路徑

public class SequenceFileOperation {
    private Configuration conf = new Configuration();
    public SequenceFileOperation(String HDFS_PATH){
        conf.set("fs.default.name",HDFS_PATH);
    }

}

      (二)寫一個writeTo方法,使用輸入串流將數據導到應用程序中,在使用Sequence.Writer將key、value以append方式追加,其中key為字串型態也就是Hadoop中的Text,而value為BytesWritable

public void writeTo(String srcPath, SequenceFile.Writer writer, Text key, BytesWritable value){
    InputStream in = null;
    try {
        in = new BufferedInputStream(new FileInputStream(srcPath));
        String fileName = srcPath.substring(srcPath.lastIndexOf("\\") + 1);
        key.set(fileName);
        int len = 0;
        byte[] buff = new byte[1024];
        while ((len = in.read(buff))!= -1) {
            value.set(buff, 0, len);
            writer.append(key, value);//將每筆資訊追加到SequenceFile.Writer的尾端
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        IOUtils.closeStream(in);
    }
}

在這裡並沒有一次寫入而是每次都寫1024個bytes,這樣的話讀取會較無效率,故可以改良成一次寫入全部。

byte[] buff = new byte[in.available()];

      (三)撰寫uploadTo方法將指定目錄下所有檔案以打包形式上傳到HDFS,writer的部分使用SequenceFile.Writer

public void uploadTo(String srcDir,String desc){
    SequenceFile.Writer writer = null;
    try {
        FileSystem fileSystem = FileSystem.get(conf);
        SequenceFile.setDefaultCompressionType(conf, SequenceFile.CompressionType.BLOCK);
        Text key = new Text();
        BytesWritable value = new BytesWritable();
        writer = SequenceFile.createWriter(fileSystem,conf,new Path(desc),key.getClass(),value.getClass());
        File folder = new File(srcDir);
        String[] list = folder.list();
        for (int i = 0; i < list.length; i++) {
            String filePath = srcDir + "\\" + list[i];
            writeTo(filePath, writer, key, value);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        IOUtils.closeStream(writer);
    }
}

      (四)以SequenceFile.Reader來下載,下載的部分給予該檔案位於哪個.seq檔,及檔案名稱來進行循序搜尋,因為在上傳時是以檔案名稱當作key故需給予檔案名稱。

public void downloadFromSeq(String src, String desc, String fileName){
    SequenceFile.Reader reader = null;
    OutputStream out = null;
    try {
        FileSystem fileSystem = FileSystem.get(conf);
        reader = new SequenceFile.Reader(fileSystem,new Path(src),conf);
        Text key = new Text();
        Text compareKey = new Text(fileName);
        BytesWritable value = new BytesWritable();
        out = new BufferedOutputStream(new FileOutputStream(desc));
        while (reader.next(key,value)){
            if (!key.equals(compareKey)) continue;
            out.write(value.getBytes(),0,value.getLength());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        IOUtils.closeStream(out);
        IOUtils.closeStream(reader);
    }
}

      (五)最後實際來使用上傳及下載的方法

public static void main(String[] args) {
        final String HDFS_PATH = "hdfs://192.168.121.130:9000";
        SequenceFileOperation sequenceFileOperation = new SequenceFileOperation(HDFS_PATH);
        sequenceFileOperation.uploadTo("C:\\Users\\hduser\\Downloads\\myTestFiles","/testFile/test.seq");
//      /testFile includes...
//        amb.exe
//        1.pdf
//        2.pdf
//        3.pdf
//        4.pdf
//        test.txt        
        sequenceFileOperation.downloadFromSeq("/testFile/test.seq","C:\\Users\\hduser\\Downloads\\1.pdf","1.pdf");
    }

留言

這個網誌中的熱門文章

java西元民國轉換_各種不同格式

C#資料庫操作(新增、修改、刪除、查詢)

【Excel好好玩】 自己的資產自己管!善用Google Sheet來幫我們評估貸款

這次介紹的主題是關於Excel的貸款還款計畫試算,我們人生中總會遇到需要大筆金額的花費,但當資金不夠時就得進行貸款,而貸款之前如果我們能夠審慎評估,並分析自己的還款能力之後在進行凍作,相信風險會小很多,因此就自己動動手來使用Google Sheet進行試算吧! 基本資料 ● 貸款總額: 1000000 ● 貸款期數: 84月 ● 年利率: 2.11% ● 月利率: 0.18% P.S 月利率 = 年利率 / 12 重要函式 PMT : 這是Google Sheet內建的重要年金計算公式,我們可以善用這個公式來計算固定利率及期數的固定攤還本息。因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 動手做 首先我們在Excel表上列出我們的基本資料 圖片來源 其中月利率的部分就使用公式「=B4/12」 接著我們填上第一列的期數跟餘額 圖片來源 =B2 =B3 使用關鍵PMT函數來計算本息的部分 因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 -PMT(貸款利率(月利率), 貸款期數, 貸款總額) =-PMT($B$5,$B$3,$B$2) 圖片來源 計算利息 利息 = 貸款餘額 x 月利率 =B8*$B$5 圖片來源 計算本金 本金 = 本息 - 利息 =C8-D8 圖片來源 製作第二列餘額的部分 餘額的部分 = 上一期的餘額 - 上一期的本金 圖片來源 接著拖曳該兩列往下拉,即可查看每一期的利息與本金 圖片來源 結語 雖然市面上已經有很多貸款銀行都提供了試算功能,但如果我們想要進一步管理自己的資產時,就需要將每一期的金額給計算出來,因此才會將公式運用在Excel表,讓我們的資產管理表能夠結合負債,進一步評估我們理財行動的下一步,希望這樣的經驗可以幫助到正在理財道路上打拼的夥伴,讓我們透過有效的管理,幫助荷包長大吧! 喜歡撰寫文章的你,不妨來了解一下: Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 — 為什麼要加入? 歡迎加入一起練習寫作,賺取知識,累積財富!