Мне кажется, что поведение Firefox корректно. Каково значение 6-го значения в IE (извините, у меня нет удобным протестировать). С тех пор нет никакого фактического значения, если, я предполагаю, что это заполняет его чем-то как 'пустой указатель', который, конечно, кажется, не то, что Вы намеревались иметь, происходят, когда Вы создали массив.
В конце дня, хотя, это действительно не имеет значения, который "корректен", так как действительность - то, что или Вы нацелены только на один браузер, в этом случае можно проигнорировать то, что другие делают, или Вы нацелены на несколько браузеров, в этом случае, Ваш код должен работать над всеми ними. В этом случае очевидное решение никогда не состоит в том, чтобы включать повисшую запятую в инициализатор массива.
, Если у Вас есть проблемы при предотвращении его (например, по некоторым причинам Вы разработали (плохо, по моему скромному мнению) привычка к включению его) и другие проблемы как это, тогда что-то как JSLint мог бы помочь.
def unicode_truncate(s, length, encoding='utf-8'):
encoded = s.encode(encoding)[:length]
return encoded.decode(encoding, 'ignore')
Вот пример строки Юникода, где каждый символ представлен двумя байтами в UTF-8:
>>> unicode_truncate(u'абвгд', 5)
u'\u0430\u0431'
Одно из свойств UTF-8 заключается в том, что его легко повторно синхронизировать, то есть легко находить границы символов Юникода в закодированном потоке байтов. Все, что вам нужно сделать, это разрезать закодированную строку на максимальную длину, затем пройти в обратном направлении от конца, удалив все байты, которые> 127 - они являются частью или началом многобайтового символа.
Как написано сейчас, это слишком просто - сотрет до последнего символа ASCII, возможно, всю строку. Что нам нужно сделать, так это проверить отсутствие усеченных двухбайтовых (начинаются с 110yyyxx
) трехбайтовых ( 1110yyyy
) или четырехбайтовых ( 11110zzz
)
Реализация Python 2.6 в виде чистого кода. Оптимизация не должна быть проблемой - независимо от того, длины, мы проверяем только последние 1–4 байта.
# coding: UTF-8
def decodeok(bytestr):
try:
bytestr.decode("UTF-8")
except UnicodeDecodeError:
return False
return True
def is_first_byte(byte):
"""return if the UTF-8 @byte is the first byte of an encoded character"""
o = ord(byte)
return ((0b10111111 & o) != o)
def truncate_utf8(bytestr, maxlen):
u"""
>>> us = u"ウィキペディアにようこそ"
>>> s = us.encode("UTF-8")
>>> trunc20 = truncate_utf8(s, 20)
>>> print trunc20.decode("UTF-8")
ウィキペディ
>>> len(trunc20)
18
>>> trunc21 = truncate_utf8(s, 21)
>>> print trunc21.decode("UTF-8")
ウィキペディア
>>> len(trunc21)
21
"""
L = maxlen
for x in xrange(1, 5):
if is_first_byte(bytestr[L-x]) and not decodeok(bytestr[L-x:L]):
return bytestr[:L-x]
return bytestr[:L]
if __name__ == '__main__':
# unicode doctest hack
import sys
reload(sys)
sys.setdefaultencoding("UTF-8")
import doctest
doctest.testmod()
Для форматирования JSON (escape-код unicode, например \ uabcd
), я использую следующий алгоритм для достижения этой цели:
Итак (в Python 2.5), с some_string
и требованием сократить примерно до 100 байтов:
# Given some_string is a long string with arbitrary Unicode data.
encoded_string = some_string.encode('unicode_escape')
partial_string = re.sub(r'([^\\])\\(u|$)[0-9a-f]{0,3}$', r'\1', encoded_string[:103])
final_string = partial_string.decode('unicode_escape')
Теперь final_string
снова в Unicode, но гарантированно поместится в пакете JSON позже. Я усек до 103, потому что сообщение в формате Unicode будет закодировано в 102 байта.
Заявление об ограничении ответственности: тестировалось только на базовой многоязычной плоскости. Да, я знаю.
Это подойдет для UTF8, если вам нравится делать это в регулярном выражении.
import re
partial="\xc2\x80\xc2\x80\xc2"
re.sub("([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$","",partial)
"\xc2\x80\xc2\x80"
Его охват от U + 0080 (2 байта) до U + 10FFFF (4 байта) строки utf8
Это действительно просто, как и алгоритм UTF8
От U + 0080 до U + 07FF Потребуется 2 байта 110yyyxx 10xxxxxx
Это означает, что если вы видите в конце только один байт, например 110yyyxx (от 0b11000000 до 0b11011111)
Это [\ xc0- \ xdf]
, он будет частичным.
От U + 0800 до U + FFFF необходимо 3 байта 1110yyyy 10yyyyxx 10xxxxxx
Если в конце вы видите только 1 или 2 байта, это будет неполный.
Он будет соответствовать этому шаблону [\ xe0- \ xef] [\ x80- \ xbf] {0,1}
Из U + 10000 – U + 10FFFF необходимо 4 байта 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
Если в конце вы увидите от 1 до 3 байтов, это будет частичный
Он будет соответствовать этому шаблону [\ xf6- \ xf7] [\ x80- \ xbf] {0,2}
Обновление:
Если вам нужна только базовая многоязычная плоскость, вы можете отбросить последний шаблон. Так и будет.
re.sub("([\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$","",partial)
Дайте мне знать, если есть какие-то проблемы с этим регулярным выражением.