Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > SQLite - знаки вопроса вместо букв


Автор: CompWorm 24.5.2010, 17:12
задача аналогична описаной http://forum.vingrad.ru/topic-184900.html
работаю с проектом, который изначально писался на Delphi2009

новая связка Delphi7+SQLite3...

БД в юникоде, экспортирую так примерно:
Код

result := Utf8Decode(SQLTable.FieldAsString(SQLTable.FieldIndex['Name']));

в ответ знаки вопроса ????????? вместо русских букв...
пробовал вместо Utf8Decode (который у меня шикарно справлялся с задачей в D2009) пользоваться http://forum.vingrad.ru/forum/topic-133239/unread-1/hl/utf/index.html результат ткой же. ANSIToUTF8 и UTF8ToANSI вообще ничего не делают. так крокозяблы и выводят.

может тут UTF16 какой-нибудь? или может как-то перекодировать в самом SQLite?  smile 

Автор: CompWorm 25.5.2010, 09:14
Цитата(CompWorm @  24.5.2010,  17:12 Найти цитируемый пост)
может тут UTF16 какой-нибудь? или может как-то перекодировать в самом SQLite?  smile  

цитирую сам себя  smile  
- проверил, нет, тут я был не прав. SQLite работает только с UTF... в настройках базы у меня выставлен UTF8 


есть другие идеи?

Автор: yogi89 25.5.2010, 11:43
Уверен, что сами данные в базе не хранятся криво? Можно проверить, сделав выборку строк без преобразования Utf8ToAnsi или Utf8Decode, либо через командную оболочку скулайта, перед запуском которой задать кодировку chcp 65001.

Задать принудительно кодировку SQLite можно запросом PRAGMA encoding="UTF-8"

Автор: CompWorm 25.5.2010, 15:36
уверен. в базе русские буквы есть. именно эта база работает описанным выше способом в D2009. проблема в том, что D7 не дружит с UTF так как более поздняя D2009...

я попробовал выполнить предложенную Вами команду
PRAGMA encoding="UTF-8"
PRAGMA encoding="chcp 65001"
PRAGMA encoding="cp1251"
эффекта нет. если зайти на закладку настроек бд в оболочке, то там неизменно стоит UTF-8 в качестве кодировки... даже если попытаться сменить на UTF-16... меняется только на закладке настроек (действительно, этой командой!)

всё равно, спасибо за попытку. 
есть ещё какие-то идеи?

Автор: yogi89 28.5.2010, 08:14
Цитата(CompWorm @  25.5.2010,  15:36 Найти цитируемый пост)
PRAGMA encoding="chcp 65001"

Не правильно меня поняли. chcp 65001 - команда для CMD, меняющая кодовую на UTF8. После, можно запустить оболочку скулайта и русские строчки будут выводиться, как надо.. Можно так проверить, действительно ли в базе данные хранятся не криво..

Цитата(CompWorm @  25.5.2010,  15:36 Найти цитируемый пост)
PRAGMA encoding="cp1251"

cp1251 - не поддерживается вообще скулайтом. 

Странно, почему не работает функция Utf8ToAnsi.  Проверил у себя(правда, на 2010х делфях) - все прекрасно преобразовывается... 



Автор: Akella 28.5.2010, 12:33
Цитата(CompWorm @  24.5.2010,  17:12 Найти цитируемый пост)
новая связка Delphi7+SQLite3...

SQLite3 - это такие компоненты доступа?

Автор: AntonN 28.5.2010, 23:03
Это встраиваемая база данных, без всяких провайдеров и датасетов

Автор: Akella 29.5.2010, 10:01
Т.е. компонента TDataSource сразу цепляется к базе??? Круто!

Автор: CompWorm 30.5.2010, 19:04
Akella, ммм... там конечно есть DISQLite3DataSetImporter, но скрестить его с TDataSource у меня не особо получилось... любопытно, надо почитать на эту тему)) 

в основном подход такой:
Код

var sltb:TSQLiteTable;
sldb := TSQLiteDatabase.Create('test.db');
...
    sltb := sldb.GetTable('select бла бла бла ... "');
    for i := 0 to sltb.Count - 1 do
      begin
        бла бла := sltb.FieldAsString(0));
        sltb.Next;
      end;

... всё круто, но ведать только для D2007 и старше. судя по отзывам в инете с D7 проблемы((( с оператороми сортировки особо изощрённые чудеса))

у меня назрел вопрос, а нет отдельного модуля для работы с UTF8 для D7... может кто пытался выковыривать код из старших версий дельфи? дело в том, что этот же код с этой же БД скомпилированный под D2009 работает на ура...

Автор: Демо 30.5.2010, 21:10
Цитата(CompWorm @  30.5.2010,  19:04 Найти цитируемый пост)
... всё круто, но ведать только для D2007 и старше. судя по отзывам в инете с D7 проблемы(((


Работаю в D6 с SQLite.
Проблем никаких.

Обёртка в приложенном файле. Добавляю свою надстройку над обёрткой и всё.

Добавлено @ 21:11
Цитата(Akella @  29.5.2010,  10:01 Найти цитируемый пост)
Т.е. компонента TDataSource сразу цепляется к базе??? Круто!


SQLite предоставляет только API для доступа к БД.

Автор: AntonN 30.5.2010, 22:41
Akella, нет там этих вещей, запросы через импортируемые из dll процедурки уходят.
Довольно удобно smile

Автор: CompWorm 31.5.2010, 11:33
Демо, я пользуюсь именно этой обёрткой.

если кому не лень, запустите у себя примерчик и скажите, есть у вас русские символы или нет.
может я просто туплю где-то...

Автор: Демо 31.5.2010, 11:56
Цитата(CompWorm @  31.5.2010,  11:33 Найти цитируемый пост)
если кому не лень, запустите у себя примерчик и скажите, есть у вас русские символы или нет.


Только вечером дома...

Добавлено через 6 минут и 10 секунд
CompWorm

А почему такой выбор - кодирование в UTF-8?

Автор: Akella 31.5.2010, 14:50
Да знаю я.
Я просто своим вопрос хотел намикнуть на то, что CompWorm не указал компоненты доступа. А ещё он не указал, поддерживают ли они анси или там юникод.

Автор: CompWorm 31.5.2010, 20:04
Демо, по умолчанию это основная кодировка в скулайте. есть ещё всякие http://www.sqlite.org/pragma.html#pragma_encoding других не вижу... а вы какой рекомендуете пользоваться?

Автор: Демо 31.5.2010, 20:36
Цитата(CompWorm @  31.5.2010,  20:04 Найти цитируемый пост)
Демо, по умолчанию это основная кодировка в скулайте


У меня по-умолчанию Win1251.

Добавлено через 1 минуту и 29 секунд
Поэтому просто никаких проблем не возникает.

Добавлено через 4 минуты и 13 секунд
CompWorm

Как добавляешь строки в базу?

Автор: Демо 31.5.2010, 20:56
Если писать без всякой перекодировки, то и читается всё нормально.

Кстати, вот эти 2 строки

Код

      MainGrid.Cells[0, SQLtb.Row+1] := Utf8Decode(SQLtb.FieldAsString(SQLtb.FieldIndex['name']));
      MainGrid.Cells[1, SQLtb.Row+1] := Utf8toansi(SQLtb.FieldAsString(SQLtb.FieldIndex['name']));


 твою первую запись из таблицы показывают нормально.

Автор: CompWorm 1.6.2010, 10:37
Цитата(Демо @  31.5.2010,  20:56 Найти цитируемый пост)
Кстати, вот эти 2 строки
...
 твою первую запись из таблицы показывают нормально. 

 smile чудесааа....

не представляю в чём тогда проблема... может с виндой что не так? хмм... ну попробую сегодня поставить дельфи7 на другой машине... я в шоке  smile

Добавлено через 4 минуты и 37 секунд
Цитата(Демо @  31.5.2010,  20:36 Найти цитируемый пост)
У меня по-умолчанию Win1251.

у меня утф, так как строки я заполнял в приблуде для работы со скулайтом, а не программно. я попробую ваш метод. спасибо.

Автор: Akella 2.6.2010, 11:30
CompWorm, по-моему, ты уже запутался в кодировках. Я бы на твоем месте взял и привёл всё к единой кодировке. И данные, и базу, и подключение, и среду разработки, и компоненты доступа %)

Автор: CompWorm 2.6.2010, 16:33
Демо
большое спасибо за помощь+! я попробовал программно заносить данные без кодирования в UTF и всё нормально заработало....

ЗЫ если зайти в базу через приблуду, то русский текст отображается кракозяблами типа
Цитата

��������!

но в проге работает на ура!  smile 

не понятно только почему мой код у вас сработал с моей базой...  smile 

Автор: hhhhhhhhhhhh 22.3.2011, 02:42
Цитата
я попробовал программно заносить данные без кодирования в UTF и всё нормально заработало....

Тогда не работает русский поиск через LIKE.
А если при записи в базу кодировать в UTF, то русский поиск работает, НО регистрозависимо.
Как сделать чтобы и кодировать ни надо было(ибо база разбухает от этого гребаного UTF) и поиск русских слов нормально работал, причем регистронезависимо?!
Помогите!

Автор: Akella 22.3.2011, 10:54
что-то типа
Код
select id from table1 where UPPER(name) = 'ВАСЯ'


Ищи в SQLite функцию UPPER

Автор: hhhhhhhhhhhh 24.3.2011, 10:27
Спасибо за наводку! Вроде разобрался!

Вот здесь есть пример с текстовым полем.
http://forum.sources.ru/index.php?showtopic=294492

Я лиш добавлю на всякий случай пример с блобовым полем
Код

Регистрируем нашу функцию
sqlite3_create_function(db.fDB, 'UPPER', 1, SQLITE_UTF8, nil, MyUpperFunc, nil, nil);

const
  SQLITE_UTF8  = 1;

type
  TFuncHandler=procedure(pCtx: pointer; nArgs: Integer; Args: PPChar); cdecl;
  TFuncFinalizer=procedure(context:pointer); cdecl;

function sqlite3_create_function(db:pointer; zFunctionName:pchar; nArg:integer;  eTextRep:integer;  userData:pointer;  xFunc,  xStep:TFuncHandler;  xFinal:TFuncFinalizer):integer; cdecl; external SQLITEDLL;
function sqlite3_value_blob(value: Pointer): Pointer; cdecl; external SQLiteDLL name 'sqlite3_value_blob';
function sqlite3_value_bytes(value: Pointer): integer; cdecl; external SQLiteDLL name 'sqlite3_value_bytes';
function sqlite3_value_type(value: pointer): integer; cdecl; external SQLiteDLL name 'sqlite3_value_type';
procedure sqlite3_result_blob(sqlite3_context: pointer; value: Pointer;
                             n: integer; destroy: pointer); cdecl; external SQLiteDLL name 'sqlite3_result_blob';
procedure sqlite3_result_null(sqlite3_context: pointer); cdecl; external SQLiteDLL name 'sqlite3_result_null';

var MyUpperBuf: String;
procedure MyUpperDisposeProc(ptr: pointer); cdecl;
begin
  MyUpperBuf := '';
end;

procedure MyUpperFunc(pCtx: pointer; nArgs: Integer; Args: PPChar); cdecl;
var Buf: PChar;
begin
  case sqlite3_value_type(Args^) of
    SQLITE_NULL: sqlite3_result_null(pCtx);
    SQLITE_BLOB:       
      begin
        Buf := sqlite3_value_blob(Args^);
            SetString(MyUpperBuf, Buf, sqlite3_value_bytes(Args^));
            StrDecompress(MyUpperBuf);
        CharUpperBuff(PChar(MyUpperBuf), Length(MyUpperBuf));
             // возвращаем в UTF ! похоже сравнение идет ТОЛЬКО В UTF
        MyUpperBuf := AnsiToUtf8(MyUpperBuf);
           sqlite3_result_blob(pCtx, PChar(MyUpperBuf), Length(MyUpperBuf), @MyUpperDisposeProc)
      end;
    else
      sqlite3_result_null(pCtx);
  end;
end;


запрос делаем чере UPPER приводя к UTF
Код
where ' +  'UPPER(colname) like "%' + AnsiToUtf8(AnsiUpperCase(ComboBox1.Text)) + '%"'));


ну и сортируем тоже через нашу функцию ORDER BY UPPER(colname) 

пс. строки в базу пишем без кодировки, база не распухает от UTF!  8D 

Автор: Akella 24.3.2011, 12:13
Цитата(hhhhhhhhhhhh @  24.3.2011,  10:27 Найти цитируемый пост)
ORDER BY UPPER(colname)

а зачем при сортировке UPPER?

Автор: hhhhhhhhhhhh 24.3.2011, 13:34
Цитата(Akella @  24.3.2011,  12:13 Найти цитируемый пост)
а зачем при сортировке UPPER?

Танцы с бубнами показали  ;) 

Автор: Akella 24.3.2011, 13:44
всмысле

Автор: hhhhhhhhhhhh 24.3.2011, 13:56
Ну, оказывается, русская сортировка тоже не работает без нашей UPPER функции

а вообще да, надо попробовать заюзать индексы для сортировки...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)