本帖最后由 s1986q 于 2024-4-1 12:59 编辑
原精华帖:https://www.52pojie.cn/thread-1908192-1-1.html
c# 每次使用都很费事,转换python代码,就可以。python包不大。
使用的内置函数。
代码bug修复
[Python] 纯文本查看 复制代码 import os
import struct
import sys
# 定义一个函数,从文件数据中获取密钥
def get_key(file_data):
"""
从文件数据中提取密钥
参数:
file_data (字节串):包含数据的文件内容
返回:
key (字节串):提取的密钥
"""
key_a = file_data[1024:1024 + 32]
key_b = file_data[1056:1056 + 32]
return bytes((key_b[i] - key_a[i]) & 0xff for i in range(32))
# 定义一个函数,从文件数据中获取所有目录信息
def get_all_dirs(file_data):
"""
从文件数据中提取所有目录的信息
参数:
file_data (字节串):包含数据的文件内容
返回:
dirs (列表):包含目录名称、目录数据长度和目录数据偏移的元组列表
"""
dirs = []
dir_num = struct.unpack('<i', file_data[252:256])[0]
for i in range(dir_num):
offset = 1280 + i * 128
item = file_data[offset:offset + 128]
item = bytes((item[j] - key[j % 32]) & 0xff for j in range(128))
dir_name = item[:120].decode('gbk').rstrip('\x00')
dir_data_length = struct.unpack('<i', item[120:124])[0] << 7
dir_data_offset = struct.unpack('<i', item[124:128])[0]
dirs.append((dir_name, dir_data_length, dir_data_offset))
return dirs
# 定义一个函数,从文件数据中获取所有文件信息
def get_all_files(file_data, dir_data_offset, dir_data_length):
"""
从文件数据中提取特定目录下的所有文件信息
参数:
file_data (字节串):包含数据的文件内容
dir_data_offset (整数):目录数据的偏移量
dir_data_length (整数):目录数据的长度
返回:
files (列表):包含文件名称、歌曲数据偏移和歌曲数据长度的元组列表
"""
files = []
for i in range(dir_data_length // 128):
offset = dir_data_offset + i * 128
item = file_data[offset:offset + 128]
item = bytes((item[j] - key[j % 32]) & 0xff for j in range(128))
file_name = item[:64].decode('gbk').rstrip('\x00')
song_data_offset = struct.unpack('<i', item[64:68])[0]
song_data_length = struct.unpack('<i', item[68:72])[0]
files.append((file_name, song_data_offset, song_data_length))
return files
# 定义一个函数,从文件数据中获取歌曲数据
def get_song_data(file_data, song_data_offset, song_data_length):
"""
从文件数据中提取歌曲数据
参数:
file_data (字节串):包含数据的文件内容
song_data_offset (整数):歌曲数据的偏移量
song_data_length (整数):歌曲数据的长度
返回:
song_data (字节串):提取的歌曲数据
"""
return file_data[song_data_offset:song_data_offset + song_data_length]
if __name__ == "__main__":
# 检查命令行参数的数量是否正确
if len(sys.argv)!= 3:
print("调用说明: PianoCatSongDataExtractor.py <input> <output>")
sys.exit(1)
# 输入文件路径
input_file = sys.argv[1]
# 输出目录路径
output_dir = sys.argv[2]
# 以二进制模式打开输入文件并读取数据
with open(input_file, 'rb') as f:
data = f.read()
# 获取密钥
key = get_key(data)
# 获取目录信息
dirs = get_all_dirs(data)
# 遍历目录信息,创建目录并提取文件信息
for dir_info in dirs:
os.makedirs(os.path.join(output_dir, dir_info[0]), exist_ok=True)
files = get_all_files(data, dir_info[2], dir_info[1])
for file_info in files:
print(f"{dir_info[0]} -> {file_info[0]}")
# 提取歌曲数据并写入文件
song_data = get_song_data(data, file_info[1], file_info[2])
with open(os.path.join(output_dir, dir_info[0], file_info[0] + ".mid"), 'wb') as f:
f.write(song_data) |