这几天遇到个小需求,需要将一个大文件分割成不同大小的小文件。
找遍了各种软件和库包,都没有可以直接使用的,无奈只能自己手撸一个程序出来了。
大致思路为:
入参有3个,分别是:
- 输入的大文件位置
- 输出的小文件位置
- 输出的小文件名前缀
- 需要分割出来的每个文件大小,按占大文件的百分比计算
处理逻辑是
- 根据输入文件的大小和输入的百分比参数,计算出每个小文件的大小
- 根据1的结果按照读取大文件指定大小的内容,然后生成小文件并写入文件内容。
必须有对应的合并程序
有分割程序就必须有对应的合并程序,不然分割出来之后没法还原回去了。
根据以上思路,写出代码:
def split(whole_filename, target_path, target_prefix, target_size_list):
total_file_size = os.path.getsize(whole_filename)
last_part_size = total_file_size
print("split %s to %d parts to %s with prefix %s" % (whole_filename, len(target_size_list), target_path, target_prefix))
file_size_list = []
# calculate each file size
for index in range(len(target_size_list)):
if index != len(target_size_list) - 1:
part_size = int(total_file_size * target_size_list[index]) // 100
file_size_list.append(part_size)
last_part_size -= part_size
else:
file_size_list.append(last_part_size)
whole_file = open(whole_filename, "rb")
for index in range(len(target_size_list)):
part_file = open(os.path.join(target_path, "%s_%d" % (target_prefix, index)), 'wb+')
context = whole_file.read(file_size_list[index])
part_file.write(context)
part_file.close()
whole_file.close()
def combine(folder, filename_list, target_filename):
print("combine %d files into %s" % (len(filename_list), target_filename))
target_file = open(target_filename, "wb+")
for filename in filename_list:
part_file = open(os.path.join(folder, filename), "rb")
target_file.write(part_file.read())
return
虽然这次只要写出lib来给我的程序调用就行了,但是为了方便以后给别人使用,还是加上命令行调用的方法以及使用说明,这下子就可以当开源软件发布了。
usage = """usages:
SplitAndCombine split <full_file_name> <target_output_folder_path> <target_part_file_prefix> <percentage_size_list>
split a file into several part files with different size calculated by percentage
SplitAndCombine combine <folder_path> <target_filename> <part_file_name_1> <part_file_name_2> ...
example
python SplitAndCombine.py split "C:\workspace\BigFile.tar" "C:\workspace" "part" 15 25 34 26
python SplitAndCombine.py combine "C:\workspace" "C:\workspace\BigFile.tar" "part_0" "part_1" "part_2" "part_3"
"""
if __name__ == '__main__':
if len(sys.argv) < 5:
print(usage)
if sys.argv[1] == 'split':
target_size_list = []
for index in range(5, len(sys.argv)):
target_size_list.append(int(sys.argv[index]))
split(sys.argv[2], sys.argv[3], sys.argv[4], target_size_list)
elif sys.argv[1] == 'combine':
target_file_list = []
for index in range(4, len(sys.argv)):
target_file_list.append(sys.argv[index])
combine(sys.argv[2], target_file_list, sys.argv[3])
else:
print(usage)
虽然程序不大,但是实现了一个新的需求,还是挺不错的。