輕量xlsx讀取庫xlsx_drone的編譯與測試

這個庫是在看其他網頁時,作為和功能豐富的xlsxio庫的對比來的,按照xlsx_drone github頁面介紹,
特征

  • 不使用任何外部應用程序來解析它們。
  • 注重速度而不是功能。
  • 簡單的接口。
  • UTF-8 支持。

安裝
直接將 src 和 ext 文件夾復制并粘貼到項目根文件夾和源代碼中。您可能希望以不同的方式容納文件是可以理解的,但請注意 xlsx_drone.h 使用相對路徑調用其名稱:#include “xlsx_drone.h”

// external libraries
#include "../ext/zip.h"
#include "../ext/sxmlc.h"
#include "../ext/sxmlsearch.h"

除此以外,連一個安裝步驟都沒有寫,只給出了幾個代碼片段,沒法直接使用,文檔也就讓你參考 src/xlsx_drone.h。

還好源代碼包中有CMakelists.txt,那就表示能用cmake & make來生成。實際結果確實生成了動態庫, 而且幾乎瞬間生成。

/# cd par/xlsx_drone
/par/xlsx_drone# mkdir build
/par/xlsx_drone# cd build
/par/xlsx_drone/build# cmake ..
-- The C compiler identification is GNU 14.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /par/xlsx_drone/build
/par/xlsx_drone/build# make
[ 20%] Building C object CMakeFiles/xlsx_drone.dir/ext/zip.c.o
In file included from /par/xlsx_drone/ext/zip.c:37:
/par/xlsx_drone/ext/miniz.h:5106:9: note: '#pragma message: Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.'5106 | #pragma message(                                                               \|         ^~~~~~~
[ 40%] Building C object CMakeFiles/xlsx_drone.dir/ext/sxmlc.c.o
[ 60%] Building C object CMakeFiles/xlsx_drone.dir/ext/sxmlsearch.c.o
[ 80%] Building C object CMakeFiles/xlsx_drone.dir/src/xlsx_drone.c.o
[100%] Linking C shared library libxlsx_drone.so
[100%] Built target xlsx_drone

瀏覽源碼目錄樹,有個test目錄下面有個xlsx_drone.test.c源文件,其中還有個helpers目錄,裝了幾個看上去用來測試的文件。
上手編譯它,很多鏈接找不到引用錯誤,其中一些像單元測試函數,一些像xlsx_drone中的函數。

/par/xlsx_drone/test# ls
helpers  xlsx_drone.test.c
/par/xlsx_drone/test# gcc  xlsx_drone.test.c -o xlsx_drone
/usr/bin/ld: /tmp/ccqiKV5x.o: in function `test_xlsx_open':
xlsx_drone.test.c:(.text+0x1c): undefined reference to `xlsx_set_print_err_messages'
/usr/bin/ld: xlsx_drone.test.c:(.text+0x2d): undefined reference to `xlsx_open'
/usr/bin/ld: xlsx_drone.test.c:(.text+0x4c): undefined reference to `UnityAssertEqualNumber'
/usr/bin/ld: xlsx_drone.test.c:(.text+0x51): undefined reference to `xlsx_get_xlsx_errno'

注意到,此文件開頭包含了#include "…/ext/unity.h"語句,而ext目錄下除了有unity的頭文件,還有c源代碼,在Makefile中沒有用到,那就加上unity.c一起編譯,一下子,單元測試引用的錯誤全消失了,只留下xlsx類錯誤。

gcc  xlsx_drone.test.c ../ext/unity.c -o xlsx_drone/usr/bin/ld: /tmp/ccD6n0u6.o: in function `test_xlsx_open':
xlsx_drone.test.c:(.text+0x1c): undefined reference to `xlsx_set_print_err_messages'
/usr/bin/ld: xlsx_drone.test.c:(.text+0x2d): undefined reference to `xlsx_open'

再加上-L 和-l參數,就鏈接成功了,把共享動態庫目錄加入LD_LIBRARY_PATH,就能執行了。執行報錯,好像是打開文件失敗,

/par/xlsx_drone/test# gcc  xlsx_drone.test.c ../ext/unity.c -o xlsx_drone -L /par/xlsx_drone/build -lxlsx_drone
/par/xlsx_drone/test# ./xlsx_drone
./xlsx_drone: error while loading shared libraries: libxlsx_drone.so: cannot open shared object file: No such file or directory/par/xlsx_drone/test# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/par/xlsx_drone/build
/par/xlsx_drone/test# ./xlsx_drone
xlsx_drone.test.c:19:test_xlsx_open:FAIL: Expected 1 Was 0
xlsx_drone.test.c:370:test_xlsx_load_sheet:FAIL: Expected 0 Was -13
Segmentation fault (core dumped)

看xlsx_drone.test.c源碼,里面的路徑是"test\helpers\non_existent.xlsx"之類,于是再在父目錄執行,結果還是報錯。最后把Windows的\目錄分隔符全都替換成Linux的/,重新編譯,執行成功,如下所示;

/par/xlsx_drone# gcc  test/xlsx_drone.test2.c ext/unity.c -o xlsx_drone2 -L /par/xlsx_drone/build -lxlsx_drone
/par/xlsx_drone# ./xlsx_drone2
test/xlsx_drone.test2.c:16:test_xlsx_open:FAIL: Expected 0 Was 1
test/xlsx_drone.test2.c:1231:test_xlsx_load_sheet:PASS
test/xlsx_drone.test2.c:1232:test_xlsx_unload_sheet:PASS
test/xlsx_drone.test2.c:1233:test_xlsx_get_last_column:PASS
test/xlsx_drone.test2.c:476:test_xlsx_read_cell:FAIL: Unity Double Precision Disabled
test/xlsx_drone.test2.c:1235:test_xlsx_close:PASS-----------------------
6 Tests 2 Failures 0 Ignored
FAIL

其中第一個測試是測不存在的文件,我故意放了一個non_existent.xlsx在helpers,導致期望0的測試執行結果為1,也報錯了。

再把首頁的代碼片段放入一個main函數,并包含頭文件,

#include "src/xlsx_drone.h"
int main()
{// open *.xlsxxlsx_workbook_t wb;xlsx_open("test/helpers/sample.xlsx", &wb);// be free to inspect some wb dataint number_of_sheets = wb.n_sheets;// load sheetxlsx_sheet_t *sheet_1 = xlsx_load_sheet(&wb, 1, NULL);// be free to inspect some sheet datachar *sheet_name = sheet_1->name;int last_row = sheet_1->last_row; // valued 0 if the sheet is empty// as of version 0.2.0 you can retrieve the last column (more info below)char *last_column = xlsx_get_last_column(sheet_1); // i.e.: "FB" or "R", etc.// read cellxlsx_cell_t cell_data_holder;    xlsx_read_cell(sheet_1, 4, "B", &cell_data_holder);// inspect resultswitch(cell_data_holder.value_type) {case XLSX_POINTER_TO_CHAR:printf("Cell 4B has value: %s", cell_data_holder.value.pointer_to_char_value);break;case XLSX_INT:printf("Cell 4B has value: %d", cell_data_holder.value.int_value);break;case XLSX_LONG_LONG:printf("Cell 4B has value: %lld", cell_data_holder.value.long_long_value);break;case XLSX_DOUBLE:printf("Cell 4B has value: %f", cell_data_holder.value.double_value);break;default:printf("Cell 4B has no value");}// you can also inspect the cell categoryint cell_category = cell_data_holder.style->related_category;	/*typedef enum xlsx_cell_category {XLSX_NUMBER, // int, long long, or doubleXLSX_TEXT, // stringXLSX_DATE, // intXLSX_TIME, // doubleXLSX_DATE_TIME, // doubleXLSX_UNKNOWN} xlsx_cell_category;*/char cat[7][10]={"NUMBER", "TEXT", "DATE", "TIME", "DATE_TIME", "UNKNOWN"};printf("Cell 4B has category XLSX_%s\n", cat[cell_category]);// when you're done reading the XLSX, close the workbook to properly free resourcesxlsx_close(&wb);	
}

編譯運行結果如下

gcc example.c -o example -L /par/xlsx_drone/build -lxlsx_drone
/par/xlsx_drone# ./example
Cell 4B has value: -1000Cell 4B has category XLSX_NUMBER

再讓DeepSeek照樣編寫一個把xlsx轉為csv的程序。

#include "src/xlsx_drone.h"
#include <stdio.h> // 添加標準IO頭文件用于CSV操作int main()
{// 打開 *.xlsx 文件xlsx_workbook_t wb;xlsx_open("test/helpers/sample.xlsx", &wb);// 加載第一個工作表xlsx_sheet_t *sheet = xlsx_load_sheet(&wb, 1, NULL);// 創建并打開CSV文件用于寫入FILE *csv_file = fopen("output.csv", "w");if (csv_file == NULL) {printf("無法創建CSV文件\n");xlsx_close(&wb);return 1;}// 獲取工作表尺寸信息int last_row = sheet->last_row;char *last_column = xlsx_get_last_column(sheet);// 遍歷所有行和列for (int row = 1; row <= last_row; row++) {for (char col_char = 'A'; col_char <= last_column[0]; col_char++) {// 處理多字母列名(如AA, AB等)char col_str[3] = {col_char, '\0'};if (last_column[1] != '\0') {// 如果需要處理兩字母列名,這里需要擴展邏輯}// 讀取單元格數據xlsx_cell_t cell;xlsx_read_cell(sheet, row, col_str, &cell);// 根據數據類型寫入CSVswitch(cell.value_type) {case XLSX_POINTER_TO_CHAR:fprintf(csv_file, "\"%s\"", cell.value.pointer_to_char_value);break;case XLSX_INT:fprintf(csv_file, "%d", cell.value.int_value);break;case XLSX_LONG_LONG:fprintf(csv_file, "%lld", cell.value.long_long_value);break;case XLSX_DOUBLE:fprintf(csv_file, "%f", cell.value.double_value);break;default:// 空單元格留空break;}// 添加逗號分隔符(最后一列后不加逗號)if (col_char < last_column[0]) {fprintf(csv_file, ",");}}// 換行表示新的一行fprintf(csv_file, "\n");}// 關閉CSV文件fclose(csv_file);// 關閉工作簿并釋放資源xlsx_close(&wb);printf("XLSX文件已成功轉換為CSV格式\n");return 0;
}

編譯執行成功,前6行的內容如下,可見它支持UTF-8, 包括漢字希臘文。

gcc xlsx2csv.c -o xlsx2csv -L /par/xlsx_drone/build -lxlsx_drone
/par/xlsx_drone# ./xls2csv
bash: ./xls2csv: No such file or directory
/par/xlsx_drone# ./xlsx2csv
XLSX文件已成功轉換為CSV格式head -6 output.csv
"General","Number","Currency","Accounting","Date","Time","Percentage","Fraction (1.5)","Scientific (0.001)","Text","Special","Custom"
"Foo",1000,1000,147,43458,0.104792,0.500000,1.500000,0.001000,"1875",2000,12
235,1000,-14562.740000,1200.874000,43458,0.104792,0.450000,1.500000,0.001000,"Just text",2000,40955
17.890000,-1000,584,,43458,0.104792,1.600000,1.500000,0.001000,"𐐀34",543415635644,
,-1000,,,43458,0.104792,,1.500000,,"foo你bar好qaz",34580585,
,1200.561000,,,43458,0.104792,,1.500000,,,,

再用這個代碼讀取8*1M行的xlsx文件,看它的性能。

gcc xlsx2csv.c -o xlsx2csv -L /par/xlsx_drone/build -lxlsx_drone -O3
root@6ae32a5ffcde:/par/xlsx_drone# time ./xlsx2csv
XLSX文件已成功轉換為CSV格式real    0m14.381s
user    0m10.321s
sys     0m3.695s

盡管用了-O3編譯,還是不太快。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97325.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97325.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97325.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux/UNIX系統編程手冊筆記:文件I/O、進程和內存分配

文件 I/O 深度解析&#xff1a;掌握通用 I/O 模型的核心邏輯 在 Linux 系統編程中&#xff0c;文件 I/O 是程序與外部設備&#xff08;文件、設備等 &#xff09;交互的基礎。從打開文件到讀寫數據&#xff0c;再到關閉資源&#xff0c;一系列系統調用構成了通用 I/O 模型的核心…

C++轉置正方形矩陣

C轉置正方形矩陣&#xff0c;就是正方形矩陣的a[i][j]a[j][i]。輸入31 2 34 5 6 7 8 9輸出1 4 72 5 83 6 9#include<bits/stdc.h> using namespace std; int main(){int n;cin>>n;int arr[n5][n5];for(int i0;i<n;i){for(int j0;j<n;j){cin>>arr[i][j]…

Ztero文獻管理工具插件設置——親測有效

一、Zotero簡介與安裝 Zotero是一款開源文獻管理軟件&#xff0c;能夠幫助我們方便地收集、整理、引用和導出文獻。它作為一個"在你的網頁瀏覽器中工作的個人研究助手"&#xff0c;可以捕獲網頁內容并自動添加引用信息。 安裝步驟&#xff1a; 訪問Zotero官網&…

【gflags】安裝與使用

gflags1. 介紹2. 安裝3. 使用3.1 頭文件3.2 定義參數3.3 訪問參數3.4 不同文件訪問參數3.5 初始化所有參數3.6 運行參數設置3.7 配置文件的使用3.8 特殊參數標識1. 介紹 gflags 是 Google 開發的一個開源庫&#xff0c;用于 C 應用程序中命令行參數的聲明、定義和解析。gflags…

基于MATLAB的三維TDOA定位算法仿真實現

一、算法原理與仿真框架 三維TDOA&#xff08;Time Difference of Arrival&#xff09;定位通過測量信號到達多個基站的時間差&#xff0c;結合幾何關系反演目標位置。其核心步驟包括&#xff1a;幾何建模&#xff1a;建立目標與基站間的距離差方程&#xff0c;形如下式&#x…

Linux-搭建DNS服務器

Linux-搭建DNS服務器1. 安裝軟件bind2.修改配置文件3. 在其他機器上測試DNS服務器4. 配置本地域名解析5. 優化后的zone1. 安裝軟件bind bind是歷史非常悠久&#xff0c;而且性能非常好的dns域名系統的軟件 [rootdns-server ~]# yum install bind bind-utils -y 啟動named服務 …

從全棧開發視角看Java與前端技術融合實踐

從全棧開發視角看Java與前端技術融合實踐 面試場景記錄&#xff1a;一次真實的面試對話 面試官&#xff1a;你好&#xff0c;很高興見到你。我是這次面試的負責人&#xff0c;可以簡單介紹一下你自己嗎&#xff1f; 應聘者&#xff1a;您好&#xff0c;我叫李明&#xff0c;今年…

第二階段WinForm-11:自定義控件

1_繼承鏈 &#xff08;1&#xff09;Form1的繼承鏈&#xff1a;Form1>Form>ContainerControl>ScrollableControl>Control &#xff08;2&#xff09;Button的繼承鏈&#xff1a;Button>ButtonBase>Control>Component 2_自定義控件 &#xff08;1&…

【2025 完美解決】Failed connect to github.com:443; Connection timed out

文章目錄前言1. 生成并上傳 SSH Key2. 寫 SSH 配置&#xff0c;強制走 ssh.github.com:4433. 連通性自檢&#xff08;看是否能握手成功&#xff09;4. 克隆5. 驗證前言 今天和往常一樣&#xff0c;寫完代碼&#xff0c;準備 push 到 github 倉庫中&#xff0c;結果發現一直卡在…

C++基礎(③反轉字符串(字符串 + 雙指針))

題目描述&#xff1a;編寫一個函數&#xff0c;將輸入的字符串反轉過來&#xff08;要求原地修改字符串&#xff0c;不使用額外空間&#xff09;。 示例&#xff1a;輸入 s ["h","e","l","l","o"] → 輸出 ["o",…

vue的動態組件keep-alive實現組件緩存和狀態保留

在 Vue.js 中&#xff0c;動態組件結合 keep-alive 是實現組件緩存和狀態保留的重要技術方案。以下是詳細解析&#xff1a;一、動態組件基礎 通過 <component :is> 實現組件動態切換&#xff1a; <component :is"currentComponent"></component>cu…

安裝Docker Desktop報錯WSL needs updating

&#xff08;1&#xff09;首先觀察下面是否勾選&#xff08;2&#xff09;說明已經啟動了&#xff0c;但是需要更新&#xff0c;cmd運行下面代碼&#xff0c;記得需要開一下代理&#xff0c;可能會有點慢上面就算好了&#xff08;3&#xff09;點擊restart這樣就代表成功了

??舊衣回收小程序|線上模式新升級

還在用老舊的傳統方式做舊衣回收&#xff1f;別out了&#xff01;線下回收箱成本高、維護難、用戶參與感弱&#xff1f;是時候用線上小程序打開全新局面了?&#x1f4a8;線上小程序 vs 傳統線下回收? 便捷性突破&#xff1a;線下&#xff1a;用戶需親自送至固定回收點&#x…

CD71.【C++ Dev】二叉樹的三種非遞歸遍歷方式

目錄 1.知識回顧 2.前序遍歷 分析 總結入棧的幾種可能 循環的條件 代碼 提交結果 3.中序遍歷 分析 代碼 提交結果 3.★后序遍歷 分析 問題:如何確定是第一次訪問到棧的元素還是第二次訪問到棧中的元素? 方法1:使用填充的內存(依賴于架構) 判斷計算機使用的架構…

音視頻學習(五十九):H264中的SPS

在 H.264 (也稱為 AVC, Advanced Video Coding) 視頻編碼標準中&#xff0c;SPS (Sequence Parameter Set) 是一個至關重要的 NALU (Network Abstraction Layer Unit) 類型&#xff0c;它承載著整個視頻序列共有的全局性配置信息。你可以把它理解為視頻文件的“基因”&#xff…

linux實時性研究

Linux 實時性研究旨在提升 Linux 系統對外部事件的響應速度和確定性,使其能夠滿足實時應用的需求。以下是關于 Linux 實時性研究的一些關鍵內容: Linux 實時性不足的原因 中斷優先級問題:在標準 Linux 內核中,中斷具有最高優先級,包括軟中斷,這使得實時任務的優先級得不到…

Java-面試八股文-Mysql篇

MySQL篇 1、Select 語句完整的執行順序 難度系數&#xff1a;?&#x1f4cc; SQL SELECT 語句書寫順序&#xff08;開發者寫的順序&#xff09; SELECT ... FROM ... JOIN ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT ...&#x1f4cc; 實際執行順序&#…

多代理系統架構:Supervisor 與 Swarm 架構詳解

多代理&#xff08;Multi-Agent&#xff09;系統正成為構建復雜 AI 應用的重要范式。本文將深入剖析兩種熱門的多代理架構模式——Supervisor&#xff08;主管模式&#xff09;與 Swarm&#xff08;群智模式&#xff09;&#xff0c;揭示它們的執行流程、適用場景及實現細節&am…

【深度學習】思維鏈(Chain of Thought, CoT):提升大模型推理能力的關鍵技術

思維鏈&#xff08;Chain of Thought, CoT&#xff09;&#xff1a;提升大模型推理能力的關鍵技術 文章目錄思維鏈&#xff08;Chain of Thought, CoT&#xff09;&#xff1a;提升大模型推理能力的關鍵技術1 什么是思維鏈&#xff08;Chain of Thought, CoT&#xff09;&#…

GitHub 宕機自救指南:打造韌性開發體系

一、引言1.1 GitHub 宕機事件回顧與影響剖析在軟件開發的廣袤版圖中&#xff0c;GitHub 宛如一座熠熠生輝的燈塔&#xff0c;為全球超 1 億開發者照亮前行之路&#xff0c;其重要性不言而喻。它集代碼托管、版本控制、協作開發以及項目管理等核心功能于一身&#xff0c;是無數開…