当前位置: 首页 > news >正文

C读写xlsx库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 directory15 | #    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?=arCFLAGS := $(CFLAGS) -O -I $(ZLIB_PATH)/include -shared -fPICMINIZIP_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) $*.call: libminizip.a libminizip.solibminizip.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/xlsxioroot@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.36root@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.csvreal    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 1root@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 rowcsvfile       path to CSV file (multiple may be specified)
Description:
Converts all specified CSV (Comma Separated Values) files to .xlsx files.
Version: 0.2.36root@6ae32a5ffcde:/par/xlsxio# time ./xlsxio_csv2xlsx /par/openxlsx-dev-aral/Demo05.xlsx.Sheet1.csvreal    0m25.949s
user    0m25.247s
sys     0m2.584s

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

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

http://www.dtcms.com/a/358849.html

相关文章:

  • 第2.3节:AI大模型之Claude系列(Anthropic)
  • k8s 定时任务需求模板
  • 直流无刷电机2
  • 【计算机408计算机网络】第四章:自底向上五层模型之网络层
  • Linux IO复用
  • DeepConf:基于置信度提高LLM表现
  • Tomcat 企业级运维实战系列(五):Tomcat 优化和安全加固
  • Tiptrans转运 | 免费5国转运地址
  • Java中不太常见的语法-总结
  • static静态文件和requests请求对象
  • 内网穿透系列十二:一款基于 HTTP 传输和 SSH 加密保护的内网穿透工具 Chisel ,具备抗干扰、稳定、安全特性
  • PromptPerfect-将你的提示词提升到完美
  • 【Java基础知识 19】继承
  • BGP路由协议(三):路径属性
  • Cybero: 1靶场渗透
  • 2021-11-10 C++不变初心数
  • 从咒语到意念:编程语言的世纪演进与人机交互的未来
  • Carrier Aggregation Enabled MIMO-OFDM Integrated Sensing and Communication
  • 并发编程——09 CountDownLatch源码分析
  • 信息系统架构
  • Java面试-MyBatis篇
  • 【后端数据库】MySQL 索引生效/失效规则 + 核心原理
  • oha:一款轻量级HTTP负载测试工具
  • XHR 介绍及实践
  • 论文介绍:《Small Language Models are the Future of Agentic AI》
  • SSR降级CSR:高可用容灾方案详解
  • 使用axios封装post和get
  • istringviewstream 和 outstringstream
  • 嵌入式学习日记
  • 【3D算法技术入门】如何基于建筑图片重建三维数字资产?