【Python】TXT、BIN文件的十六进制相互转换小程序

【Python】TXT、BIN文件的十六进制相互转换小程序

文章目录

TXT文件格式

以ASCII码字符串为内容,16进制字节为数据,每个字节数据中间以空格隔开

如:

python 复制代码
 32 32 0A 7E 2E 32 62 C0 30 21 00 5B 44 5D 20 3A 20 74 69 6D 65 3A 31 31 2E 30 30 30 2C 74 6F 74 61 6C 20 6D 69 6C 3A 30 2C 53 4F 48 3A 31 30 30 0A 7E 5B 33 16 92 31 21 00 5B 44 5D 20 3A 20 74 69 6D 65 3A 31 31 2E 30 30 30 2C 62 61 74 5F 63 79 63 6C 65 5F 63 6F 75 6E 74 3A 30 2C 62 61 74 5F 72 65 6D 61 69 6E 5F 70 6F 77 65 72 3A 36 38 36 2C 62 61 74 5F 6F 76 65 72 5F 64 69 73 63 68 61 72 67 65 5F 74 69 6D 65 3A 30 0A 7E 50 34 1A 40 33 21 00 5B 44 5D 20 3A 20 74 69 6D 65 3A 31 32 2E 30 30 30 2C 6D 6F 64 65 3A 31 38 2C 67 65 61 72 3A 32 2C 73 70 65 65 64 3A 30 2C 61 63 63 3A 30 2C 6C 65 66 74 42 72 61 6B 65 3A 30 2C 72 69 67 68 74 42 72 61 6B 65 3A 30 0A 7E 59 35 12 12 34 21 00 5B 44 5D 20 3A 20 74 69 6D 65 3A 31 32 2E 30 30 30 2C 42 4D 53 20 73 6F 63 3A 39 34 2C 52 65 6D 61 69 6E 20 6D 69 6C 3A 35 31 37 2C 76 6F 6C 74 61 67 65 3A 35 32 34 2C 63 75 72 72 65 6E 74 3A 30 2C 74 65 6D 70 65 72 61 74 75 72 65 3A 32 32 0A 7E 2E 36 66 E4 34 21 00 5B 44 5D 20 3A 20 74 69 6D 65 3A 31 32 2E 30 30 30 2C 74 6F 74 61 6C 20 6D 69 6C 3A 30 2C 53 4F 48 3A 31 30 30 0A 7E 

BIN文件样式

BIN文件为二进制文件 以二进制形式打开后 可以看到同txt一样的效果

Python代码

python 复制代码
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import struct

class FileConverterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("TXT-BIN 文件转换器")
        self.root.geometry("900x600")
        
        # 创建主框架
        main_frame = ttk.Frame(root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)
        
        # 标题
        title_label = ttk.Label(main_frame, text="TXT-BIN 文件转换器", font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
        
        # 创建左右两个框架
        self.create_left_frame(main_frame)  # TXT转BIN
        self.create_right_frame(main_frame)  # BIN转TXT
        
        # 初始化文件列表
        self.txt_files = []
        self.bin_files = []
        
    def create_left_frame(self, parent):
        """创建左侧TXT转BIN框架"""
        left_frame = ttk.LabelFrame(parent, text="TXT 转 BIN", padding="10")
        left_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 5))
        left_frame.columnconfigure(0, weight=1)
        left_frame.rowconfigure(3, weight=1)
        
        # 选择TXT文件按钮
        txt_select_btn = ttk.Button(left_frame, text="选择TXT文件", command=self.select_txt_files)
        txt_select_btn.grid(row=0, column=0, sticky=tk.W, pady=(0, 10))
        
        # 选择的TXT文件列表标签
        txt_files_label = ttk.Label(left_frame, text="选择的TXT文件:")
        txt_files_label.grid(row=1, column=0, sticky=tk.W, pady=(0, 5))
        
        # TXT文件列表
        self.txt_listbox = tk.Listbox(left_frame, height=6)
        self.txt_listbox.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 滚动条
        txt_scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=self.txt_listbox.yview)
        txt_scrollbar.grid(row=2, column=1, sticky=(tk.N, tk.S), pady=(0, 10))
        self.txt_listbox.configure(yscrollcommand=txt_scrollbar.set)
        
        # 输出目录标签
        self.output_dir_label = ttk.Label(left_frame, text="输出目录: ")
        self.output_dir_label.grid(row=3, column=0, sticky=tk.W, pady=(0, 5))
        
        # 输出文件列表标签
        output_files_label = ttk.Label(left_frame, text="输出BIN文件:")
        output_files_label.grid(row=4, column=0, sticky=tk.W, pady=(0, 5))
        
        # 输出文件列表
        self.output_bin_listbox = tk.Listbox(left_frame, height=6)
        self.output_bin_listbox.grid(row=5, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 转换按钮
        convert_txt_btn = ttk.Button(left_frame, text="TXT转BIN", command=self.convert_txt_to_bin)
        convert_txt_btn.grid(row=6, column=0, pady=10)
        
    def create_right_frame(self, parent):
        """创建右侧BIN转TXT框架"""
        right_frame = ttk.LabelFrame(parent, text="BIN 转 TXT", padding="10")
        right_frame.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(5, 0))
        right_frame.columnconfigure(0, weight=1)
        right_frame.rowconfigure(3, weight=1)
        
        # 选择BIN文件按钮
        bin_select_btn = ttk.Button(right_frame, text="选择BIN文件", command=self.select_bin_files)
        bin_select_btn.grid(row=0, column=0, sticky=tk.W, pady=(0, 10))
        
        # 选择的BIN文件列表标签
        bin_files_label = ttk.Label(right_frame, text="选择的BIN文件:")
        bin_files_label.grid(row=1, column=0, sticky=tk.W, pady=(0, 5))
        
        # BIN文件列表
        self.bin_listbox = tk.Listbox(right_frame, height=6)
        self.bin_listbox.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 滚动条
        bin_scrollbar = ttk.Scrollbar(right_frame, orient=tk.VERTICAL, command=self.bin_listbox.yview)
        bin_scrollbar.grid(row=2, column=1, sticky=(tk.N, tk.S), pady=(0, 10))
        self.bin_listbox.configure(yscrollcommand=bin_scrollbar.set)
        
        # 输出目录标签
        self.output_dir_label_bin = ttk.Label(right_frame, text="输出目录: ")
        self.output_dir_label_bin.grid(row=3, column=0, sticky=tk.W, pady=(0, 5))
        
        # 输出文件列表标签
        output_files_label_bin = ttk.Label(right_frame, text="输出TXT文件:")
        output_files_label_bin.grid(row=4, column=0, sticky=tk.W, pady=(0, 5))
        
        # 输出文件列表
        self.output_txt_listbox = tk.Listbox(right_frame, height=6)
        self.output_txt_listbox.grid(row=5, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 转换按钮
        convert_bin_btn = ttk.Button(right_frame, text="BIN转TXT", command=self.convert_bin_to_txt)
        convert_bin_btn.grid(row=6, column=0, pady=10)
        
    def select_txt_files(self):
        """选择TXT文件"""
        files = filedialog.askopenfilenames(
            title="选择TXT文件",
            filetypes=[("TXT files", "*.txt"), ("All files", "*.*")]
        )
        
        if files:
            self.txt_files = list(files)
            self.update_txt_lists()
    
    def select_bin_files(self):
        """选择BIN文件"""
        files = filedialog.askopenfilenames(
            title="选择BIN文件",
            filetypes=[("BIN files", "*.bin"), ("All files", "*.*")]
        )
        
        if files:
            self.bin_files = list(files)
            self.update_bin_lists()
    
    def update_txt_lists(self):
        """更新TXT文件相关列表"""
        # 清空列表
        self.txt_listbox.delete(0, tk.END)
        self.output_bin_listbox.delete(0, tk.END)
        
        if self.txt_files:
            # 获取第一个文件的目录作为输出目录
            first_file_dir = os.path.dirname(self.txt_files[0])
            self.output_dir_label.config(text=f"输出目录: {first_file_dir}")
            
            # 添加文件到列表
            for file_path in self.txt_files:
                # 显示文件名
                file_name = os.path.basename(file_path)
                self.txt_listbox.insert(tk.END, file_name)
                
                # 生成输出文件名
                output_name = os.path.splitext(file_name)[0] + ".bin"
                self.output_bin_listbox.insert(tk.END, output_name)
    
    def update_bin_lists(self):
        """更新BIN文件相关列表"""
        # 清空列表
        self.bin_listbox.delete(0, tk.END)
        self.output_txt_listbox.delete(0, tk.END)
        
        if self.bin_files:
            # 获取第一个文件的目录作为输出目录
            first_file_dir = os.path.dirname(self.bin_files[0])
            self.output_dir_label_bin.config(text=f"输出目录: {first_file_dir}")
            
            # 添加文件到列表
            for file_path in self.bin_files:
                # 显示文件名
                file_name = os.path.basename(file_path)
                self.bin_listbox.insert(tk.END, file_name)
                
                # 生成输出文件名
                output_name = os.path.splitext(file_name)[0] + ".txt"
                self.output_txt_listbox.insert(tk.END, output_name)
    
    def convert_txt_to_bin(self):
        """将TXT文件转换为BIN文件"""
        if not self.txt_files:
            messagebox.showwarning("警告", "请先选择TXT文件")
            return
        
        success_count = 0
        error_count = 0
        
        for txt_file in self.txt_files:
            try:
                # 读取TXT文件
                with open(txt_file, 'r', encoding='utf-8') as f:
                    content = f.read().strip()
                
                # 解析16进制字符串
                hex_strings = content.split()
                hex_bytes = []
                
                for hex_str in hex_strings:
                    # 确保是有效的16进制字符串
                    if len(hex_str) == 2 and all(c in '0123456789ABCDEFabcdef' for c in hex_str):
                        hex_bytes.append(int(hex_str, 16))
                    else:
                        raise ValueError(f"无效的16进制字符串: {hex_str}")
                
                # 生成输出文件名
                output_dir = os.path.dirname(txt_file)
                output_name = os.path.splitext(os.path.basename(txt_file))[0] + ".bin"
                output_path = os.path.join(output_dir, output_name)
                
                # 写入BIN文件
                with open(output_path, 'wb') as f:
                    f.write(bytes(hex_bytes))
                
                success_count += 1
                
            except Exception as e:
                error_count += 1
                messagebox.showerror("错误", f"转换文件 {os.path.basename(txt_file)} 时出错:\n{str(e)}")
        
        if success_count > 0:
            messagebox.showinfo("完成", f"成功转换 {success_count} 个文件")
        if error_count > 0:
            messagebox.showwarning("部分完成", f"有 {error_count} 个文件转换失败")
    
    def convert_bin_to_txt(self):
        """将BIN文件转换为TXT文件"""
        if not self.bin_files:
            messagebox.showwarning("警告", "请先选择BIN文件")
            return
        
        success_count = 0
        error_count = 0
        
        for bin_file in self.bin_files:
            try:
                # 读取BIN文件
                with open(bin_file, 'rb') as f:
                    binary_data = f.read()
                
                # 转换为16进制字符串
                hex_strings = [format(byte, '02X') for byte in binary_data]
                txt_content = ' '.join(hex_strings)
                
                # 生成输出文件名
                output_dir = os.path.dirname(bin_file)
                output_name = os.path.splitext(os.path.basename(bin_file))[0] + ".txt"
                output_path = os.path.join(output_dir, output_name)
                
                # 写入TXT文件
                with open(output_path, 'w', encoding='utf-8') as f:
                    f.write(txt_content)
                
                success_count += 1
                
            except Exception as e:
                error_count += 1
                messagebox.showerror("错误", f"转换文件 {os.path.basename(bin_file)} 时出错:\n{str(e)}")
        
        if success_count > 0:
            messagebox.showinfo("完成", f"成功转换 {success_count} 个文件")
        if error_count > 0:
            messagebox.showwarning("部分完成", f"有 {error_count} 个文件转换失败")

def main():
    root = tk.Tk()
    app = FileConverterApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()

运行效果

附录:列表的赋值类型和py打包

列表赋值

BUG复现

闲来无事写了个小程序 代码如下:

python 复制代码
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021

@author: 16016
"""

a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):
    for j in range(16):
        a_list[j]=str(a_list[j])+'_'+str(j)
        print("序号:",j)
        print('a_list:\n',a_list)
        
        
        c_list[j]=a_list
        print('c_list[0]:\n',c_list[0])
        print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])
        # 写入到Excel:
#print(c_list,'\n')    

我在程序中 做了一个16次的for循环 把列表a的每个值后面依次加上"_"和循环序号

比如循环第x次 就是把第x位加上_x 这一位变成x_x 我在输出测试中 列表a的每一次输出也是对的

循环16次后列表a应该变成['0_0', '1_1', '2_2', '3_3', '4_4', '5_5', '6_6', '7_7', '8_8', '9_9', '10_10', '11_11', '12_12', '13_13', '14_14', '15_15'] 这也是对的

同时 我将每一次循环时列表a的值 写入到空列表c中 比如第x次循环 就是把更改以后的列表a的值 写入到列表c的第x位

第0次循环后 c[0]的值应该是['0_0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] 这也是对的

但是在第1次循环以后 c[0]的值就一直在变 变成了c[x]的值

相当于把c_list[0]变成了c_list[1]...以此类推 最后得出的列表c的值也是每一项完全一样

我不明白这是怎么回事

我的c[0]只在第0次循环时被赋值了 但是后面它的值跟着在改变

如图:

第一次老出bug 赋值以后 每次循环都改变c[0]的值 搞了半天都没搞出来

无论是用appen函数添加 还是用二维数组定义 或者增加第三个空数组来过渡 都无法解决

代码改进

后来在我华科同学的指导下 突然想到赋值可以赋的是个地址 地址里面的值一直变化 导致赋值也一直变化 于是用第二张图的循环套循环深度复制实现了

代码如下:

python 复制代码
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021

@author: 16016
"""

a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):
    for j in range(16):
        a_list[j]=str(a_list[j])+'_'+str(j)
        print("序号:",j)
        print('a_list:\n',a_list)
        
        
        for i in range(16):
            c_list[j].append(a_list[i])
        print('c_list[0]:\n',c_list[0])
        print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])
        # 写入到Excel:
print(c_list,'\n')    

解决了问题

优化

第三次是请教了老师 用copy函数来赋真值

代码如下:

python 复制代码
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021

@author: 16016
"""

a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):
    for j in range(16):
        a_list[j]=str(a_list[j])+'_'+str(j)
        print("序号:",j)
        print('a_list:\n',a_list)
        
        
        c_list[j]=a_list.copy()
        print('c_list[0]:\n',c_list[0])
        print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])
        # 写入到Excel:
#print(c_list,'\n')    

同样能解决问题

最后得出问题 就是指针惹的祸!

a_list指向的是个地址 而不是值 a_list[i]指向的才是单个的值 copy()函数也是复制值而不是地址

如果这个用C语言来写 就直观一些了 难怪C语言是基础 光学Python不学C 遇到这样的问题就解决不了

C语言yyds Python是什么垃圾弱智语言

总结

由于Python无法单独定义一个值为指针或者独立的值 所以只能用列表来传送

只要赋值是指向一个列表整体的 那么就是指向的一个指针内存地址 解决方法只有一个 那就是将每个值深度复制赋值(子列表内的元素提取出来重新依次连接) 或者用copy函数单独赋值

如图测试:




部分代码:

python 复制代码
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 20 16:45:48 2021

@author: 16016
"""

def text1():
    A=[1,2,3]
    B=[[],[],[]]
    for i in range(len(A)):
        A[i]=A[i]+i
        B[i]=A
        print(B)

def text2():
    A=[1,2,3]
    B=[[],[],[]]
    
    A[0]=A[0]+0
    B[0]=A
    print(B)
    A[1]=A[1]+1
    B[1]=A
    print(B)
    A[2]=A[2]+2
    B[2]=A
    print(B)
    
if __name__ == '__main__':
    text1()
    print('\n')
    text2()

py打包

Pyinstaller打包exe(包括打包资源文件 绝不出错版)

依赖包及其对应的版本号

PyQt5 5.10.1

PyQt5-Qt5 5.15.2

PyQt5-sip 12.9.0

pyinstaller 4.5.1

pyinstaller-hooks-contrib 2021.3

Pyinstaller -F setup.py 打包exe

Pyinstaller -F -w setup.py 不带控制台的打包

Pyinstaller -F -i xx.ico setup.py 打包指定exe图标打包

打包exe参数说明:

-F:打包后只生成单个exe格式文件;

-D:默认选项,创建一个目录,包含exe文件以及大量依赖文件;

-c:默认选项,使用控制台(就是类似cmd的黑框);

-w:不使用控制台;

-p:添加搜索路径,让其找到对应的库;

-i:改变生成程序的icon图标。

如果要打包资源文件

则需要对代码中的路径进行转换处理

另外要注意的是 如果要打包资源文件 则py程序里面的路径要从./xxx/yy换成xxx/yy 并且进行路径转换

但如果不打包资源文件的话 最好路径还是用作./xxx/yy 并且不进行路径转换

python 复制代码
def get_resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

而后再spec文件中的datas部分加入目录

如:

python 复制代码
a = Analysis(['cxk.py'],
             pathex=['D:\\Python Test\\cxk'],
             binaries=[],
             datas=[('root','root')],
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

而后直接Pyinstaller -F setup.spec即可

如果打包的文件过大则更改spec文件中的excludes 把不需要的库写进去(但是已经在环境中安装了的)就行

这些不要了的库在上一次编译时的shell里面输出

比如:

然后用pyinstaller --clean -F 某某.spec

相关推荐
AI前端老薛2 小时前
Taro 小程序如何优雅地分包
小程序·taro
long_songs2 小时前
Python编程第02课:Windows/Mac/Linux环境安装配置详解
windows·python·macos
蜡台2 小时前
浙政钉(浙里办小程序) H5 二次回退问题修复方案
前端·小程序·浙政钉·浙里办
别抢我的锅包肉2 小时前
【Python】PySpark 核心实操入门指南
python
cyhysr2 小时前
Python读取ppt文本转存txt
python·powerpoint
A懿轩A2 小时前
【NotebookLM 使用教程】 Slides 指令库:11套通用PPT风格Prompt(含中英文对照)
python·prompt·powerpoint·ppt·notebooklm
weixin_408099672 小时前
文字识别通用OCR接口调用与功能说明
图像处理·人工智能·后端·python·ocr·api·文字识别
Thomas.Sir2 小时前
第八章:RAG知识库开发之【Dify 实现数据库数据智能查询系统:从零构建企业级自然语言查询助手】
数据库·python·ai·dify
别抢我的锅包肉2 小时前
【PySpark】 如何在 Windows 成功使用 `saveAsTextFile()` 全流程教程 ✅
python