使用zlib输出gzip格式的文件
zlib是一个比较通用的压缩库,通过在程序中引入zlib,可以方便的对数据进行压缩。今天花了点时间研究了一下,在tbuldr中实现了直接将数据库中的数据导出为gzip文件的功能。
下载zlib源代码,对于Linux,可以编译成静态库,然后将zlib.h,libz.a(如有必要,再加上zonf.h)和程序代码放置到同一个目录,编译的时候包含libz.a即可。
#./configure #make #make install
如果要编译成动态库,则只需要第一步改成./configure -s即可。
废话少说,下面是一段演示代码,非常简单:
#include <stdio.h>
#include "zlib.h"
int main()
{
char *data = "this is a gzip test from NinGoo.net";
gzFile *fp=NULL;
fp=gzopen("test_out.gz","wb");
gzwrite(fp,data,strlen(data));
gzclose(fp);
}
编译:
gcc -o test test.c libz.a
执行:
$./test $gzip -d test_out.gz $more test_out this is a gzip test from NinGoo.net
tbuldr中,只需要在file参数指定的文件名后面加上.gz,就会自动输出为gzip格式的文件。至此,tbuldr已基本实现了sqluldr2的全部功能,性能测试结果也不相上下了。
另外,zlib也可以在内存中对数据进行压缩和解压缩,参考:
http://hispider.googlecode.com/svn/trunk/devel/hispider/src/utils/zstream.c
学习oci编程,从ociuldr开始
Update:发现原来在linux上写的代码,到windows上编译会有些错误,主要是编译器对变量声明的位置容忍度不一样,已经修正了代码。另外对输出的日志做了一点增强,打印了导出的总时间,省得人工计算了。并将源代码,windows32位版本,linux32位版,及linux64版本一并打包提供下载测试。
一直想学学oci编程,无奈基础不好,几次都是看了几页文档就放下了。所以比较佩服老楼,写了很多优秀的工具,例如广泛使用的ociuldr,以及为很多人解决了难题的AUL等。最近老楼焕发第二春,对ociuldr做了大量改进,并且升级成了sqluldr2,刚刚获得的最新消息是,sqluldr2开始支持gzip压缩格式了,牛人就是牛。
上周六一大早跑到公司,处理完一点小事后,想想反正来了,就多呆会儿吧。干什么呢?溜达到老楼的blog上,看到一对sqluldr的信息,就花了一上午的时间研究了下老版的ociuldr的源代码,再参考hrb_qiuyb写的oci8版的ociuldr2,这次终于能看明白了,还是oci8的函数比较容易懂,于是就开始自己动手编译。hrb_qiuyb版的bug比较多,动不动就segment fault,想了想不如多花点时间,好好的重新改写一下,虽然老楼已经出了sqludr2,珠玉在前,不过最近流行山寨,他做企业版,我来做山寨版,哈哈。山寨版的名字,就叫tbuldr(ToolBox*UnLoader),因为是基于老楼开放出来的源代码弄的,那就继续开源吧,希望不要抢了sqluldr2的生意哈。
到今天为止,代码终于差不多稳定了,修复了几个主要的bug,同时把sqluldr2最新的一些特性也用山寨的方法实现了,可能效率不如老楼的,不过至少外观上看是差不多了,如输出到stdout,新版本的sqlldr控制文件,固定长度导出,指定表名导出,按列输出等功能一一实现了。
另外还实现了一些小的功能:
- feedback参数,指定输出多少行以后打印一条日志,可以更好的观察进度,默认还是50w条。
- enclose参数,为每列加入包含字符。当选择的field字符在列值中有出现的时候,enclose就有作用了。
- fixlen参数,表示固定长度输出。而不是像sqluldr2一样当field指定为0×20(空格)的时候采用固定长度。这个主要是考虑到某些非常特殊的情况下,可能会有人希望用空格做分隔符而又不希望是固定长度的。
- 还有个隐含的debug参数,打开后会输出一些debug信息,主要array fetch时为各列分配的内存等数据。这个主要是dw用了老楼很早以前的一个debug版本,觉得log里输出了列名还挺有用,就保留了,不过默认是不显示的,也没有写在help里,这里偷偷的透露一下了,哈哈
$tbuldr
----------------------------------------------------------------------------
- tbuldr: Release 2.21 (ociuldr)
- First issued by Lou Fangxin (@) Copyright 2004/2008, all rights reserved.
- Modified by Ning Haiyuan (http://www.NinGoo.net).
----------------------------------------------------------------------------
Usage: TBULDR keyword=value [,keyword=value,...]
Valid Keywords:
user = username/password@tnsname
query = select statement, can simply speicify a table name
sql = SQL file name
field = seperator string between fields
record = seperator string between records
enclose = fields enclose string
file = output file name, default: uldrdata.txt
head = print row header(Yes|No,ON|OFF,1|0)
read = set DB_FILE_MULTIBLOCK_READ_COUNT at session level
sort = set SORT_AREA_SIZE at session level (UNIT:MB)
hash = set HASH_AREA_SIZE at session level (UNIT:MB)
serial = set _serial_direct_read to TRUE if 1 at session level
trace = set event 10046 to given level at session level
table = table name in the sqlldr control file
mode = sqlldr option, INSERT or APPEND or REPLACE or TRUNCATE
log = log file name, prefix with + to append mode
long = maximum long field size, default 8192 max 65534
array = array fetch size, default 50
buffer = sqlldr READSIZE and BINDSIZE, default 16 (MB)
feedback = display progress every x rows, default 500000
form = display rows as form (Yes|No)
fixlen = fix length format (Yes|No)
for field, record and enclose, use '0x' to specify hex character code
r=0x0d n=0x0a |=0x7c ,=0x2c t=0x09 (more: man ascii)
$tbuldr user=test/test query=t
0 rows exported at 2009-04-16 20:43:53
400 rows exported at 2009-04-16 20:43:54
output file uldrdata.txt closed at 4 rows. Elapsed time: 0 min 1 sec.
control file is t_sqlldr.ctl.
当然,山寨版就是山寨版,以下sqluldr2的新功能暂未实现:
- parfile,这个是比较有用功能,可以防止命令行中显式输入密码导致密码泄漏等。因为涉及到文件内容解析,对我来说,难度有点高,以后再说。
- gzip压缩,这是下午老楼刚刚加入的新特性,还有待研究。不过这是利用了zlib实现的,网上有不少现成的代码,集成进来应当是能搞定的。另外也可以输出到stdout后通过管道调用gzip实现压缩,这个已经支持了。
- BLOB/BFILE等不提供支持,虽然BLOB可以按照LONG RAW的方式导出成16进制字符,不过不保证没问题,如果BLOB里存储的是字符应当问题不大。CLOB/LONG最大只支持到65534字节,对于大部分情况应当是足够了。
第一次用c和oci正儿八经的写东西,bug肯定一大堆。山寨有风险,慎用,如果是生产环境有需求的,建议还是找老楼的企业版,支持山寨版的同学,可以自行编译帮忙做测试,有bug和建议欢迎提交^_^
