1

我正在尝试找出一种方法来编码/解码二进制数据,使换行符不是编码字符串的一部分。

这似乎是一个递归问题,但我似乎无法找到解决方案。

例如一个天真的实现:

>>> original = 'binary\ndata'

>>> encoded = original.replace('\n', '=n')
'binary=ndata'
>>> decoded = original.replace('=n', '\n')
'binary\ndata'

如果=n原始字符串中已经存在 a 会发生什么?

>>> original = 'binary\ndata=n'

>>> encoded = original.replace('\n', '=n')
'binary=ndata=n'
>>> decoded = original.replace('=n', '\n')
'binary\ndata\n'  # wrong

尝试逃避现有=n的,但如果已经有一个逃逸的会发生什么=n

>>> original = '++nbinary\ndata=n'

>>> encoded = original.replace('=n', '++n').replace('\n', '=n')
'++nbinary=ndata++n'

我怎样才能解决这个递归问题?

4

7 回答 7

1

解决方案

original = 'binary\ndata \\n'
# encoded = original.encode('string_escape')                   # escape many chr
encoded = original.replace('\\', '\\\\').replace('\n', '\\n')  # escape \n and \\
decoded = encoded.decode('string_escape')

已验证

>>> print encoded
binary\ndata \\n
>>> print decoded
binary
data \n

解决方案来自How do I un-escape a backslash-escaped string in python?

编辑:我也用你的临时经济编码写了它。原始的“string_escape”编解码器转义了反斜杠、撇号以及 chr(32) 以下和 chr(126) 以上的所有内容。两者的解码都是一样的。

于 2012-11-23T18:44:40.883 回答
1

对可能包含“转义”字符的字符串进行编码的方法也是对转义字符进行转义。在 python 中,转义字符是一个反斜杠,但你可以使用任何你想要的。每次出现换行符或转义符时,您的成本是一个字符。

为避免让您感到困惑,我将使用正斜杠:

# original
>>> print "slashes / and /newline/\nhere"
slashes / and /newline/
here
# encoding
>>> print "slashes / and /newline/\nhere".replace("/", "//").replace("\n", "/n")
slashes // and //newline///nhere

这种编码是明确的,因为所有真正的斜线都是双倍的;但它必须在一次通过中解码,因此您不能只使用两个连续调用replace()

# decoding
>>> def decode(c):
    # Expand this into a real mapping if you have more substitutions
    return '\n' if c == '/n' else c[0]

>>> print "".join( decode(c) for c in re.findall(r"(/.|.)", 
                                         "slashes // and //newline///nhere"))
slashes / and /newline/
here

请注意,输入中有一个实际值/n(以及换行符之前的另一个斜杠):无论如何它都可以正常工作。

于 2012-11-23T00:32:09.173 回答
0

如果您将一个包含 n 个符号(例如 ASCII)的字母表编码为一组较小的 m 个符号(例如,除了换行符之外的 ASCII),您必须允许编码的字符串比原始字符串长。

这样做的典型方法是将一个字符定义为“转义”字符;“转义”后面的字符表示编码字符。这种技术自 1940 年代以来一直用于电传打字机。这就是您在键盘上看到的“Esc”键的来源。

Python(和其他语言)已经在带有反斜杠字符的字符串中提供了这一点。换行符被编码为 '\n'(或 '\r\n')。反斜杠会自行转义,因此文字字符串 '\r\n' 将被编码为 '\\r\\n'。

请注意,仅包含转义字符的字符串的编码长度将是原始字符串的两倍。如果这是不可接受的,您将不得不使用使用更大字母的编码来避免转义字符(可能比原始字符串长)或压缩它(也可能比原始字符串长)。

于 2012-11-23T02:02:04.193 回答
0

怎么样:

In [8]: import urllib

In [9]: original = 'binary\ndata'

In [10]: encoded = urllib.quote(original)

In [11]: encoded
Out[11]: 'binary%0Adata'

In [12]: urllib.unquote(encoded)
Out[12]: 'binary\ndata'
于 2012-11-23T21:11:54.820 回答
0

如果您系统地对整个字符串进行编码,您最终不会转义它吗?说你所做的每个角色 chr(ord(char) + 1) 或类似的微不足道的事情?

于 2012-11-22T23:34:04.543 回答
0

我对二进制数据没有很多经验,所以这可能完全关闭/效率低下/两者兼而有之,但这会解决您的问题吗?

In [40]: original = 'binary\ndata\nmorestuff'

In [41]: nlines = [index for index, i in enumerate(original) if i == '\n']

In [42]: encoded = original.replace('\n', '')

In [43]: encoded
Out[43]: 'binarydatamorestuff'

In [44]: decoded = list(encoded)

In [45]: map(lambda x: decoded.insert(x, '\n'), nlines)
Out[45]: [None, None]

In [46]: decoded = ''.join(decoded)

In [47]: decoded
Out[47]: 'binary\ndata\nmorestuff'

同样,我确信有更好/更准确的方法 - 这只是从新手的角度来看。

于 2012-11-22T23:38:56.053 回答
0

转义编码专门设计用于从二进制数据中删除某些字符。在您仅删除\n角色的情况下,开销将小于 0.4%。

于 2019-06-04T12:15:38.243 回答