1、前言微信
本文將對Kettle6中壓縮文件步驟(英文原名:Zip File)進行詳細說明。顧名思義,該步驟實現對源文件的壓縮處理,並能夠完成目標文件夾建立、壓縮源文件處理等配套功能。使用時注意如下兩個限制:spa
壓縮源文件、目標文件的名稱都必須來自數據流中的字段.net
只支持zip壓縮翻譯
本文附錄解釋如何經過修改源碼增長gzip功能。3d
2、說明blog
壓縮文件步驟的屬性對話框以下圖1所示:ip
圖1. ci
下面經過一個表格逐項解釋每個對話框中字段的含義。get
序號input |
名稱 |
含義 |
1 |
建立目標文件夾 |
若是選中,那麼在壓縮文件存放的文件夾不存在時,Kettle將自動建立。若是未選中,務必確保目標文件夾已存在,不然將拋出異常ZipFile.Error.TargetParentFolderNotExists。 |
2 |
覆蓋目標文件 |
實際上,這裏應該翻譯爲「添加到已有文件」更爲合理。其真實含義是,若是選中,那麼若是壓縮目標文件已經存在,Kettle僅在已有文件中增長文件條目,從而完成zip歸檔功能。 |
3 |
添加zip文件名到結果集 |
將最終文件名稱推入輸出行集。 |
4 |
源文件名字段 |
壓縮文件的來源。整個步驟的處理流程是,從輸入行集的源文件名字段中取出一個值(設爲A),從輸入行集的目標文件名字段中取出一個值(設爲B),而後將A文件壓縮到B中。 |
5 |
目標文件名字段 |
輸入行集中存儲壓縮目標文件名的字段名稱。 |
6 |
保留源文件夾 |
選中時,7纔可用。具體含義是,若是選中,那麼最終壓縮文件中,不只存儲了源文件名稱,並且也保留了源文件的文件目錄結構。具體的目錄結構,來自於第7步設置字段的值。 |
7 |
源文件夾字段名 |
設置壓縮文件中目錄結構的來源。僅在第6步選中時有效。 |
8 |
壓縮以後 |
壓縮以後,有3個選擇。
|
9 |
移動到的文件夾名稱 |
包含目標文件夾的字段名稱。 |
3、附錄
主要代碼解釋以下:
包:org.pentaho.di.trans.steps.zipfile
元數據類:ZipFileMeta
運行數據類:ZipFileData
執行過程類:ZipFile
下面解釋兩個源碼改進辦法。
1.如何解決壓縮後刪除文件的異常?
ZipFile類中有一個processFile方法,用於實現壓縮後的處理。其中:
case ZipFileMeta.OPERATION_TYPE_DELETE:
用於實現壓縮後刪除源文件。
產生異常的緣由在於文件關閉前刪除了文件,因此只要在文件關閉後刪除便可。具體代碼就一句:
if (data.sourceFile != null)
data.sourceFile.close();
修改後的結果以下圖2所示:
圖2.
2.如何增長gzip壓縮功能?
ZipFile類中有一個processRow方法,用於處理每個壓縮請求。其中約224行處調用了一個zipFile方法,用於實現對文件的zip壓縮。就在此處能夠增長一個自定義邏輯,用於實現gzip壓縮。個人邏輯是根據用戶指定目標文件的擴展名來判斷,若是擴展名是gz,那麼就採用gzip壓縮,不然仍是採用原有zip壓縮。因此,這裏修改後的代碼以下圖3所示:
圖3.
gzipFile方法是本人新增,用於實現gzip功能,代碼以下:
privatevoidgzipFile() throwsKettleException {
StringlocalrealZipfilename = KettleVFS.getFilename(data.zipFile);
booleanupdateZip = false;
byte[] buffer = null;
OutputStreamdest= null;
BufferedOutputStreambuff= null;
GZIPOutputStreamgzout= null;
InputStreamin = null;
try {
if (log.isDebug()) {
log.logDebug("GZipFileThreadName:"+ Thread.currentThread().getName() + " "
+Thread.currentThread().getId());
}
updateZip = (data.zipFile.exists() && meta.isOverwriteZipEntry());
if (updateZip) {
FilefileZip= getFile(localrealZipfilename);
fileZip.delete();
}
// Prepare GZip File
buffer = newbyte[18024];
dest = KettleVFS.getOutputStream(localrealZipfilename,false);
buff = new BufferedOutputStream(dest);
gzout = new GZIPOutputStream(buff);
// Associate a file input stream for the current file
in = KettleVFS.getInputStream(data.sourceFile);
intlen;
while ((len = in.read(buffer)) > 0) {
gzout.write(buffer, 0, len);
}
gzout.finish();
}catch(Exception e) {
thrownewKettleException(BaseMessages.getString(PKG, "ZipFile.ErrorCreatingZip"), e);
}finally{
try {
if (in != null) {
// Close the current file input stream
in.close();
}
if (gzout != null) {
// Close the GZIPOutPutStream
gzout.flush();
// gzout.closeEntry();
gzout.close();
}
if (buff != null) {
buff.close();
}
if (dest != null) {
dest.close();
}
}catch(Exception e) { /* Ignore */
}
}
}
本文分享自微信公衆號 - Kettle博士(gh_f656c3d7ba54)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。