#Симптом и границы применимости
В приложении с SQLite кириллица сохраняется или выводится знаками вопроса и «кракозябрами» после неправильного преобразования строк в PHP/Python. Обычно причина в кодировке входящего файла, HTTP-ответа или обработке байтов перед записью, а не в настройке «кодировки таблицы» SQLite.
#Как отличить возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Неверно прочитан исходный файлКодировка CP1251 ошибочно расшифровывается как UTF-8 либо наоборот. | Искажённый текст ещё до INSERT | Исправить чтение входных байтов |
| Повторная перекодировкаУже декодированную строку приложение повторно обрабатывает как байты другой кодировки. | Последовательности вида РџСЂ | Убрать лишнее преобразование |
| Ошибочный HTTP-ответБраузер интерпретирует правильный UTF-8 как другую кодировку. | В sqlite3 текст правильный, на сайте неверный | Проверить Content-Type и шаблон |
#Пошаговая диагностика и безопасное исправление
- 1. Найдите этап, на котором портится строкаВыберите одну тестовую фразу «Привет, ёж» и проследите её в исходном файле, входных параметрах, SQL-результате и HTML-странице. Не начинайте с UPDATE всех строк: если порча в браузере, сами данные могут быть правильными.
- 2. Сохраните копию и сравните образецВыполните штатное резервное копирование работающей SQLite через Backup API или .backup, затем на тестовой копии найдите строку с искажением. Проверяйте отдельно представление в интерфейсе и содержимое базы.
- 3. Посмотрите байты значения в SQLiteВ sqlite3 на тестовом файле выполните SELECT hex(name) и length(name) для строки; hex показывает байты хранения TEXT. Для корректной фразы на UTF-8 кириллица обычно начинается с D0/D1, но вывод следует сравнивать с известными исходными байтами.SQLКомандаsqlite3, чтение. users, name и ID — условный пример; hex не доказывает автоматически исходную кодировку.
SELECT name, hex(name), length(name) FROM users WHERE id=42;
- 4. Проверьте обработку файла до INSERTЕсли данные импортируются из CSV, установите исходную кодировку в программе экспорта и прочитайте файл с ней явно. В Python для UTF-8 откройте файл с encoding="utf-8"; если получаете UnicodeDecodeError, проверьте реальную кодировку файла вместо игнорирования ошибок.
- Фрагмент Python для локального тестового файла; только чтение, ничего не пишет в SQLitePythonКомандаФрагмент Python для локального тестового файла; только чтение, ничего не пишет в SQLite.
with open("sample.csv", "r", encoding="utf-8", newline="") as f:print(f.readline())
- 5. Исправьте преобразование из Windows-1251 в PHP при подтверждении кодировкиДля исходных CP1251-байтов в PHP допустимо один раз преобразовать их через mb_convert_encoding в UTF-8 до вставки через подготовленный SQL-запрос. Если вход уже UTF-8, выполнять преобразование не нужно.
- Дополнительная команда по темеPHPКомандаПример PHP только для достоверно определённой кодировки Windows-1251; переменная $inputBytes содержит исходные байты.
$utf8 = mb_convert_encoding($inputBytes, 'UTF-8', 'Windows-1251');
- 6. Проверяйте HTTP-кодировку отдельноДля веб-страницы посмотрите заголовок Content-Type в средствах разработчика браузера: для HTML ожидается text/html; charset=UTF-8. Сверьте этот заголовок и мета-тег с реальными байтами шаблона. Менять заголовок недостаточно, если в базе уже испорченная строка.
- 7. Сохраните чистый образец через параметризованный запросВ тестовой базе запишите заранее известную корректную Unicode-строку с параметром prepared statement, затем прочитайте её тем же способом, что делает приложение. Не склеивайте значение с SQL вручную: проблема кодировки не отменяет риск SQL-инъекции.
- 8. Не исправляйте исторические строки без источникаЕсли в базе уже сохранены символы замены U+FFFD или «????», восстановить исходную кириллицу может быть невозможно без исходного файла/архива. Создайте отдельную процедуру миграции только после проверки точной обратимости преобразования на копии.
#Как проверить, что проблема устранена
Контрольная фраза совпадает посимвольно на входе, в запросе SELECT и в браузере; байты и заголовок HTTP согласованы, повторная перекодировка не выполняется.
#Если исправление не помогло
Если в SQLite текст правильный, ищите ошибку на этапе HTML/JSON-вывода. Если неверен уже ввод, проверьте кодировку файла, формы, внешнего API и сериализацию.