Python按指定偏移量分割大文件 f.seek()调用失败的解决方法
原代码存在的问题
- 参数传递顺序错误:调用
splitfile时颠倒了起止偏移,把结束偏移0x181b作为start参数传入,起始偏移0x18反而作为end参数传入,和分割区间的逻辑完全相反。 seek()方法参数使用完全错误:f.seek(offset, whence)的第二个参数whence仅支持三个固定值:0代表从文件开头计算偏移、1代表从当前指针位置计算偏移、2代表从文件末尾计算偏移。原代码用hex(start - end)[2]取字符转整数得到的是无意义值,根本不符合参数要求。- 读写逻辑完全混乱:
- 指针跳转后没有读取原文件对应区间的内容,反而调用write方法往原文件写数据,会直接损坏原文件;
- 打开输出分片文件时没有获取输出文件的操作句柄,所有写操作都作用在原文件上;
- 把
seek()的返回值(跳转后的指针位置整数)转成字节写入,写的根本不是原文件的内容; - 完全没有计算「结束偏移-起始偏移」的读取长度,不知道要读多少字节,根本不可能拿到正确的分片内容。
- 文件操作不规范:
- 原文件打开后没有使用上下文管理器管理,容易出现资源泄漏;
- 写
f.close时漏了括号,根本不会执行关闭文件的操作; - 输出文件用
w+文本模式打开,写入二进制内容会触发编码错误,导致分片损坏。
- 变量未初始化:全局变量
Num没有提前赋值,第一次调用函数时会直接抛出未定义错误。 - 存在冗余代码:定义的
str2hex函数全程没有被调用,属于无效代码。
正确实现方案
按偏移分割二进制文件的核心逻辑很简单:以二进制只读模式打开原文件,将文件指针跳转到区间起始位置,读取长度为「结束偏移-起始偏移」的字节内容,再将读取到的内容写入新的分片文件即可,全程不要修改原文件。
可直接运行的实现代码如下:
def split_file_by_offset(filename, split_ranges): """ 按字节偏移区间分割二进制文件 :param filename: 原文件路径 :param split_ranges: 分割区间列表,每个元素为(起始偏移, 结束偏移)格式的元组,偏移传整数值即可,支持直接写0x开头的十六进制值 """ # 二进制只读模式打开原文件,用上下文管理器自动处理关闭 with open(filename, "rb") as src_file: # 自动生成分片编号,从1开始计数 for part_idx, (start, end) in enumerate(split_ranges, 1): # 校验偏移合法性 if start < 0 or end <= start: print(f"分片{part_idx}的偏移区间不合法,已跳过") continue # 从文件开头跳转至起始偏移位置 src_file.seek(start, 0) # 计算需要读取的字节长度,读取对应内容 content = src_file.read(end - start) # 二进制写模式生成分片文件 part_name = f"{filename}_part{part_idx}" with open(part_name, "wb") as out_file: out_file.write(content) print(f"分片{part_idx}生成完成,对应偏移:0x{start:x} -- 0x{end:x},文件大小:{len(content)}字节,文件名:{part_name}") if __name__ == "__main__": # 在这里配置你需要的所有分割区间,直接写十六进制偏移即可 split_config = [ (0x18, 0x181b), (0x21e4, 0x4e4a) ] split_file_by_offset("test", split_config)
使用说明
- 直接修改
split_config里的区间元组即可添加更多分片,不需要修改函数逻辑; - 全程使用二进制模式操作,不会修改原文件,也不会出现编码导致的内容损坏问题;
- 不需要手动维护全局计数变量,也不需要额外写十六进制字符串转换函数,Python原生支持直接识别0x开头的十六进制整数值;
- 所有文件操作都通过上下文管理器自动处理关闭,不会出现文件句柄泄漏的问题。
内容的提问来源于stack exchange,提问作者wTrace3zh
相关产品推荐
相关产品推荐

