You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

采用二进制表示设计通讯录数据库的Python实现思路是否正确?

你的实现思路存在几个关键问题

嘿,你的核心想法(用二进制格式存储通讯录数据)本身没问题,但目前的实现方式绕了弯路,还会给后续的数据操作带来一堆麻烦,具体问题如下:

1. 完全没必要手动把数据转成二进制字符串

SQLite这类关系型数据库本身就会自动处理数据的底层二进制存储。比如你定义的INTEGER、VARCHAR类型,数据库引擎会以高效的二进制格式来存储它们,根本不需要你手动把整数转成bin()返回的"0b10"这类字符串,也不需要把字符串拆成字节再拼接成二进制字符串。

你现在把所有数据都转成了字符串类型存入数据库,比如原本的整数user_id变成了"0b1",这会导致:

  • 无法直接对user_id做数值运算(比如排序、范围查询)
  • 浪费存储空间:二进制字符串比原生数值/字符串占用更多字节
  • 后续读取数据时,还要自己写复杂的代码把这些二进制字符串还原成原数据,非常繁琐

2. 字符串转二进制的方式不合理

你把字符串转成bytearray后,每个字节调用bin()再拼接,比如"USER1"会变成一串类似0b101010100b1001010...的字符串,这种格式:

  • 没有分隔符,还原时很难准确拆分每个字节的二进制内容
  • 存储的是文本形式的二进制描述,不是真正的二进制字节流,完全失去了二进制存储的意义

正确的实现思路

如果你确实想以二进制格式存储(比如需要自定义序列化、加密场景),应该用SQLite的BLOB类型来存储二进制数据,而不是转成字符串。但对于普通通讯录场景,直接用SQLite的原生类型存储是最简单高效的:

修正后的代码示例

import sqlite3 as lite

con = lite.connect('address_book.db')
cur = con.cursor()

# 直接使用原生类型的数据,不需要手动转二进制
users = (
    (1, 'USER1', 'Surname1', 'Address1'),
    (2, 'USER2', 'Surname2', 'Address2'),
)

cur.execute("DROP TABLE IF EXISTS users")
cur.execute("""
    CREATE TABLE IF NOT EXISTS users(
        user_id INTEGER PRIMARY KEY,
        first_name VARCHAR(20) NOT NULL,
        last_name VARCHAR(20) NOT NULL,
        address VARCHAR(20) NOT NULL
    )
""")
# 直接插入原生数据,sqlite3会自动处理存储格式
cur.executemany("INSERT INTO users VALUES(?, ?, ?, ?)", users)
con.commit()

# 验证读取是否正常
cur.execute("SELECT * FROM users WHERE user_id = 1")
print(cur.fetchone())  # 输出 (1, 'USER1', 'Surname1', 'Address1'),和原数据一致

如果确实需要二进制存储(比如自定义序列化)

如果因为某些特殊需求必须手动处理二进制,可以用pickle把数据序列化字节流,然后存入BLOB字段:

import pickle
import sqlite3 as lite

con = lite.connect('address_book.db')
cur = con.cursor()

cur.execute("DROP TABLE IF EXISTS users_blob")
cur.execute("""
    CREATE TABLE IF NOT EXISTS users_blob(
        user_id INTEGER PRIMARY KEY,
        user_data BLOB NOT NULL
    )
""")

users = (
    (1, 'USER1', 'Surname1', 'Address1'),
    (2, 'USER2', 'Surname2', 'Address2'),
)

# 把用户数据序列化二进制字节流
for user_id, fname, lname, addr in users:
    user_data = pickle.dumps((fname, lname, addr))
    cur.execute("INSERT INTO users_blob VALUES(?, ?)", (user_id, user_data))

con.commit()

# 读取时反序列化
cur.execute("SELECT user_data FROM users_blob WHERE user_id = 1")
data = cur.fetchone()[0]
print(pickle.loads(data))  # 输出 ('USER1', 'Surname1', 'Address1')

总结一下:你的核心需求(二进制存储)可以通过数据库原生的BLOB类型或序列化工具实现,但手动转二进制字符串的做法是不必要的,反而会引入更多问题。

内容的提问来源于stack exchange,提问作者Ren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:47:21