PDA

Просмотр полной версии : [Вопрос] Кодировка в SQLite



Gressie
16.04.2020, 06:56
Здравствуйте. Возможно ли в SQLite делать сохранение русского текста? Пробовал делать стандартную таблицу.

CREATE TABLE "my_table" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"text" TEXT
)

Если английский текст сохраняется и выводится нормально, то русский текст записывается в поле text как BLOB. А выводит текст к примеру, должно быть: "Сообщение" а выводит "яяяСяяяояяяояяябяяящяяяеяяяняяяияяяе"
Таблицу и базу данных пробовал создавать через DB Browser for sqlite
Как исправить?

Daniel_Cortez
16.04.2020, 21:44
Похоже на баг с возвратом строк в функциях SA-MP, некогда писал об этом: https://pro-pawn.ru/showthread.php?13007-%D0%91%D0%B0%D0%B3-%D0%B2-GetPVarString-GetSVarString-%D0%B8-%D0%BA%D0%B0%D0%BA-%D0%B5%D0%B3%D0%BE-%D0%B8%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D1%8C
Код для обхода проблемы приведён в той же теме.

tnc
17.04.2020, 14:06
Похоже на баг с возвратом строк в функциях SA-MP, некогда писал об этом: https://pro-pawn.ru/showthread.php?13007-%D0%91%D0%B0%D0%B3-%D0%B2-GetPVarString-GetSVarString-%D0%B8-%D0%BA%D0%B0%D0%BA-%D0%B5%D0%B3%D0%BE-%D0%B8%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D1%82%D1%8C
Код для обхода проблемы приведён в той же теме.

А разве проблема не в том, что SQLite из коробки не поддерживает windows-1251 (https://www.sqlite.org/pragma.html#pragma_encoding)?

Судя по документации, то можно установить только utf8/utf16:



PRAGMA encoding;
PRAGMA encoding = 'UTF-8';
PRAGMA encoding = 'UTF-16';
PRAGMA encoding = 'UTF-16le';
PRAGMA encoding = 'UTF-16be';

Daniel_Cortez
17.04.2020, 14:34
А разве проблема не в том, что SQLite из коробки не поддерживает windows-1251 (https://www.sqlite.org/pragma.html#pragma_encoding)?
Нет, дело не в этом.
Ок, попробую разжевать ещё раз:

должно быть: "Сообщение" а выводит "яяяСяяяояяяояяябяяящяяяеяяяняяяияяяе"
Если присмотреться, это не какая-то каша из рандомных символов, а просто перед каждым символом вставляются 3 лишних буквы "я". Запомним это.
Как я уже упоминал в статье по ссылке выше, во многих функциях SA-MP присутствует баг с записью строк в переданный массив: символы по ошибке конвертируются в int32_t (на самом деле в исходниках этот тип называется "cell", но он является производным от int32_t) не из unsigned char, а из обычного char, т.е. с расширением знакового бита, из-за чего у всех символов с кодом больше 127 (0x7F) старшие 3 байта устанавливаются в FF (т.е. 0x7F после преобразования становится 0x0000007F, но 0x80 => 0xFFFFFF80). Если получившуюся "неправильную" строку подать в SendClientMessage(), ShowPlayerDialog() или любую другую функцию SA-MP (кроме printf() или format()), сервер примет такую строку за упакованную (т.к. в обычной неупакованной строке старшие биты символов равны нулю) и интерпретирует старшие байты, по ошибке установленные в FF, как отдельные символы. Код "FF" имеет символ кириллицы "я" - именно так и появляются те самые 3 лишних "я" перед каждой буквой в строке.

tnc
17.04.2020, 14:53
Я все же решил проверить. Проблема остается и после фикса:



before the fix
i: 0 | dec: 209 | hex 000000D1
i: 1 | dec: 128 | hex 00000080
i: 2 | dec: 209 | hex 000000D1
i: 3 | dec: 131 | hex 00000083
i: 4 | dec: 209 | hex 000000D1
i: 5 | dec: 129 | hex 00000081
i: 6 | dec: 32 | hex 00000020
i: 7 | dec: 209 | hex 000000D1
i: 8 | dec: 143 | hex 0000008F
i: 9 | dec: 208 | hex 000000D0
i: 10 | dec: 183 | hex 000000B7
i: 11 | dec: 209 | hex 000000D1
i: 12 | dec: 139 | hex 0000008B
i: 13 | dec: 208 | hex 000000D0
i: 14 | dec: 186 | hex 000000BA
i: 15 | dec: 33 | hex 00000021
after the fix
i: 0 | dec: 209 | hex 000000D1
i: 1 | dec: 128 | hex 00000080
i: 2 | dec: 209 | hex 000000D1
i: 3 | dec: 131 | hex 00000083
i: 4 | dec: 209 | hex 000000D1
i: 5 | dec: 129 | hex 00000081
i: 6 | dec: 32 | hex 00000020
i: 7 | dec: 209 | hex 000000D1
i: 8 | dec: 143 | hex 0000008F
i: 9 | dec: 208 | hex 000000D0
i: 10 | dec: 183 | hex 000000B7
i: 11 | dec: 209 | hex 000000D1
i: 12 | dec: 139 | hex 0000008B
i: 13 | dec: 208 | hex 000000D0
i: 14 | dec: 186 | hex 000000BA
i: 15 | dec: 33 | hex 00000021
reason: С_С_С_ С_Р·С<Рє!

Код:

printf("before the fix");
for (new i = 0, len = strlen(reason); i < len; i++)
{
printf("i: %d \t| dec: %d \t| hex %08x", i, reason[i], reason[i]);
}
FixSVarString(reason);
printf("after the fix");
for (new i = 0, len = strlen(reason); i < len; i++)
{
printf("i: %d \t| dec: %d \t| hex %08x", i, reason[i], reason[i]);
}


Извиняюсь, что не переименовал функцию, но это было ради теста. reason - загружается из базы данных. Возможно топикастер указал рандомный набор, а не вывод от printf и подобных функции для IO?

P.S: если чего, то я не пытаюсь спорить, а просто решил проверить.