什么是文本编码最有效的二进制文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是文本编码最有效的二进制文件?相关的知识,希望对你有一定的参考价值。

到目前为止,我能找到的最接近的竞争者是yEnc(2%)和ASCII85(25%的开销)。 yEnc似乎存在一些问题,主要是因为它使用的是8位字符集。这引出了另一个想法:是否存在基于UTF-8字符集的二进制文本编码?

答案

这实际上取决于二进制数据的性质以及“文本”对输出的约束。

首先,如果您的二进制数据未压缩,请在编码前尝试压缩。然后我们可以假设1/0或单个字节的分布或多或少是随机的。

现在:你为什么需要文字?通常,这是因为通信通道不会平等地通过所有字符。例如您可能需要纯ASCII文本,其可打印字符范围为0x20-0x7E。你有95个字符可供玩耍。理论上,每个字符可以编码每个字符的log2(95)〜= 6.57位。定义一个非常接近的变换很容易。

但是:如果你需要一个分隔符,该怎么办?现在你只有94个字符等。所以编码的选择实际上取决于你的要求。

举一个非常愚蠢的例子:如果你的频道通过所有256个字符没有问题,并且你不需要任何分隔符,那么你可以编写一个平凡的变换,实现100%的效率。 :-)如何做到这一点留给读者练习。

UTF-8不是任意编码二进制数据的良好传输。它能够传输值0x01-0x7F,只有14%的开销。我不确定0x00是否合法;可能不是。但是,高于0x80的任何内容都会扩展为UTF-8中的多个字节。我将UTF-8视为传递0x01-0x7F或126个唯一字符的约束通道。如果您不需要分隔符,则每个字符可以传输6.98位。

该问题的一般解决方案:假设N个字符的字母表,其二进制编码为0到N-1。 (如果编码不是假定的,那么使用查找表在我们的中间0..N-1表示与您实际发送和接收的表示之间进行转换。)

假设字母表中有95个字符。现在:其中一些符号代表6位,有些代表7位。如果我们有一个6位符号和B 7位符号,那么:

A + B = 95(符号总数)2A + B = 128(可以进行7位前缀的总数。您可以使用6位符号开始2个前缀,或者使用7位符号开始。 )

求解系统得到:A = 33,B = 62。您现在构建一个符号表:

Raw     Encoded
000000  0000000
000001  0000001
...
100000  0100000
1000010 0100001
1000011 0100010
...
1111110 1011101
1111111 1011110

要进行编码,首先要关闭6位输入。如果这六位大于或等于100001,则移位另一位。然后查找相应的7位输出代码,转换为适合输出空间并发送。每次迭代,您将移动6或7位输入。

要解码,接受一个字节并转换为原始输出代码。如果原始代码小于0100001,则将相应的6位移到输出上。否则将相应的7位移到输出上。每次迭代,您将生成6-7位输出。

对于均匀分布的数据,我认为这是最佳的。如果您知道源中的零比零多,则可能需要将7位代码映射到空间的开头,以便更有可能使用7位代码。

另一答案

简短的回答是:不,仍然没有。

我遇到了将尽可能多的信息编码到JSON字符串中的问题,这意味着没有控制字符,反斜杠和引号的UTF-8。

我出去研究了你可以挤进有效的UTF-8字节多少位。我不同意答案,说明UTF-8带来了太多的开销。这不是真的。

如果只考虑一个字节的序列,它就像标准ASCII一样强大。含义每字节7位。但如果你删掉所有特殊字符,你会留下类似Ascii85的东西。

但是在更高的平面中控制字符更少。因此,如果您使用6字节块,您将能够编码每个块5个字节。在输出中,您将获得任意长度的UTF-8字符的任意组合(1到6个字节)。

这将给你一个比Ascii85更好的结果:5/6而不是4 / 5,83%效率而不是80%。从理论上讲,块长度越大,效果越好:19字节块大约为84%。

在我看来,编码过程变得太复杂,而它提供的利润很少。所以Ascii85或它的一些修改版本(我现在正在看Z85)会更好。

另一答案

我去年搜索了最有效的二进制文本编码。我意识到紧凑性不是唯一的标准。最重要的是您可以使用编码字符串。例如,yEnc有2%的开销,但它是8位编码,因此它的使用非常有限。

我的选择是Z85。它可以接受25%的开销,编码字符串几乎可以在任何地方使用:XML,JSON,源代码等。有关详细信息,请参阅Z85 specification

最后,我用C / C ++编写了Z85 library并在生产中使用它。

另一答案

根据Wikipedia

basE91为压缩的8位二进制输入生成最短的纯ASCII输出。

另一答案

听起来你已经有了答案,马克。 UTF-8作为二进制编码没有用,因为任何大于一个字节的UTF-8字符即使存储文本(每字节2位或更多位)也有超过25%的开销。 Base64编码已经比那更好了。

另一答案

Wikipedia上列出的那些旁边有Bommanews:

B-News(或bommanews)的开发是为了解除UUEncode和Base64编码固有的开销:它使用一种新的编码方法来填充文本消息中的二进制数据。这种方法占用了更多的CPU资源,但它设法将UUEncode的损失从大约40%降低到3.5%(这些数字之间的小数点不是显示器上的污垢),同时仍然避免在消息中使用ANSI控制代码身体。

它与yEnc:source相当

yEnc比B-News的CPU密集程度低,并且达到了相同的低开销水平,但它并没有避免使用所有控制代码,只是遗漏了那些(实验上)被观察到对某些控制代码产生不良影响的代码。服务器,这意味着它比B-News的RFC更少。

另一答案

目前base91是最好的编码,如果您仅限于ASCII字符并且不想使用不可打印的字符。它还具有快速编码/解码速度的优点,因为可以使用查找表,不像base85,它必须使用慢速分割来解码

高于base122将有助于提高效率,但它不是8位清洁。但是因为它基于UTF-8编码,所以它可以用于许多目的。而8位清洁现在毫无意义

Base-122 Encoding

Base-122编码一次获取七位输入数据的块。如果块映射到合法字符,则使用单字节UTF-8字符编码:0xxxxxxx。如果块将映射到非法字符,我们改为使用双字节UTF-8字符:110xxxxx 10xxxxxx。由于只有六个非法代码点,我们只能用三位来区分它们。将这些位称为sss给出了格式:110sssxx 10xxxxxx。其余的8位似乎可以编码更多的输入数据。不幸的是,代表小于0x80的代码点的双字节UTF-8字符无效。浏览器会将无效的UTF-8字符解析为错误字符。执行大于0x80的代码点的一种简单方法是使用格式110sss1x 10xxxxxx,相当于与0x80的按位OR(这可能会得到改进,参见§4)。图3总结了完整的base-122编码。

Base-122 encoding scheme

http://blog.kevinalbs.com/base122

另一答案

我最近需要将二进制编码为ascii,这就是我提出的。我不知道这是否是最有效的(可能不是),但它简单快速。基本上,我将一个字节编码为十六进制,但我使用(a-p)而不是使用基组(0-9,A-F)。因为该集是连续的,所以不需要任何表查找。

//buff is a unsigned character array containing the binary data
//N is the number of bytes to be encoded 
string simple_encode(unsigned char *buff, int N)
{
    string sEncode = "";
    for(int i = 0; i<N; i++)
    {
        sEncode += (97 + (buff[i] >> 4));
        sEncode += (97 + (buff[i] & 0x0F));
    }
    return sEncode;
}

//sbuff is a string containing the encoded ascii data
//szDecoded is an unsigned char array that has been allocated to 1/2 
//the length of sbuff
//N is an integer pointer and returns the number of converted bytes
void simple_decode(string sbuff, unsigned char *szDecode, int *N)
{
    *N = sbuff.length()/2;
    for(int i=0; i < *N; i++)
    {
        szDecode[i] = ((sbuff.at(2*i)-97) << 4) + (sbuff.at(2*i+1)-97);
    }
}

以上是关于什么是文本编码最有效的二进制文件?的主要内容,如果未能解决你的问题,请参考以下文章

对可能是二进制但通常是文本的数据进行有效的 JSON 编码

02 字符编码

如何测试文本片段是不是是 Quoted-printable 编码的

针对base64编码和URIEncode的一点研究

二进制文件与文本文件的差异

对文本文件进行排序