C读写xlsx库xlsxio的编译和测试

xlsxio库编译与测试指南

前面测试的openxlsx使用pugixml库解析xml文件。而xlsxio使用Expat库解析xml文件。
DeepSeek介绍说,

pugixml (DOM模型)

工作原理:pugixml首先将整个XML文档一次性加载到内存中,并构建一个完整的节点树(Document Object Model)。然后,你可以像操作地图一样,在这个树结构上进行导航、搜索和修改。

Expat (SAX模型)

工作原理:Expat是一个流式解析器。它顺序读取XML文档的字节流,当遇到开始标签、结束标签、文本等内容时,会调用你事先注册好的回调函数。

Expat库被其他工具广泛调用,在我的gcc docker镜像中,它是默认安装的。

xlsxio依赖expat库和minizip库,间接依赖zlib库
编译步骤
1.克隆xlsxio github存储库

root@6ae32a5ffcde:/par# git clone --depth=1 https://github.com/brechtsanders/xlsxio
Cloning into 'xlsxio'...
remote: Enumerating objects: 86, done.
remote: Counting objects: 100% (86/86), done.
remote: Compressing objects: 100% (65/65), done.
remote: Total 86 (delta 36), reused 37 (delta 17), pack-reused 0 (from 0)
Receiving objects: 100% (86/86), 68.06 KiB | 1.19 MiB/s, done.
Resolving deltas: 100% (36/36), done.

2.检查expat库是否存在

root@6ae32a5ffcde:/par# whereis libexpat.so
libexpat.so: /usr/lib/x86_64-linux-gnu/libexpat.so
root@6ae32a5ffcde:/par# whereis libexpat.a
libexpat.a: /usr/lib/x86_64-linux-gnu/libexpat.a

如果不存在,克隆expat github存储库

root@6ae32a5ffcde:/par# git clone --depth=1 https://github.com/libexpat/libexpat
Cloning into 'libexpat'...
remote: Enumerating objects: 231, done.
remote: Counting objects: 100% (231/231), done.
remote: Compressing objects: 100% (190/190), done.
remote: Total 231 (delta 90), reused 112 (delta 34), pack-reused 0 (from 0)
Receiving objects: 100% (231/231), 8.02 MiB | 8.76 MiB/s, done.
Resolving deltas: 100% (90/90), done.
Updating files: 100% (211/211), done.

3.检查libz库是否存在

root@6ae32a5ffcde:/par# whereis libz.so
libz.so: /usr/lib/x86_64-linux-gnu/libz.so
root@6ae32a5ffcde:/par# whereis libz.a
libz.a: /usr/lib/x86_64-linux-gnu/libz.a

如果不存在,参考这篇文章编译安装
4.编译xlsxio

root@6ae32a5ffcde:/par# cd xlsxio
root@6ae32a5ffcde:/par/xlsxio# make
gcc -c -o lib/xlsxio_read.static.o lib/xlsxio_read.c -DBUILD_XLSXIO_STATIC -O3 -Iinclude -Ilib -DUSE_MINIZIP
lib/xlsxio_read.c:15:14: fatal error: minizip/unzip.h: No such file or directory
   15 | #    include <minizip/unzip.h>
      |              ^~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:124: lib/xlsxio_read.static.o] Error 1

要把minizip的头文件目录加入INCLUDE搜索路径。

root@6ae32a5ffcde:/par/xlsxio# make CFLAGS:="-I /par/zlib-1.3.1/contrib"
gcc -c -o lib/xlsxio_read.static.o lib/xlsxio_read.c -DBUILD_XLSXIO_STATIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -c -o lib/xlsxio_read_sharedstrings.static.o lib/xlsxio_read_sharedstrings.c -DBUILD_XLSXIO_STATIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
ar cr libxlsxio_read.a lib/xlsxio_read.static.o lib/xlsxio_read_sharedstrings.static.o
gcc -c -o lib/xlsxio_write.static.o lib/xlsxio_write.c -DBUILD_XLSXIO_STATIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
ar cr libxlsxio_write.a lib/xlsxio_write.static.o
gcc -c -o lib/xlsxio_read.shared.o lib/xlsxio_read.c -DBUILD_XLSXIO_DLL -fPIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -c -o lib/xlsxio_read_sharedstrings.shared.o lib/xlsxio_read_sharedstrings.c -DBUILD_XLSXIO_DLL -fPIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -o libxlsxio_read.so -shared -Wl,-soname,libxlsxio_read.so -s lib/xlsxio_read.shared.o lib/xlsxio_read_sharedstrings.shared.o  -lminizip -lexpat
/usr/bin/ld: cannot find -lminizip: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:137: libxlsxio_read.so] Error 1

链接libxlsxio_read.so报错,找不到minizip库,其实这个库暂时用不到,把-lminizip去掉,就能链接成功了

root@6ae32a5ffcde:/par/xlsxio# gcc -o libxlsxio_read.so -shared -Wl,-soname,libxlsxio_read.so -s lib/xlsxio_read.shared.o lib/xlsxio_read_sharedstrings.shared.o -lexpat

从Makefile去掉ZIPLIB_LDFLAGS = -lminizip等号后的-lminizip,重新make

root@6ae32a5ffcde:/par/xlsxio# make CFLAGS:="-I /par/zlib-1.3.1/contrib"
gcc -c -o lib/xlsxio_write.shared.o lib/xlsxio_write.c -DBUILD_XLSXIO_DLL -fPIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -o libxlsxio_write.so -shared -Wl,-soname,libxlsxio_write.so -s lib/xlsxio_write.shared.o   -pthread
gcc -c -o src/xlsxio_xlsx2csv.static.o src/xlsxio_xlsx2csv.c -DBUILD_XLSXIO_STATIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -o xlsxio_xlsx2csv src/xlsxio_xlsx2csv.static.o libxlsxio_read.a  -lexpat
/usr/bin/ld: libxlsxio_read.a(xlsxio_read.static.o): in function `XML_Char_openzip':
xlsxio_read.c:(.text+0x40): undefined reference to `unzLocateFile'

但是跳过minizip库的后果就是在链接可执行文件时,找不到相应的压缩代码二进制代码

直接链接minizip.o也行不通,因为它是示例文件的目标代码,里面有main函数,而且也不包括相应的压缩代码二进制代码

root@6ae32a5ffcde:/par/xlsxio# gcc -o xlsxio_xlsx2csv src/xlsxio_xlsx2csv.static.o libxlsxio_read.a /par/zlib-1.3.1/contrib/minizip/minizip.o -lexpat
/usr/bin/ld: /par/zlib-1.3.1/contrib/minizip/minizip.o: in function `main':
minizip.c:(.text+0x0): multiple definition of `main'; src/xlsxio_xlsx2csv.static.o:xlsxio_xlsx2csv.c:(.text+0x3d2): first defined here
/usr/bin/ld: libxlsxio_read.a(xlsxio_read.static.o): in function `XML_Char_openzip':
xlsxio_read.c:(.text+0x40): undefined reference to `unzLocateFile'

所以还是需要先生成minizip库,进入相应目录
root@6ae32a5ffcde:/par/xlsxio# cd /par/zlib-1.3.1/contrib/minizip/
按照这篇文章的提示,改写minizip的Makefile, 按照我的实际情况修改如下:

ZLIB_PATH := ../..
CC?=cc
AR?=ar

CFLAGS := $(CFLAGS) -O -I $(ZLIB_PATH)/include -shared -fPIC

MINIZIP_SO_OBJS = unzip.o zip.o ioapi.o $(ZLIB_PATH)/libz.so
MINIZIP_A_OBJS = unzip.o zip.o ioapi.o $(ZLIB_PATH)/libz.a

.c.o:
	$(CC) -c $(CFLAGS) $*.c

all: libminizip.a libminizip.so

libminizip.so:  $(MINIZIP_SO_OBJS)
	$(CC) $(CFLAGS) -o $@ $(MINIZIP_SO_OBJS)
	
libminizip.a:	$(MINIZIP_A_OBJS)
	$(AR) rcs $@ $(MINIZIP_A_OBJS)

clean:
	rm -f *.o *.a *.so

执行make,顺利生成静态库libminizip.a,生成动态库libminizip.so 报错

root@6ae32a5ffcde:/par/zlib-1.3.1/contrib/minizip# make
ar rcs libminizip.a unzip.o zip.o ioapi.o ../../libz.a
cc  -O -I ../../include -shared -fPIC -o libminizip.so unzip.o zip.o ioapi.o ../../libz.so
/usr/bin/ld: unzip.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:16: libminizip.so] Error 1
root@6ae32a5ffcde:/par/zlib-1.3.1/contrib/minizip# make libminizip.a
make: 'libminizip.a' is up to date.

将静态库libminizip.a和动态库libz链接到xlsxio_xlsx2csv,成功

root@6ae32a5ffcde:/par/zlib-1.3.1/contrib/minizip# cd /par/xlsxio

root@6ae32a5ffcde:/par/xlsxio# gcc -o xlsxio_xlsx2csv src/xlsxio_xlsx2csv.static.o libxlsxio_read.a /par/zlib-1.3.1/contrib/minizip/libminizip.a -lz -lexpat
root@6ae32a5ffcde:/par/xlsxio# ./xlsxio_xlsx2csv
Usage:  xlsxio_xlsx2csv [-h] [-s separator] [-n] xlsxfile ...
Parameters:
  -h            display command line help
  -s separator  specify separator to use (default is comma)
  -b            don't write UTF-8 BOM signature
  -n            use UNIX style line breaks
  -u            use sheet number in output file name (instead of sheet name)
  xlsxfile      path to .xlsx file (multiple may be specified)
Description:
Converts all sheets in all specified .xlsx files to individual CSV (Comma Separated Values) files.
Version: 0.2.36

root@6ae32a5ffcde:/par/xlsxio# time ./xlsxio_xlsx2csv /par/openxlsx-dev-aral/Demo05.xlsx
Processing file: /par/openxlsx-dev-aral/Demo05.xlsx
Sheet found: Sheet1, exporting to: /par/openxlsx-dev-aral/Demo05.xlsx.Sheet1.csv

real    0m4.726s
user    0m3.325s
sys     0m0.085s
root@6ae32a5ffcde:/par/xlsxio#

再把ZIPLIB_LDFLAGS =/par/zlib-1.3.1/contrib/minizip/libminizip.a写入xlsxio的Makefile,重新make,不知何故,产生的命令行虽然加了libminizip.a,但缺少-lz,报错,手工加上-lz就好了

root@6ae32a5ffcde:/par/xlsxio# make CFLAGS:="-I /par/zlib-1.3.1/contrib"
gcc -c -o src/xlsxio_csv2xlsx.static.o src/xlsxio_csv2xlsx.c -DBUILD_XLSXIO_STATIC -I /par/zlib-1.3.1/contrib -Iinclude -Ilib -DUSE_MINIZIP
gcc -o xlsxio_csv2xlsx src/xlsxio_csv2xlsx.static.o libxlsxio_write.a /par/zlib-1.3.1/contrib/minizip/libminizip.a -pthread
/usr/bin/ld: /par/zlib-1.3.1/contrib/minizip/libminizip.a(zip.o): in function `zipWriteInFileInZip':
zip.c:(.text+0x11e6): undefined reference to `crc32'
/usr/bin/ld: zip.c:(.text+0x1244): undefined reference to `deflate'
/usr/bin/ld: /par/zlib-1.3.1/contrib/minizip/libminizip.a(zip.o): in function `zipCloseFileInZipRaw64':
zip.c:(.text+0x141f): undefined reference to `deflate'
/usr/bin/ld: zip.c:(.text+0x1479): undefined reference to `deflateEnd'
/usr/bin/ld: zip.c:(.text+0x14a7): undefined reference to `deflateEnd'
/usr/bin/ld: zip.c:(.text+0x18c5): undefined reference to `deflateEnd'
/usr/bin/ld: zip.c:(.text+0x18d3): undefined reference to `deflateEnd'
/usr/bin/ld: /par/zlib-1.3.1/contrib/minizip/libminizip.a(zip.o): in function `zipOpenNewFileInZip4_64':
zip.c:(.text+0x21f6): undefined reference to `get_crc_table'
/usr/bin/ld: zip.c:(.text+0x2524): undefined reference to `deflateInit2_'
collect2: error: ld returned 1 exit status
make: *** [Makefile:185: xlsxio_csv2xlsx] Error 1

root@6ae32a5ffcde:/par/xlsxio# gcc -o xlsxio_csv2xlsx src/xlsxio_csv2xlsx.static.o libxlsxio_write.a /par/zlib-1.3.1/contrib/minizip/libminizip.a -pthread -lz
root@6ae32a5ffcde:/par/xlsxio# ./xlsxio_csv2xlsx
Usage:  xlsxio_csv2xlsx [-h] [-s separator] [-d rows] [-n] csvfile ...
Parameters:
  -h            display command line help
  -s separator  specify separator to use (default is comma)
  -d rows       rows used for column width detection (default is 20)
  -t            tread top row as header row
  csvfile       path to CSV file (multiple may be specified)
Description:
Converts all specified CSV (Comma Separated Values) files to .xlsx files.
Version: 0.2.36

root@6ae32a5ffcde:/par/xlsxio# time ./xlsxio_csv2xlsx /par/openxlsx-dev-aral/Demo05.xlsx.Sheet1.csv

real    0m25.949s
user    0m25.247s
sys     0m2.584s

可见,xlsxio_csv2xlsx 成功读取了上一步产生的csv文件,并把它转为了Demo05.xlsx.Sheet1.csv.xlsx,文件大小是39,436,422,比原始的Demo05.xlsx大了4MB。

本文基本上实现了调用xlsxio库的程序的生成和测试,读写时间和OpenXLSX差距不大,中间遗留的问题,以后慢慢研究解决。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值