测试DuckDB电子表格读取插件rusty_sheet 0.2版

又在超第一时间拿到了张泽鹏先生的rusty_sheet插件0.2版,迫不及待装上测试,却发现DuckDB对插件版本卡得很严,1.4.0都用不了1.4.1版的插件。这难不倒我,一边下载新版本DuckDB,一边让deepseek编了个python程序,把插件中间的1.4.1都替换成了1.4.0,就可以在1.4.0中用了。

代码如下:

python 复制代码
import sys
import os

def replace_string_in_binary(filename, old_str, new_str):
    """
    在二进制文件中替换指定字符串
    """
    # 检查文件是否存在
    if not os.path.exists(filename):
        print(f"错误: 文件 '{filename}' 不存在")
        return False
    
    # 检查新旧字符串长度是否相同
    if len(old_str) != len(new_str):
        print(f"错误: 新旧字符串长度必须相同 ('{old_str}' -> '{new_str}')")
        return False
    
    try:
        # 读取二进制文件
        with open(filename, 'rb') as f:
            content = f.read()
        
        # 将二进制内容转换为字节数组以便修改
        content_bytearray = bytearray(content)
        
        # 将字符串编码为字节
        old_bytes = old_str.encode('utf-8')
        new_bytes = new_str.encode('utf-8')
        
        # 查找并替换所有匹配的字节序列
        replaced_count = 0
        i = 0
        while i <= len(content_bytearray) - len(old_bytes):
            # 检查是否匹配
            if content_bytearray[i:i+len(old_bytes)] == old_bytes:
                # 替换字节
                content_bytearray[i:i+len(old_bytes)] = new_bytes
                replaced_count += 1
                i += len(old_bytes)  # 跳过已替换的部分
            else:
                i += 1
        
        if replaced_count == 0:
            print(f"未找到字符串 '{old_str}'")
            return False
        
        # 写回文件
        with open(filename, 'wb') as f:
            f.write(content_bytearray)
        
        print(f"成功替换 {replaced_count} 处 '{old_str}' -> '{new_str}'")
        return True
        
    except Exception as e:
        print(f"处理文件时出错: {e}")
        return False

def main():
    # 检查命令行参数
    if len(sys.argv) != 4:
        print("用法: python rep.py <文件名> <旧字符串> <新字符串>")
        print("示例: python rep.py file.bin \"1.4.1\" \"1.4.0\"")
        sys.exit(1)
    
    filename = sys.argv[1]
    old_str = sys.argv[2]
    new_str = sys.argv[3]
    
    # 执行替换
    success = replace_string_in_binary(filename, old_str, new_str)
    
    if not success:
        sys.exit(1)

if __name__ == "__main__":
    main()

如果希望在旧版本测试的,可以使用这个程序。

sql 复制代码
python3 rep.py '/par/14/rusty_sheet.duckdb_extension' "1.4.1" "1.4.0"
成功替换 5 处 '1.4.1' -> '1.4.0'
root@66d4e20ec1d7:/par# ./duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/14/rusty_sheet.duckdb_extension';
D from read_sheets('/par/file*xls',header=0);
┌─────────────┐
│      A      │
│   varchar   │
├─────────────┤
│ Hello World │
│ Hello World │
└─────────────┘

这个版本插件最大的变化有两点,第一点:支持通配符处理多个电子表格;第二点:支持更多种类电子表格,包括旧版xls文件,ODS、wps et文件等。

上哪去找那么多种电子表格?我从calamine的源代码包中找到了一些,位于calamine/tests/。

先看这个插件包括的函数

sql 复制代码
select function_name from duckdb_functions() where function_name like '%sheet%';
┌────────────────┐
│ function_name  │
│    varchar     │
├────────────────┤
│ read_sheet     │
│ read_sheets    │
│ analyze_sheet  │
│ analyze_sheets │

函数名一目了然,分析读取单个、多个电子表格文件。

下面举例

1.分析单表单个sheet, 用analyze_sheet,

例如

sql 复制代码
from analyze_sheet('/par/2025work.xlsx',sheet_name='证书',header=1);
┌─────────────┬─────────────┐
│ column_name │ column_type │
│   varchar   │   varchar   │
├─────────────┼─────────────┤
│ 8日         │ varchar     │
│ B           │ varchar     │
│ C           │ varchar     │

如果用通配符,那么只有第一个满足条件的sheet被分析

sql 复制代码
from analyze_sheet('/par/2025work.xlsx',sheet_name='*',header=1);
┌──────────────────────────┬─────────────┐
│       column_name        │ column_type │
│         varchar          │   varchar   │
├──────────────────────────┼─────────────┤
│ 工单创建时间             │ varchar     │
│ 工单办结时间             │ varchar     │

2.分析单表多个sheet, 用analyze_sheets ,

sql 复制代码
from analyze_sheets('/par/2025work.xlsx',sheets=['证书','工单实录'],header=1);
┌────────────────────┬────────────┬──────────────────────────┬─────────────┐
│     file_name      │ sheet_name │       column_name        │ column_type │
│      varchar       │  varchar   │         varchar          │   varchar   │
├────────────────────┼────────────┼──────────────────────────┼─────────────┤
│ /par/2025work.xlsx │ 工单实录   │ 工单创建时间             │ varchar     │
│ /par/2025work.xlsx │ 工单实录   │ 工单办结时间             │ varchar     │
│         ·          │  ·         │ ·                        │    ·        │
│ /par/2025work.xlsx │ 证书       │ J                        │ varchar     │
│ /par/2025work.xlsx │ 证书       │ K                        │ varchar     │

虽然analyze_sheets也可以用来分析单个sheet, 但是有冗余列,不推荐

sql 复制代码
 from analyze_sheets('/par/2025work.xlsx',sheets=['证书'],header=1);
┌────────────────────┬────────────┬─────────────┬─────────────┐
│     file_name      │ sheet_name │ column_name │ column_type │
│      varchar       │  varchar   │   varchar   │   varchar   │
├────────────────────┼────────────┼─────────────┼─────────────┤
│ /par/2025work.xlsx │ 证书       │ 8日         │ varchar     │
│ /par/2025work.xlsx │ 证书       │ B           │ varchar     │
│ /par/2025work.xlsx │ 证书       │ C           │ varchar     │

3.读取单文件多个sheet, 用read_sheets

通配符读取所有满足条件的sheet

sql 复制代码
from read_sheets('/par/400.xls',sheets=['*']);
┌──────────────────────┬─────────┬─────────┬────────────────┬
│  400热线分日工单情况 │    B    │    C    │       D        │ 
│       varchar        │ varchar │ varchar │    varchar     │ 
├──────────────────────┼─────────┼─────────┼────────────────┼
│ 分日工单情况         │ NULL    │ NULL    │ 分类型工单数量 │
│ 日期                 │ 星期    │ 接起量  │ 口令\n问题     │ 
│ 2025-01-01           │ 元旦    │ 11      │ 5              │ 
│     ·                │  ·      │ ·       │ ·              │
│ 2025-12-29           │ 周五    │ 0       │ NULL           │ 
│ 2025-12-30           │ 周六    │ 0       │ NULL           │ 
│ 2025-12-31           │ 周日    │ 0       │ NULL           │ 
│ 合计                 │ NULL    │ 0       │ 0              │ 
├──────────────────────┴─────────┴─────────┴────────────────┴
│ 401 rows (40 shown) 

也可以用明确的sheet名列表

sql 复制代码
from read_sheets('/par/400.xls',sheets=['一月','二月']);
┌──────────────────────┬─────────┬─────────┬────────────────┬
│  400热线分日工单情况 │    B    │    C    │       D        │ 
│       varchar        │ varchar │ varchar │    varchar     │ 
├──────────────────────┼─────────┼─────────┼────────────────┼
│ 分日工单情况         │ NULL    │ NULL    │ 分类型工单数量 │
│ 日期                 │ 星期    │ 接起量  │ 口令\n问题     │ 
│ 2025-01-01           │ 元旦    │ 11      │ 5              │ 
│     ·                │  ·      │ ·       │ ·              │
│ 2025-02-28           │ 周五    │ 198     │ 17             │
│ 合计                 │ NULL    │ 2637    │ 406            │
├──────────────────────┴─────────┴─────────┴────────────────┴
│ 65 rows (40 shown)

4.读取多文件多个sheet, 用read_sheets,列标题按第一个sheet的列标题给出,缺少的列用NULL填充

.system ls ???.xls

conv.xls demo.xls file.xls gbk2.xls

sql 复制代码
from read_sheets('/par/????.xls',sheets=['*'],header=1);
┌──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────────┐
│          id          │        title         │     inserted_at      │      updated_at      │         mapping          │
│       varchar        │       varchar        │       varchar        │       varchar        │         varchar          │
├──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────────┤
│ e6535268-e25a-4620...  │ 把下列句子翻译成英语 │ 2025-01-23T14:10:3...  │ 2025-01-23T14:48:2...  │ Length too long!         │
│ 74c16f63-675c-4bc8...  │ 货车运输成本最小化...  │ 2025-01-27T13:56:2...  │ 2025-01-27T14:06:5...  │ Length too long!         │
│ ·                    │  ·                   │  ·                   │  ·                   │  ·                       │
│ 23                   │ "doubly quoted str...  │ 'singly quoted str...  │ NULL                 │ NULL                     │
│ 24                   │ Formula:             │ The quick brown fox  │ 2                    │ NULL                     │
│ 1                    │ Tom                  │ 12.4                 │ NULL                 │ NULL                     │
│ 2                    │ Jerry                │ 3                    │ NULL                 │ NULL                     │
│ 3                    │ 张一                 │ -12                  │ NULL                 │ NULL                     │
├──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────────┤
│ 281 rows (40 shown)                                                                                        5 columns │
相关推荐
tung tung tung sahur24 分钟前
领略 Rust 抽象之美:自定义迭代器实现全解析
开发语言·后端·rust
微小冷26 分钟前
Rust图形界面egui初步教程
rust·编程语言·egui·用户图形界面·示例项目
ftpeak30 分钟前
《Rust MP4视频技术开发》第八章:生成MP4
开发语言·rust·音视频·mp4
王道长服务器 | 亚马逊云39 分钟前
帝国CMS + AWS:老牌内容系统的新生之路
服务器·网络·数据库·云计算·aws
李慕婉学姐1 小时前
Springboot的民宿管理系统的设计与实现29rhm9uh(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
l1t2 小时前
luadbi和luasql两种lua duckdb驱动的性能对比
开发语言·单元测试·lua·c·csv·duckdb
国服第二切图仔2 小时前
Rust开发实战之使用 Reqwest 实现 HTTP 客户端请求
开发语言·http·rust
云边有个稻草人2 小时前
Rust 借用分割技巧:安全解构复杂数据结构
数据结构·安全·rust
人工智能的苟富贵2 小时前
用 Rust 写一个前端项目辅助工具:JSON 格式化器
前端·rust·json
weixin_497845542 小时前
Windows系统Rust安装慢的问题
开发语言·后端·rust