下面給出在 Ubuntu 中把 dict.txt 導入 SQLite3 的實戰方案(含三種常見格式、命令逐行解釋、加速與校驗)。🧰
一、快速判斷文件格式
head -n 5 dict.txt
**解釋:**預覽前 5 行,確認是 單列(每行一個詞)、TSV(\t 分隔)、還是 CSV(, 分隔),並檢查是否含空格、中文、引號等字符。若編碼不是 UTF-8,可先轉碼:
iconv -f GB18030 -t UTF-8 dict.txt -o dict_utf8.txt && mv dict_utf8.txt dict.txt
**解釋:**將文件統一轉為 UTF-8,避免導入出現亂碼或報錯。<span style="color:red">UTF-8</span> 很關鍵。
二、方式一:SQLite3 內置導入(性能最佳,推薦)⚡
1)單列文本(每行一個詞)
sqlite3 dict.db
在 sqlite3 交互界面依次執行:
PRAGMA journal_mode=WAL;
PRAGMA synchronous=OFF;
CREATE TABLE IF NOT EXISTS dict(word TEXT PRIMARY KEY);
.mode csv
.import dict.txt dict
CREATE INDEX IF NOT EXISTS idx_word ON dict(word);
解釋:
PRAGMA journal_mode=WAL;開啓 <span style="color:red">WAL</span> 日誌,提升併發與導入速度。PRAGMA synchronous=OFF;犧牲少量崩潰恢復能力換取更快寫入(導入完可恢復默認)。CREATE TABLE…建立單列表,PRIMARY KEY便於唯一約束與查找(如已存在可跳過)。<span style="color:red">主鍵</span>有去重效果。.mode csv設為 CSV 模式;對“單列、無逗號”的文件同樣適用——每行即一列。.import dict.txt dict執行導入。CREATE INDEX…若未設主鍵,可單獨建索引;有主鍵時可不建。<span style="color:red">索引</span>能極大提升查詢性能。
2)TSV(形如 word[TAB]meaning)
PRAGMA journal_mode=WAL;
PRAGMA synchronous=OFF;
CREATE TABLE IF NOT EXISTS dict(word TEXT PRIMARY KEY, meaning TEXT);
.separator "\t"
.import dict.txt dict
解釋:
.separator "\t"明確按製表符分列。- 表結構包含
word與meaning兩列,更貼近詞典場景。設置 <span style="color:red">PRIMARY KEY</span> 可自動去重。
3)key:value 這種“冒號分隔”的文件
awk -F':' 'BEGIN{OFS=","} {gsub(/^[ \t]+|[ \t]+$/, "", $1); gsub(/^[ \t]+|[ \t]+$/, "", $2); print $1,$2}' dict.txt > dict.csv
sqlite3 dict.db -cmd "PRAGMA journal_mode=WAL;" -cmd "PRAGMA synchronous=OFF;" -cmd "CREATE TABLE IF NOT EXISTS dict(word TEXT PRIMARY KEY, meaning TEXT);" -cmd ".mode csv" -cmd ".import dict.csv dict"
解釋:
awk將:轉換為,並去除兩端空白,輸出為標準 CSV。- 之後用
.mode csv+.import一步導入。<span style="color:red">清洗</span>先行更穩妥。
三、方式二:Python 穩妥導入(可加校驗、去重、清洗)🧠
#!/usr/bin/env python3
import sqlite3, csv, sys
DB = "dict.db"
TXT = "dict.txt" # 若是冒號或製表符分隔,先轉換或按相應方式讀取
conn = sqlite3.connect(DB)
cur = conn.cursor()
cur.execute("PRAGMA journal_mode=WAL;")
cur.execute("PRAGMA synchronous=OFF;")
cur.execute("""
CREATE TABLE IF NOT EXISTS dict(
word TEXT PRIMARY KEY,
meaning TEXT
)
""")
batch = []
with open(TXT, "r", encoding="utf-8", newline="") as f:
# 假設 CSV:word,meaning;若單列,可把 meaning 置為 None
reader = csv.reader(f)
for row in reader:
if not row:
continue
if len(row) == 1:
batch.append((row[0].strip(), None))
else:
batch.append((row[0].strip(), row[1].strip()))
if len(batch) >= 5000:
cur.executemany("INSERT OR IGNORE INTO dict(word,meaning) VALUES(?,?)", batch)
batch.clear()
if batch:
cur.executemany("INSERT OR IGNORE INTO dict(word,meaning) VALUES(?,?)", batch)
conn.commit()
conn.close()
print("done")
解釋:
journal_mode=WAL、synchronous=OFF加速寫入。- 建表時將
word設為 <span style="color:red">PRIMARY KEY</span>,配合INSERT OR IGNORE可自動<span style="color:red">去重</span>。 - 批量
executemany(每 5000 行)可顯著提速;單列場景自動補meaning=None。 - Python 方式便於加入清洗、過濾、黑名單等業務規則。
四、導入完成後的校驗 ✅
SELECT COUNT(*) FROM dict;
SELECT * FROM dict LIMIT 5;
EXPLAIN QUERY PLAN SELECT meaning FROM dict WHERE word='example';
解釋:
COUNT(*)查看總行數是否與原文件行數接近(去重後會減少)。LIMIT 5抽樣核對。EXPLAIN QUERY PLAN…確認查詢是否走 <span style="color:red">索引</span>(應顯示使用主鍵或索引)。
五、常見報錯與處理 🧪
- “expected X columns but found 1”:表結構與文件列數不匹配;調整
.separator/.mode或先用awk轉換。 - “UNIQUE constraint failed”:存在重複鍵;使用
INSERT OR IGNORE,或導入前sort -u去重。 - 亂碼:統一為 <span style="color:red">UTF-8</span> 後再導入(見上文
iconv)。 - 導入過慢:確保
WAL、synchronous=OFF、大批量提交,並關閉無用觸發器/外鍵檢查(PRAGMA foreign_keys=OFF;)。
六、方法對比表
| 場景 | CLI .import |
Python 導入 |
|---|---|---|
| 性能(大文件) | <span style="color:red">高</span> | 中-高 |
| 清洗/邏輯 | 一般 | <span style="color:red">強</span> |
| 上手成本 | 低 | 中 |
| 去重能力 | 主鍵/索引 | OR IGNORE/自定義 |
七、導入流程圖(vditor/mermaid)
小結:優先選擇 SQLite CLI + .import(配合 <span style="color:red">事務</span> 與 <span style="color:red">WAL</span>),在需要複雜清洗時切換 Python。無論哪種方式,都請保證 UTF-8、表結構匹配、主鍵/索引 完整到位。