2013-09-30 3 views
0

Я пытаюсь написать реализацию питон java.util.Properties, который имеет требование, согласно которому символы Юникода записываются в выходной файл в формате \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. Выполнение грубой подстройки выхода простого пользователя

ответ

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, за которым следует кодовая точка, закодированная в виде четырехзначного шестнадцатеричного числа. Выражение c for c in s является генератором , поэтому мы преобразуем его обратно в строку, используя str.join в пустой строке.

Для декодирования, вы можете просто использовать unicode_escape кодек, как вы упомянули:

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

это работает только, если входной является строка Unicode. Не пытайтесь пройти UTF-8! Результатом будет строка ASCII, чтобы она работала в любом случае. –

Смежные вопросы