测试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中用了。
代码如下:

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()

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

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/。
先看这个插件包括的函数

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,
例如

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

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

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

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

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

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

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

3.读取单文件多个sheet, 用read_sheets
通配符读取所有满足条件的sheet

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

也可以用明确的sheet名列表

from read_sheets('/par/400.xls',sheets=['一月','二月']);
┌──────────────────────┬─────────┬─────────┬────────────────┬
│  400热线分日工单情况 │    B    │    C    │       D        │ 
│       varcharvarcharvarcharvarchar     │ 
├──────────────────────┼─────────┼─────────┼────────────────┼
│ 分日工单情况         │ NULLNULL    │ 分类型工单数量 │
│ 日期                 │ 星期    │ 接起量  │ 口令\n问题     │ 
│ 2025-01-01           │ 元旦    │ 115              │ 
│     ·                │  ·      │ ·       │ ·              │
│ 2025-02-28           │ 周五    │ 19817             │
│ 合计                 │ NULL2637406            │
├──────────────────────┴─────────┴─────────┴────────────────┴
│ 65 rows (40 shown)

4.读取多文件多个sheet, 用read_sheets,列标题按第一个sheet的列标题给出,缺少的列用NULL填充
.system ls ???.xls
conv.xls demo.xls file.xls gbk2.xls

from read_sheets('/par/????.xls',sheets=['*'],header=1);
┌──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────────┐
│          id          │        title         │     inserted_at      │      updated_at      │         mapping          │
│       varcharvarcharvarcharvarcharvarchar          │
├──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────────┤
│ 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…  │ NULLNULL                     │
│ 24                   │ Formula:             │ The quick brown fox  │ 2NULL                     │
│ 1                    │ Tom                  │ 12.4NULLNULL                     │
│ 2                    │ Jerry                │ 3NULLNULL                     │
│ 3                    │ 张一                 │ -12NULLNULL                     │
├──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────────┤
│ 281 rows (40 shown)                                                                                        5 columns
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值