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源创计划”,欢迎正在阅读的你也加入,一块儿分享。