将unicode字符解码并编码为'\ u ####'

时间:2013-09-30 04:25:12

标签: python

我正在尝试编写java.util.Properties的python实现,该实现要求将unicode字符以\u####

的格式写入输出文件

(如果您感到好奇,文档就在这里,但问题并不重要:http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html

我基本上需要通过以下测试用例的东西

def my_encode(s):
    # Magic

def my_decode(s):
    # Magic

# Easy ones that are solved by .encode/.decode 'unicode_escape'
assert my_decode('\u2603') == u'☃'
assert my_encode(u'☃') == '\\u2603'

# This one also works with .decode('unicode_escape')
assert my_decode('\\u0081') == u'\x81'
# But this one does not quite produce what I want
assert my_encode(u'\u0081') == '\\u0081' # Instead produces '\\x81'

请注意,我已经尝试了unicode_escape并且它已接近但不能完全满足我的需求

我注意到simplejson正确执行了此转换:

>> simplejson.dumps(u'\u0081')
'"\\u0081"'

但我宁愿避免:

  1. 重新发明轮子
  2. 对simplejson的输出做一些粗略的子串接

1 个答案:

答案 0 :(得分:3)

根据您链接到的文档:

  

属性键或值中小于\u0020且字符大于\u007E的字符将写为\uxxxx,以表示相应的十六进制值xxxx

因此,它很容易转换为Python:

def my_encode(s):
    return ''.join(
        c if 0x20 <= ord(c) <= 0x7E else r'\u%04x' % ord(c)
        for c in s
    )

对于字符串中的每个字符,如果代码点在0x20和0x7E之间,则该字符保持不变;否则,使用\u后跟编码为4位十六进制数的代码点。表达式c for c in s生成器表达式,因此我们使用空字符串上的str.join将其转换回字符串。

对于解码,您可以像上面提到的那样使用unicode_escape编解码器:

def my_decode(s):
    return s.decode('unicode_escape')