Python中如何高效读取带算法与密钥的编码文件?维吉尼亚密码代码优化
维吉尼亚密码文档工具的优化方案
你当前实现了一个基于维吉尼亚密码的文档加密/解密工具,支持加密、解密预览、编辑文档和重新加密功能,核心逻辑可行,但在代码健壮性、性能和可读性上有不少可以优化的空间,具体改进方案如下:
原实现代码
keys = open("keys.txt") for i in keys: if "vg:" in i: vgKey = i.lstrip("vg: ") vgKey = vgKey.strip() keys.close() def encrypt(phrase,key=vgKey): alphabet = list("abcdefghijklmnopqrstuvwxyz") cypher = [] phrase = phrase.lower() keyCount = 0 for i in phrase: if i in alphabet: alphPos = alphabet.index(i) if keyCount > len(key)-1: keyCount -= len(key) alphPos += alphabet.index(key[keyCount]) if alphPos > 25: alphPos -= 26 cypher.append(alphabet[alphPos]) keyCount += 1 else: cypher.append(i) return "".join(cypher) def decrypt(cypher,key=vgKey): alphabet = list("abcdefghijklmnopqrstuvwxyz") phrase = [] cypher = cypher.lower() keyCount = 0 for i in cypher: if i in alphabet: alphPos = alphabet.index(i) if keyCount > len(key)-1: keyCount -= len(key) alphPos -= alphabet.index(key[keyCount]) if alphPos < 0: alphPos += 26 phrase.append(alphabet[alphPos]) keyCount += 1 else: phrase.append(i) return "".join(phrase) db = open("DBI.csv","w") dbEncrypted = open("DBIEncrypted.csv") for i in dbEncrypted: db.write(decrypt(i)) db.close() dbEncrypted.close() db = open("DBI.csv") dbCont = db.readlines() print("".join(dbCont)) row = input("Which row would you like to edit? Type n for a new row.\n") if row != "": text = input("What would you like the new value to be?\n") if row != "n": dbCont[int(row)] = text+"\n" elif row == "n": dbCont[len(dbCont)-1] += "\n" dbCont.append(text) db.close() dbEncrypted = open("DBIEncrypted.csv","w") for i in dbCont: dbEncrypted.write(encrypt(i)) dbEncrypted.close()
具体优化方案
1. 安全的文件操作:使用上下文管理器with
原代码手动调用close()容易因异常导致文件句柄泄漏,用with语句可以自动管理文件资源,无需手动关闭,同时添加默认密钥避免未找到匹配项时出错:
def load_key(file_path="keys.txt", default_key="default"): with open(file_path, "r") as f: for line in f: line = line.strip() if line.startswith("vg:"): return line.lstrip("vg: ").strip() return default_key
2. 加密/解密函数的性能与可读性优化
- 用字典替代列表查找:
list.index()是O(n)操作,换成字符到索引的字典映射,查找速度提升为O(1) - 取模运算简化密钥索引:替代手动的索引重置逻辑,代码更简洁高效
- 保留原字符大小写:原代码统一转小写,优化后可以区分大小写,加密后大写字符依然保持大写
- 抽象通用逻辑:加密和解密的核心逻辑高度重复,提取通用函数减少冗余代码
优化后的加密解密核心逻辑:
# 预定义字符映射,仅初始化一次 CHAR_TO_IDX = {c: i for i, c in enumerate("abcdefghijklmnopqrstuvwxyz")} IDX_TO_CHAR = {i: c for i, c in enumerate("abcdefghijklmnopqrstuvwxyz")} def _shift_char(char, key_char, shift_direction): """通用字符移位函数,shift_direction为1表示加密(加),-1表示解密(减)""" is_upper = char.isupper() char_lower = char.lower() if char_lower not in CHAR_TO_IDX: return char char_idx = CHAR_TO_IDX[char_lower] key_idx = CHAR_TO_IDX[key_char.lower()] new_idx = (char_idx + shift_direction * key_idx) % 26 new_char = IDX_TO_CHAR[new_idx] return new_char.upper() if is_upper else new_char def encrypt(phrase, key): key_len = len(key) result = [] key_idx = 0 for char in phrase: result.append(_shift_char(char, key[key_idx % key_len], 1)) if char.lower() in CHAR_TO_IDX: key_idx += 1 return "".join(result) def decrypt(cypher, key): key_len = len(key) result = [] key_idx = 0 for char in cypher: result.append(_shift_char(char, key[key_idx % key_len], -1)) if char.lower() in CHAR_TO_IDX: key_idx += 1 return "".join(result)
3. 避免临时文件,内存中处理内容
原代码把解密后的内容写入DBI.csv临时文件再重新读取,完全可以直接在内存中处理,减少磁盘IO开销:
def load_and_decrypt_file(file_path, key): with open(file_path, "r") as f: return decrypt(f.read(), key).splitlines(keepends=True)
4. 健壮的输入处理
原代码直接转换row为整数,若输入非数字会崩溃,添加异常处理;同时优化新行添加逻辑,避免多余换行符:
row = input("Which row would you like to edit? Type n for a new row.\n").strip() if row: text = input("What would you like the new value to be?\n").strip() if row.lower() == "n": decrypted_lines.append(text + "\n") else: try: row_idx = int(row) if 0 <= row_idx < len(decrypted_lines): decrypted_lines[row_idx] = text + "\n" else: print("Row index out of range") except ValueError: print("Invalid row number, please enter a number or 'n'")
5. 模块化代码结构
把功能拆分为独立函数,比如加载密钥、读取解密文件、保存加密文件,提升代码可读性和可维护性,同时添加主函数入口:
优化后的完整代码
def load_key(file_path="keys.txt", default_key="default"): with open(file_path, "r") as f: for line in f: line = line.strip() if line.startswith("vg:"): return line.lstrip("vg: ").strip() return default_key # 预定义字符映射,仅初始化一次 CHAR_TO_IDX = {c: i for i, c in enumerate("abcdefghijklmnopqrstuvwxyz")} IDX_TO_CHAR = {i: c for i, c in enumerate("abcdefghijklmnopqrstuvwxyz")} def _shift_char(char, key_char, shift_direction): """通用字符移位函数,shift_direction为1表示加密(加),-1表示解密(减)""" is_upper = char.isupper() char_lower = char.lower() if char_lower not in CHAR_TO_IDX: return char char_idx = CHAR_TO_IDX[char_lower] key_idx = CHAR_TO_IDX[key_char.lower()] new_idx = (char_idx + shift_direction * key_idx) % 26 new_char = IDX_TO_CHAR[new_idx] return new_char.upper() if is_upper else new_char def encrypt(phrase, key): key_len = len(key) result = [] key_idx = 0 for char in phrase: result.append(_shift_char(char, key[key_idx % key_len], 1)) if char.lower() in CHAR_TO_IDX: key_idx += 1 return "".join(result) def decrypt(cypher, key): key_len = len(key) result = [] key_idx = 0 for char in cypher: result.append(_shift_char(char, key[key_idx % key_len], -1)) if char.lower() in CHAR_TO_IDX: key_idx += 1 return "".join(result) def load_and_decrypt_file(file_path, key): with open(file_path, "r") as f: return decrypt(f.read(), key).splitlines(keepends=True) def save_encrypted_file(content_lines, file_path, key): encrypted_content = encrypt("".join(content_lines), key) with open(file_path, "w") as f: f.write(encrypted_content) def main(): # 加载密钥 vgKey = load_key() # 读取并解密文件 decrypted_lines = load_and_decrypt_file("DBIEncrypted.csv", vgKey) print("".join(decrypted_lines)) # 处理编辑输入 row = input("Which row would you like to edit? Type n for a new row.\n").strip() if row: text = input("What would you like the new value to be?\n").strip() if row.lower() == "n": decrypted_lines.append(text + "\n") else: try: row_idx = int(row) if 0 <= row_idx < len(decrypted_lines): decrypted_lines[row_idx] = text + "\n" else: print("Row index out of range") except ValueError: print("Invalid row number, please enter a number or 'n'") # 重新加密保存 save_encrypted_file(decrypted_lines, "DBIEncrypted.csv", vgKey) if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Euler
相关产品推荐
相关产品推荐

