Python zlib вывод, как восстановить из mysql utf-8 таблицу?

Если бы это был я то - я сделал бы что-то вроде этого:

<style type="text/css" media="screen">
 table { border: 1px solid black;float:left;width:148px;}
 #table_container{width:300px;margin:0 auto;}
</style>

С таблицей как:

<div id="table_container">
  <table>
    <tr>
      <th>a</th>
      <th>b</th>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>9</td>
    </tr>
    <tr>
      <td>16</td>
      <td>25</td>
    </tr>
  </table>
  <table>
    <tr>
      <th>a</th>
      <th>b</th>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>9</td>
    </tr>
    <tr>
      <td>16</td>
      <td>25</td>
    </tr>
  </table>
</div>
7
задан Heinrich Schmetterling 24 October 2009 в 20:03
поделиться

3 ответа

Unicode разработан для совместимости с latin-1, поэтому попробуйте:

>>> import zlib
>>> u = zlib.compress("test").decode('latin1')
>>> u
u'x\x9c+I-.\x01\x00\x04]\x01\xc1'

А затем

>>> zlib.decompress(u.encode('latin1'))
'test'

EDIT: Исправлена ​​опечатка, latin-1 не предназначен для совместимости с юникодом все наоборот.

7
ответ дан 7 December 2019 в 01:22
поделиться

У вас есть объект Unicode , который действительно кодирует байты. Это прискорбно, поскольку строки Unicode должны на самом деле кодировать только текст, верно?

В любом случае, мы хотим создать байтовую строку ... это str в Python 2.x. По напечатанной вами строке u'x \ x9cK \ x04 \ x00 \ x00b \ x00b ' мы видим, что значения байтов закодированы как кодовые точки Unicode. Мы можем получить числовое значение кодовой точки с помощью функции ord (..) . Затем мы можем получить представление этого числа в виде строки байтов с помощью функции chr (..) . Давайте попробуем следующее:

>>> ord(u"A")
65
>>> chr(_)
'A'

Итак, мы можем сами декодировать строку:

>>> udata = u'x\x9cK\x04\x00\x00b\x00b'
>>> bdata = "".join(chr(ord(uc)) for uc in udata)
>>> bdata
'x\x9cK\x04\x00\x00b\x00b'

(Подождите, что делает вышеприведенный код? Материал соединения? Сначала мы создаем список кодовых точек в строке:

>>> [ord(uc) for uc in udata]
[120, 156, 75, 4, 0, 0, 98, 0, 98]

Затем мы интерпретируем числа как байты, преобразуя их по отдельности:

>>> [chr(ord(uc)) for uc in udata]
['x', '\x9c', 'K', '\x04', '\x00', '\x00', 'b', '\x00', 'b']

Наконец, мы объединяем их с помощью "" в качестве разделителя, используя "". Join (list-of-strings)

Конец ожидания ..)

Однако cls ловко отмечает, что кодировка Latin-1 имеет свойство, заключающееся в том, что значение байта символа в кодировке Latin-1 равно кодовой точке символа в Unicode. При условии, конечно, что символ находится в диапазоне от 0 до 255, где определена Latin-1. Это означает, что мы можем выполнить преобразование байтов напрямую с помощью Latin-1:

>>> udata = u'x\x9cK\x04\x00\x00b\x00b'
>>> udata.encode("latin-1")
'x\x9cK\x04\x00\x00b\x00b'

Что, как видите, дает тот же результат.

cls ловко отмечает, что кодировка Latin-1 имеет свойство, заключающееся в том, что значение байта символа в кодировке Latin-1 равно кодовой точке символа в Unicode. При условии, конечно, что символ находится в диапазоне от 0 до 255, где определена Latin-1. Это означает, что мы можем выполнить преобразование байтов напрямую с помощью Latin-1:

>>> udata = u'x\x9cK\x04\x00\x00b\x00b'
>>> udata.encode("latin-1")
'x\x9cK\x04\x00\x00b\x00b'

Что, как видите, дает тот же результат.

cls ловко отмечает, что кодировка Latin-1 имеет свойство, заключающееся в том, что значение байта символа в кодировке Latin-1 равно кодовой точке символа в Unicode. При условии, конечно, что символ находится в диапазоне от 0 до 255, где определена Latin-1. Это означает, что мы можем выполнить преобразование байтов напрямую с помощью Latin-1:

>>> udata = u'x\x9cK\x04\x00\x00b\x00b'
>>> udata.encode("latin-1")
'x\x9cK\x04\x00\x00b\x00b'

Что, как видите, дает тот же результат.

2
ответ дан 7 December 2019 в 01:22
поделиться
valueInserted = zlib.compress('a') = 'x\x9cK\x04\x00\x00b\x00b'

Обратите внимание, что это объект str . Вы говорите, что «вставили его в столбец mysql типа blob, используя кодировку utf-8». Поскольку сжатая строка является двоичной, а не текстовой, "blob" является подходящим типом столбца, но ЛЮБАЯ кодировка или другое преобразование - очень плохая идея. Вы должны иметь возможность восстанавливать данные из базы данных ТОЧНО вплоть до последнего бита, который вы вставили, иначе распаковка завершится неудачно, либо из-за ошибки, либо (что менее вероятно, но хуже) тихо производит мусор.

Вы говорите, что возвращаетесь после любого процесса, который вы проходите при вставке и повторном извлечении:

valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'

Обратите внимание, что есть только одно крошечное визуальное различие: u 'Something' вместо 'something'. Это делает его объектом unicode . Основываясь на ваших собственных доказательствах, "возвращается как UTF-8" неверно. Объект unicode и объект str, закодированный в utf8, - это не одно и то же.

Предположение 1: вставить как необработанную строку, извлечь с помощью latin1 decode.

Предположение 2: вставить как сжатый.decode ('latin1'). Encode ('utf8'), извлекать с помощью декодирования utf8.

Вам действительно нужно понимать процесс вставки и извлечения, в том числе то, что кодирование и декодирование происходит по умолчанию.

Тогда вам действительно нужно исправить ваш код. Однако тем временем вы, вероятно, можете накапливать то, что у вас есть.

Обратите внимание на это:

>>> valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'
>>> all(ord(char) <= 255 for char in valueFromSqlColumn)
True

Проведите несколько проб с более сложным вводом, чем 'a'. Если, как я предполагаю, вы видите, что все символы Юникода имеют порядковый номер в диапазоне (256), тогда у вас есть простой кладж:

>>> compressed = valueFromSqlColumn.encode('latin1')
>>> compressed
'x\x9cK\x04\x00\x00b\x00b'
>>> zlib.decompress(compressed)
'a'

Почему это работает, так это то, что кодирование / декодирование Latin1 не работает » t изменить порядковый номер. Вы можете восстановить исходное сжатое значение следующим образом:

>>> compressed2 = ''.join(chr(ord(uc)) for uc in valueFromSqlColumn)
>>> compressed2
'x\x9cK\x04\x00\x00b\x00b'
>>> compressed2 == compressed
True

, если вы считаете, что использование .encode ('latin1') слишком похоже на voodoo.

Если вышеуказанное не работает (т.е. некоторые порядковые номера не входят в диапазон (256) ), то вам нужно будет создать небольшой исполняемый скрипт, который показывает точно и воспроизводимо, как вы сжимаете, вставляете в базу данных и извлекаете из базы данных ... разбросайте много переменной print " ", repr (variable) вокруг вашего кода, чтобы вы могли видеть, что происходит.

1
ответ дан 7 December 2019 в 01:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: