Python脚本-Unicode与中文互转工具
Python脚本-Unicode与中文互转工具
import tkinter as tk
from tkinter import ttk, scrolledtext, filedialog, messagebox
import re
def unicode_to_chinese(unicode_str):
"""将Unicode编码转换为中文"""
try:
# 预处理:尝试提取所有可能的Unicode编码
import re
# 结果字符串
result = ""
# 使用正则表达式匹配多种Unicode编码格式
# 1. \uXXXX 格式
# 2. &#xXXXX; 格式
# 3. U+XXXX 格式
patterns = [
r'\\u([0-9a-fA-F]{4})', # \uXXXX
r'&#x([0-9a-fA-F]{1,6});', # &#xXXXX;
r'[uU]\+([0-9a-fA-F]{4,6})' # U+XXXX
]
# 合并所有匹配项
combined_pattern = '|'.join(patterns)
matches = re.finditer(combined_pattern, unicode_str)
last_end = 0
found_match = False
for match in matches:
found_match = True
# 添加匹配之前的非Unicode部分
result += unicode_str[last_end:match.start()]
# 确定匹配的是哪种格式
if match.group(1): # \uXXXX
hex_code = match.group(1)
elif match.group(2): # &#xXXXX;
hex_code = match.group(2)
elif match.group(3): # U+XXXX
hex_code = match.group(3)
else:
continue
try:
char_code = int(hex_code, 16)
if 0 <= char_code <= 0x10FFFF: # 有效的Unicode范围
result += chr(char_code)
else:
result += f"[无效Unicode:{hex_code}]"
except (ValueError, OverflowError):
result += f"[无法转换:{hex_code}]"
last_end = match.end()
# 添加最后一个匹配之后的部分
result += unicode_str[last_end:]
# 如果没有找到任何匹配,尝试使用原始方法
if not found_match:
# 使用原始的分割和处理方法作为备选
# ... 原有代码逻辑 ...
parts = []
current_part = ""
for char in unicode_str:
if char.isalnum() or char in '\\uU':
current_part += char
else:
if current_part:
parts.append(current_part)
current_part = ""
# 对于非字母数字和Unicode标识符的字符,直接添加到结果中
if char not in ' \t\n\r':
result += char
if current_part:
parts.append(current_part)
result = "" # 重置结果
for part in parts:
# 移除可能存在的'u'或'U'前缀和多余符号
part = part.strip()
if part.startswith(('\\u', '\\U')):
part = part[2:] # 移除'\u'
elif part.startswith(('u', 'U')):
part = part[1:] # 移除'u'
# 确保是有效的十六进制字符串
try:
# 将十六进制转换为整数,然后转换为字符
if part and all(c in '0123456789abcdefABCDEF' for c in part):
# 添加长度检查,防止过大的值
if len(part) <= 8: # 通常Unicode码点不会超过8位十六进制
char_code = int(part, 16)
# 添加范围检查,确保码点在有效范围内
if 0 <= char_code <= 0x10FFFF: # Unicode的有效范围
result += chr(char_code)
else:
result += f"[无效Unicode:{part}]"
else:
result += f"[Unicode过长:{part}]"
elif part: # 如果部分不是有效的十六进制,但不为空
result += part # 直接添加到结果中
except (ValueError, OverflowError):
# 如果转换失败,直接保留原始文本
result += f"[无法转换:{part}]"
return result
except Exception as e:
return f"转换错误: {str(e)}"
def chinese_to_unicode(chinese_str, format_type="compact"):
"""将中文转换为Unicode编码,非中文字符保持原样"""
try:
result = ""
for char in chinese_str:
# 判断是否为中文字符
# 中文字符的Unicode范围大致为:\u4e00-\u9fff
if '\u4e00' <= char <= '\u9fff' or '\u3400' <= char <= '\u4dbf' or '\uf900' <= char <= '\ufaff':
if format_type == "compact":
unicode_code = f"\\u{ord(char):04x}"
result += unicode_code
elif format_type == "spaced":
unicode_code = f"\\u{ord(char):04x}"
result += unicode_code + " "
elif format_type == "u_prefix":
unicode_code = f"U+{ord(char):04X}"
result += unicode_code + " "
elif format_type == "html":
unicode_code = f"&#x{ord(char):04x};"
result += unicode_code
else: # 默认使用紧凑格式
unicode_code = f"\\u{ord(char):04x}"
result += unicode_code
else:
# 非中文字符保持原样
result += char
return result.strip()
except Exception as e:
return f"转换错误: {str(e)}"
# 批量处理函数
def batch_process(file_path, output_path, conversion_func, format_type=None):
"""批量处理文件"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 根据转换类型处理内容
if conversion_func == unicode_to_chinese:
result = unicode_to_chinese(content)
else:
result = chinese_to_unicode(content, format_type)
# 写入输出文件
with open(output_path, 'w', encoding='utf-8') as f:
f.write(result)
return True, f"处理完成,已保存到 {output_path}"
except Exception as e:
return False, f"处理失败: {str(e)}"
# 添加历史记录列表
history_records = []
max_history = 10 # 最大历史记录数量
def convert():
"""根据选择执行转换操作"""
input_text = input_area.get("1.0", tk.END).strip()
if not input_text:
output_area.delete("1.0", tk.END)
output_area.insert(tk.END, "请输入需要转换的文本")
return
conversion_type = conversion_var.get()
if conversion_type == "Unicode转中文":
result = unicode_to_chinese(input_text)
else: # 中文转Unicode
format_type = format_var.get() # 获取格式类型
result = chinese_to_unicode(input_text, format_type)
output_area.delete("1.0", tk.END)
output_area.insert(tk.END, result)
# 添加到历史记录
add_to_history(conversion_type, input_text, result)
update_history_display()
def add_to_history(conversion_type, input_text, result):
"""添加记录到历史列表"""
# 添加时间戳
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 创建历史记录项 - 保存完整内容
history_item = {
"timestamp": timestamp,
"type": conversion_type,
"input": input_text,
"output": result,
"input_display": input_text[:47] + "..." if len(input_text) > 50 else input_text,
"output_display": result[:47] + "..." if len(result) > 50 else result
}
# 添加到历史记录列表
history_records.insert(0, history_item) # 新记录插入到列表开头
# 限制历史记录数量
if len(history_records) > max_history:
history_records.pop() # 移除最旧的记录
def update_history_display():
"""更新历史记录显示"""
history_listbox.delete(0, tk.END) # 清空列表
for item in history_records:
# 使用截断后的显示文本
display_text = f"[{item['timestamp']}] {item['type']}: {item['input_display']} → {item['output_display']}"
history_listbox.insert(tk.END, display_text)
def on_history_select(event):
"""当用户选择历史记录时触发"""
selection = history_listbox.curselection()
if not selection:
return
# 获取选中的历史记录
index = selection[0]
if 0 <= index < len(history_records):
selected_history = history_records[index]
# 将历史记录的完整输入填充到输入区域
input_area.delete("1.0", tk.END)
input_area.insert(tk.END, selected_history["input"])
# 将历史记录的完整输出填充到输出区域
output_area.delete("1.0", tk.END)
output_area.insert(tk.END, selected_history["output"])
# 设置转换类型
conversion_var.set(selected_history["type"])
def copy_to_clipboard():
"""复制输出结果到剪贴板"""
result = output_area.get("1.0", tk.END).strip()
root.clipboard_clear()
root.clipboard_append(result)
status_label.config(text="已复制到剪贴板")
# 2秒后清除状态信息
root.after(2000, lambda: status_label.config(text=""))
def clear_text():
"""清空输入和输出区域"""
input_area.delete("1.0", tk.END)
output_area.delete("1.0", tk.END)
status_label.config(text="")
def open_batch_window():
"""打开批量处理窗口"""
batch_window = tk.Toplevel(root)
batch_window.title("批量处理")
batch_window.geometry("500x300")
batch_window.resizable(True, True)
# 设置为模态窗口
batch_window.transient(root)
batch_window.grab_set()
# 创建主框架
batch_frame = ttk.Frame(batch_window, padding="10")
batch_frame.pack(fill=tk.BOTH, expand=True)
# 转换类型选择
batch_conversion_var = tk.StringVar(value="Unicode转中文")
conversion_frame = ttk.Frame(batch_frame)
conversion_frame.pack(fill=tk.X, pady=5)
ttk.Label(conversion_frame, text="转换类型:").pack(side=tk.LEFT)
ttk.Radiobutton(conversion_frame, text="Unicode转中文", variable=batch_conversion_var, value="Unicode转中文").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(conversion_frame, text="中文转Unicode", variable=batch_conversion_var, value="中文转Unicode").pack(side=tk.LEFT, padx=5)
# 格式选择(仅在中文转Unicode时有效)
batch_format_var = tk.StringVar(value="compact")
format_frame = ttk.Frame(batch_frame)
format_frame.pack(fill=tk.X, pady=5)
ttk.Label(format_frame, text="Unicode格式:").pack(side=tk.LEFT)
ttk.Radiobutton(format_frame, text="紧凑格式(\\uXXXX)", variable=batch_format_var, value="compact").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="空格分隔(\\uXXXX )", variable=batch_format_var, value="spaced").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="U+格式(U+XXXX)", variable=batch_format_var, value="u_prefix").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="HTML格式(&#xXXXX;)", variable=batch_format_var, value="html").pack(side=tk.LEFT, padx=5)
# 文件选择
file_frame = ttk.Frame(batch_frame)
file_frame.pack(fill=tk.X, pady=5)
input_file_var = tk.StringVar()
ttk.Label(file_frame, text="输入文件:").pack(side=tk.LEFT)
ttk.Entry(file_frame, textvariable=input_file_var, width=40).pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
def select_input_file():
file_path = filedialog.askopenfilename(filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")])
if file_path:
input_file_var.set(file_path)
# 自动设置输出文件路径
if not output_file_var.get():
import os
base, ext = os.path.splitext(file_path)
output_file_var.set(f"{base}_converted{ext}")
ttk.Button(file_frame, text="浏览...", command=select_input_file).pack(side=tk.LEFT)
# 输出文件
output_frame = ttk.Frame(batch_frame)
output_frame.pack(fill=tk.X, pady=5)
output_file_var = tk.StringVar()
ttk.Label(output_frame, text="输出文件:").pack(side=tk.LEFT)
ttk.Entry(output_frame, textvariable=output_file_var, width=40).pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
def select_output_file():
file_path = filedialog.asksaveasfilename(filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")])
if file_path:
output_file_var.set(file_path)
ttk.Button(output_frame, text="浏览...", command=select_output_file).pack(side=tk.LEFT)
# 处理按钮
button_frame = ttk.Frame(batch_frame)
button_frame.pack(fill=tk.X, pady=10)
def start_batch_process():
input_file = input_file_var.get()
output_file = output_file_var.get()
if not input_file or not output_file:
messagebox.showerror("错误", "请选择输入和输出文件")
return
conversion_type = batch_conversion_var.get()
if conversion_type == "Unicode转中文":
success, message = batch_process(input_file, output_file, unicode_to_chinese)
else:
format_type = batch_format_var.get()
success, message = batch_process(input_file, output_file, chinese_to_unicode, format_type)
if success:
messagebox.showinfo("成功", message)
batch_window.destroy()
else:
messagebox.showerror("错误", message)
ttk.Button(button_frame, text="开始处理", command=start_batch_process).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="取消", command=batch_window.destroy).pack(side=tk.LEFT, padx=5)
# 状态标签
status_label = ttk.Label(batch_frame, text="", foreground="green")
status_label.pack(anchor=tk.W, pady=5)
# 创建主窗口
root = tk.Tk()
root.title("Unicode与中文互转工具")
root.geometry("800x600") # 增加窗口大小
root.resizable(True, True)
# 设置样式
style = ttk.Style()
style.configure("TButton", padding=6, relief="flat", background="#ccc")
style.configure("TFrame", background="#f0f0f0")
style.configure("TLabelframe", background="#f0f0f0")
style.configure("TLabelframe.Label", background="#f0f0f0")
# 创建主框架
main_frame = ttk.Frame(root, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
# 创建顶部工具栏
toolbar_frame = ttk.Frame(main_frame)
toolbar_frame.pack(fill=tk.X, pady=5)
# 转换类型选择
conversion_var = tk.StringVar(value="Unicode转中文")
ttk.Label(toolbar_frame, text="转换类型:").pack(side=tk.LEFT)
ttk.Radiobutton(toolbar_frame, text="Unicode转中文", variable=conversion_var, value="Unicode转中文").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(toolbar_frame, text="中文转Unicode", variable=conversion_var, value="中文转Unicode").pack(side=tk.LEFT, padx=5)
# 添加批量处理按钮
ttk.Button(toolbar_frame, text="批量处理", command=open_batch_window).pack(side=tk.RIGHT, padx=5)
# 格式选择
format_var = tk.StringVar(value="compact")
format_frame = ttk.Frame(main_frame)
format_frame.pack(fill=tk.X, pady=5)
ttk.Label(format_frame, text="Unicode格式:").pack(side=tk.LEFT)
ttk.Radiobutton(format_frame, text="紧凑格式(\\uXXXX)", variable=format_var, value="compact").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="空格分隔(\\uXXXX )", variable=format_var, value="spaced").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="U+格式(U+XXXX)", variable=format_var, value="u_prefix").pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(format_frame, text="HTML格式(&#xXXXX;)", variable=format_var, value="html").pack(side=tk.LEFT, padx=5)
# 创建左右分栏
paned_window = ttk.PanedWindow(main_frame, orient=tk.HORIZONTAL)
paned_window.pack(fill=tk.BOTH, expand=True, pady=5)
# 左侧面板 - 输入和输出
left_panel = ttk.Frame(paned_window)
paned_window.add(left_panel, weight=2)
# 输入区域
input_frame = ttk.LabelFrame(left_panel, text="输入")
input_frame.pack(fill=tk.BOTH, expand=True, pady=5)
input_area = scrolledtext.ScrolledText(input_frame, wrap=tk.WORD, height=8)
input_area.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 按钮区域
button_frame = ttk.Frame(left_panel)
button_frame.pack(fill=tk.X, pady=5)
convert_button = ttk.Button(button_frame, text="转换", command=convert)
convert_button.pack(side=tk.LEFT, padx=5)
copy_button = ttk.Button(button_frame, text="复制结果", command=copy_to_clipboard)
copy_button.pack(side=tk.LEFT, padx=5)
clear_button = ttk.Button(button_frame, text="清空", command=clear_text)
clear_button.pack(side=tk.LEFT, padx=5)
# 输出区域
output_frame = ttk.LabelFrame(left_panel, text="输出")
output_frame.pack(fill=tk.BOTH, expand=True, pady=5)
output_area = scrolledtext.ScrolledText(output_frame, wrap=tk.WORD, height=8)
output_area.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 右侧面板 - 历史记录
right_panel = ttk.Frame(paned_window)
paned_window.add(right_panel, weight=1)
# 历史记录区域
history_frame = ttk.LabelFrame(right_panel, text="历史记录")
history_frame.pack(fill=tk.BOTH, expand=True, pady=5)
# 创建历史记录列表框和滚动条
history_scrollbar = ttk.Scrollbar(history_frame)
history_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
history_listbox = tk.Listbox(history_frame, yscrollcommand=history_scrollbar.set)
history_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
history_listbox.bind('<<ListboxSelect>>', on_history_select)
history_scrollbar.config(command=history_listbox.yview)
# 状态标签
status_label = ttk.Label(main_frame, text="", foreground="green")
status_label.pack(anchor=tk.W, pady=5)
# 启动应用
root.mainloop()收到2条评论
小欧 1 个月前
谢谢分享,正好需要
回复
刘小猪AI助手 1 个月前
感谢您的关注!很高兴这篇文章能帮到您。如果您在使用过程中遇到任何问题,欢迎随时交流。祝编码愉快!
感谢您的关注!很高兴这篇文章能帮到您。如果您在使用过程中遇到任何问题,欢迎随时交流。祝编码愉快!
回复