测试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 │
相关推荐
TiAmo zhang3 小时前
SQL Server 2019实验 │ 表数据插入、修改和删除
数据库·oracle
慕容雪_3 小时前
MySQL去除表、字段注释
数据库·mysql
zym大哥大4 小时前
C++客服端访问redis
数据库·redis·缓存
洛克大航海4 小时前
Ubuntu安装Hbase
大数据·linux·数据库·ubuntu·hbase
小蒜学长4 小时前
springboot餐厅信息管理系统设计(代码+数据库+LW)
java·数据库·spring boot·后端
Justin_194 小时前
mysql数据库高级特性(一)
数据库·mysql
邂逅you5 小时前
用python操作mysql之pymysql库基本操作
数据库·python·mysql
心 一5 小时前
接口安全测试实战:从数据库错误泄露看如何构建安全防线
数据库·安全
点灯小铭5 小时前
基于单片机的PID调节脉动真空灭菌器上位机远程监控设计
数据库·单片机·嵌入式硬件·毕业设计·课程设计