Python - 缩小文件大小的程序导致文件大小增加

3

我正在为大学做压缩技术的研究。其中一个实验是将某些威尔士语字母(双字母)替换为单个字符。

我认为用单个字符替换两个字符会减小文件大小(即使是微不足道的),或者最坏的情况下保持文件大小不变。我已经编写了一个Python脚本来完成此操作,但实际上它却增加了文件大小。我测试的原始文件大小约为74,400KB,输出程序大小约为74,700KB。

这是我的Python代码:

replacements = {
        'ch':'ƒ',
        'Ch':'†',
        'CH':'‡',
        'dd':'Œ',
        'Dd':'•',
        'DD':'œ',
        'ff':'¤',
        'Ff':'¦',
        'FF':'§',
        'ng':'±',
        'Ng':'µ',
        'NG':'¶',
        'll':'º',
        'Ll':'¿',
        'LL':'Æ',
        'ph':'Ç',
        'Ph':'Ð',
        'PH':'×',
        'rh':'Ø',
        'Rh':'Þ',
        'RH':'ß',
        'th':'æ',
        'Th':'ç',
        'TH':'ð',
        }
print("Input file location: ")
inLoc = input("> ")
print("Output file location: ")
outLoc = input("> ")

with open(inLoc, "r",encoding="Latin-1") as infile, open(outLoc, "w", encoding="utf-8") as outfile:
for line in infile:
    for src, target in replacements.items():
        line = line.replace(src, target)
    outfile.write(line)

当我在一个只有几行的非常小的文本文件上进行测试时,我查看了输出结果,与预期相符。
Input.txt:
Lle wyt ti heddiw?

Ddoe es i at gogledd Nghymru.

Output.txt:

¿e wyt ti heŒiw?

•oe es i at gogleŒ µhymru.

有人能解释一下正在发生什么吗?

2个回答

8
您正在改变文件的编码。Latin-1始终是每个字符1个字节,但UTF-8不是,因此一些特殊字符被编码为多个字节,导致大小增加。

因为一些替换内容在Latin-1范围之外(例如'ƒ'),所以无法将其作为Latin-1编写回去。因此,如果原始文本中有其他的Latin-1字符,如é,这些字符也会被扩展;它们在Latin-1中是一个字节,在UTF-8中是两个字节。原帖中将ASCII双字母组(在Latin-1或UTF-8中为两个字节)转换为使用UTF-8编码的单个低序数Unicode字符实际上并不会产生任何费用,因为UTF-8编码很可能也是两个字节(所有小于0x7ff的序数在UTF-8中都是两个字节)。但你的其他非ASCII Latin-1字符会膨胀。 - ShadowRanger
唯一减小大小的方法是让映射将有向图映射到拉丁-1范围内的某个地方,然后作为拉丁-1写回;这将在每个二合字替换中节省一个字节,但存在数据丢失的风险,因为您可能因其他原因而出现那些拉丁-1字符,并且无法区分由二合字转换创建的字符与原始文本中存在的字符。 - ShadowRanger
@ShadowRanger 那么,除了像你说的仍然使用Latin-1并可能丢失字符的方法之外,我没有办法将双字母替换为相同大小的单个字符吗? - hjalpmig
@hjalpmig:它不会丢失字符,只是失去区分性。你已经拥有的大多数映射都在latin-1空间内,但其他一些则在其外。如果你找到一个仅使用latin-1输出的映射,你可以通过写成latin-1来节省一小部分空间。同样,如果这可以真正成为威尔士语,没有非威尔士语字符,你可能可以使用latin8(一种带有凯尔特语字符的变体编码)以每个字符一个字节进行编码,但问题是,本地编码的东西将默认在系统语言环境中打开,而没有人使用cy_GB - ShadowRanger
@hjalpmig:实际上,最好的解决方案是使用可移植的UTF-8编码(或在Windows上使用UTF-16),并使用专用压缩方案(例如gzip)压缩文本,如果空间是一个大问题。在边缘处挠来挠去,削减一两个字节,并不能算作压缩。 - ShadowRanger
显示剩余2条评论

0

""UTF-8对于任何ASCII字符只使用一个字节,这些字符在UTF-8和ASCII编码中具有相同的编码值,并且对于其他字符最多使用四个字节。"" - https://en.wikipedia.org/wiki/Unicode


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接