Разделить строку по длине байта в Python

1

У меня есть ситуация, когда мне нужно вставить более 4000 символов в Oracle VARCHAR, и мне было рекомендовано не использовать CLOB. Предложенное решение состояло в том, чтобы разделить его на 2 столбца, по 4000 и 8000. Я сделал код динамическим, чтобы можно было обрабатывать количество столбцов X для повторного использования. Он работал отлично, проходил тестирование и т.д., Пока не был развернут, и кто-то скопировал и вставил из продукта Microsoft, и он сломался, потому что в функции было сгенерировано более 4000 байтов. Я не рассматривал Unicode.

Я попробовал несколько идей, чтобы решить эту проблему, прежде чем остановиться на одном, где я начинаю с 4000 символов, и если длина байта превышает 4000, удалите символ и снова проверьте длину байта. Это работает, но мне интересно, есть ли лучшее решение. Функция также изменяет имена столбцов с 'column' на 'column1', 'column2',... и т.д.

 text = data[key]
 index = 1
 while text:
     length = 4000
     while len(text[0:length].encode('utf-8')) > 4000:
          length -= 1
     data['{}{}'.format(key, index)] = text[0:length]
     text = text[length:]
     index += 1
 del data[key]
  • 1
    Этот вопрос / ответ имеет аналогичное решение для вашего, но он может иметь некоторые другие функции, которые вы найдете полезным
Теги:

2 ответа

1

Проверьте, действовал ли ваш совет по отношению к объектам CLOB, или он основан на старой информации о доступе к объектам LOB с использованием локаторов.

Лучшая практика для "маленьких" CLOB в cx_Oracle - представлять их как строки: ваш код будет простым и все же эффективным. Смотрите пример https://github.com/oracle/python-cx_Oracle/blob/master/samples/ReturnLobsAsStrings.py

Другое решение состоит в том, чтобы использовать последнюю версию Oracle DB, которая поддерживает 32K VARCHAR2.

  • 0
    У него было много причин, от того, как оно хранится, как оно резервируется, до списка проблем, с которыми он сталкивался за годы работы с LOB. Может быть, сейчас все по-другому, Идк, но он не сдвигается с места. Мне нравится идея 32 КБ, но БД настроена на 4 КБ.
0

Я закончил тем, что соединил ссылку Дж. Андерсона с моим кодом. Он более эффективен в том смысле, что он не кодирует для каждой проверки длины.

    encoded_text = data[key].encode('utf-8')
    index = 1
    while encoded_text:
        length = min(4000, len(encoded_text))
        if len(encoded_text) > 4000:
            while (encoded_text[length] & 0xc0) == 0x80:
                length -= 1
        data['{}{}'.format(key, index)] = encoded_text[:length].decode('utf-8')
        encoded_text = encoded_text[length:]
        index += 1
    del data[key]

Я также поиграл с идеей использовать encode('unicode-escape') чтобы обойти проблему с юникодом, но это может потенциально более чем удвоить мою длину строки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню