某个编码错误文件的恢复过程
之前在另一个账号上的日记。可惜和她分手时,一怒注销了账号。把文章也发在这里一份:
某人不小心打开了若干年前的文本文件,然后悲剧的发现除英文字符和标点外,其余内容皆为乱码。比如介个样子À´»ØµØ£¬·´¸´µØ,或者介样Ïòºó¼æÈݵģ¬Óë¾É°æ±¾¼æÈݵÄ。
文件保存了中英文混合内容,当前编码为UTF-8。目测是由于某种原因,把字节流本身(而不是它表示的字符串)保存成了UTF8。上面这句话十分拗口,让我用一种形式化语言解释一下,假设:
* E是encoding函数;
* D是decoding函数;
* 读一个文本文件就是,把一个字节流stream转换成字符串s(叫decoding)可以用s =D(stream)来表示;
* 而在文本编辑器里敲入字符串s,然后点击保存到文件,则是把s转换成字节流stream(叫encoding),可以用stream =E(s)表示。
通常来说文本处理会经历:编辑stream= E1(s),然后使用s= D1(stream)。请注意encoding和decoding务必使用同种编码1。而我们这里遇到的问题,实际过程类似stream= E1(s),由于某种奇葩原因stream_= E2(stream),最后stream as string = D2(stream_)。也就是说某人看到的是stream,而不是s,自然就乱码了。
有了如上猜测,解决方案自然简单:
第一步,当前文件中存的实际上是stream_,所以先把它解码成字符串stream;
第二步,stream被理解为字符串,但实际上是个字节流,因此我们必须把它还原为字节流。这一步可以通过把字符串encoding成ISO 8859-1编码(注意,不是ASCII,是ISO 8859-1,这样才能把每个byte还原出来;用ASCII只能还原每个byte的低7位)。本质上,这样的做法是把字符串中每一个字符当成一个byte还原。
第三步,用正确的编码把字节流decoding成字符串。
还是用同样形式化的语言描述上述过程
第一步,stream as string = D2(stream_), D2 is UTF-8
第二步,stream= E3(stream as string), E3 is ISO 8859-1
第三部,s= E1(stream), E1 is GB2312
经过测试,原始字节流是GB2312编码。最终得到了正确的文本内容。
某人不小心打开了若干年前的文本文件,然后悲剧的发现除英文字符和标点外,其余内容皆为乱码。比如介个样子À´»ØµØ£¬·´¸´µØ,或者介样Ïòºó¼æÈݵģ¬Óë¾É°æ±¾¼æÈݵÄ。
文件保存了中英文混合内容,当前编码为UTF-8。目测是由于某种原因,把字节流本身(而不是它表示的字符串)保存成了UTF8。上面这句话十分拗口,让我用一种形式化语言解释一下,假设:
* E是encoding函数;
* D是decoding函数;
* 读一个文本文件就是,把一个字节流stream转换成字符串s(叫decoding)可以用s =D(stream)来表示;
* 而在文本编辑器里敲入字符串s,然后点击保存到文件,则是把s转换成字节流stream(叫encoding),可以用stream =E(s)表示。
通常来说文本处理会经历:编辑stream= E1(s),然后使用s= D1(stream)。请注意encoding和decoding务必使用同种编码1。而我们这里遇到的问题,实际过程类似stream= E1(s),由于某种奇葩原因stream_= E2(stream),最后stream as string = D2(stream_)。也就是说某人看到的是stream,而不是s,自然就乱码了。
有了如上猜测,解决方案自然简单:
第一步,当前文件中存的实际上是stream_,所以先把它解码成字符串stream;
第二步,stream被理解为字符串,但实际上是个字节流,因此我们必须把它还原为字节流。这一步可以通过把字符串encoding成ISO 8859-1编码(注意,不是ASCII,是ISO 8859-1,这样才能把每个byte还原出来;用ASCII只能还原每个byte的低7位)。本质上,这样的做法是把字符串中每一个字符当成一个byte还原。
第三步,用正确的编码把字节流decoding成字符串。
还是用同样形式化的语言描述上述过程
第一步,stream as string = D2(stream_), D2 is UTF-8
第二步,stream= E3(stream as string), E3 is ISO 8859-1
第三部,s= E1(stream), E1 is GB2312
经过测试,原始字节流是GB2312编码。最终得到了正确的文本内容。
还没人转发这篇日记