![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чтение данных из файла UTF-8 [D6, WinXP]
leonidus © (2008-06-13 11:58:00)Есть файл с данными в формате UTF8, мне нужно их прочесть и сконверировать в UTF16.
st_u:widestring;
f:textfile;
AssignFile(F, edit1.Text);
Reset(F);
readln(F,st_u);
st_u:= UTF8Decode(st_u);
В результате получаю st_u='', хотя при чтении из файла (readln(F,st_u)) строка содержит данные. Что же не так?
Anatoly Podgoretsky (2008-06-14 00:31:00) [1]
> почему же, это может быть UTF8 - все что до 7F кодируется
> одним байтом.
Хотя бы из-за этого 00 00, а до него обычный ASCII
И больше никакой информации из файла не приведно, хотя и это достаточно, чтобы сказать, что это не UTF8
leonidus (2008-06-13 23:57:00) [2]Я пробовал и через BlockRead:
function StringToHex(const Source: String): String;
var i, Len: Integer;
begin
Result := '';
Len := Length(Source);
for i := 1 to Len do
Result := Result + IntToHex(Ord(Source[i]), 2) + ' ';
end;
var
Buf: array[1..20048] of Char;
st,idx:string;
FromF: file;
AssignFile(FromF, edit1.Text);
Reset(FromF, 1);
repeat
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
st:='';
for i:=1 to 20048 do
st:=st+buf[i];
idx:=idx+st;
st:=StringToHex(st);
idx_hex:=idx_hex+st;
until (NumRead = 0);
CloseFile(FromF);
В результате получаю текстовую строку:
idx_hex=30 30 64 61 74 61 62 61 73 65 69 6E 66 6F 00 00 ....
из которой извлекаю слово, смещение и длину и помещаю все это в TtntStringList в такое примерно виде:
30 30 64 61 74 61 62 61 73 65 69 6E 66 6F=0|1313
30 30 64 61 74 61 62 61 73 65 73 63 72 69 70 74=1313|10413
до знака равно это закодированное слово, затем смещение и длина.
Осталось только декодировать само слово преобразовав его в читаемые символы не потеряв при этом юникода.
McSimm (2008-06-13 23:55:00) [3]
> Это не UTF8
почему же, это может бытьUTF8 - все что до 7F кодируется одним байтом.
palva (2008-06-13 22:52:00) [4]То, что вы описывали в [13] не очень подходит для чтения текстовыми функциями ReadLn. Для двоичного чтения используйте функцию BlockRead, либо другой метод чтения при помощи TFileStream. Но здесь, конечно, вам надо освоиться с чтением строки или целого числа из файла при помощи двоичного чтения.
leonidus (2008-06-13 22:30:00) [5]ок, Анатолий тогда подскажите как прочесть эти данные и записать в WideString
Anatoly Podgoretsky (2008-06-13 22:27:00) [6]> leonidus (13.06.2008 22:14:20) [20]
Это не UTF8
leonidus (2008-06-13 22:14:00) [7][18] так я же приводил:
30 30 64 61 74 61 62 61 73 65 69 6E 66 6F 00 00
palva (2008-06-13 21:56:00) [8]
> вот файл с которым борюсь:
С файлом надо не бороться, с ним надо работать. Только сначала нужно освоить инструмент, которым работаете. Тогда это и будет кропотливая и нудная, но работа, а не борьба. Инструмент освоить здесь вам пожалуй что и помогут. А вот разбираться с файлом вряд ли будут, даже если вы будет уверять, что UTF8Decode не работает.
Anatoly Podgoretsky (2008-06-13 21:37:00) [9]А сюда привестм, что несколько байтов с UTF8 как просили не можешь?
leonidus (2008-06-13 19:56:00) [10]вот файл с которым борюсь:
http://www.realsofts.com/fr-ru-synt.zip
Anatoly Podgoretsky (2008-06-13 19:39:00) [11]> leonidus (13.06.2008 19:17:14) [14]
Попробуй сам преобразовать свои хекс коды в ANSI и сам увидишь.
palva (2008-06-13 19:37:00) [12]leonidus (13.06.08 19:13) [13]
Ну то есть вопрос о неправильной работе функции UTF8Decode снят.
leonidus (2008-06-13 19:17:00) [13]Анатолий, мне нравится ваша лаконичность, но было бы здорово если бы она подпитывалась фактами. Я открываю файл через программу ListEdit, она определяет кодировку WIN(RUS) при этом не отображая скажем немецкие умляуты, но если я принудительно высталяю UTF-8, то все слова отображаются корректно, из чего я делаю вывод что кодировка документа именно UTF-8. что подтверждает и документация
http://stardict.sourceforge.net/StarDictFileFormatтребующая от словаря именно такой кодировки.
leonidus (2008-06-13 19:13:00) [14]palva дело в том что файл состоит больше чем из одного слова 00databaseinfo, а если его открывать функцией [5], то на выходе только "00databaseinfo".
А идея вот в чем я пишу конвертер словарей StarDict в свой более простой формат, по спецификации формата словарей StarDict, словарь состоит из индексного файла и файла данных. Я сейчас разбираюсь с индексным. Он в формате UTF8 (был бы UTF16 я бы без проблем открыл его средствами библиотеки TNT) содержит последовательность заголовков словарных статей , маркер конца словарной статьи это символ "00", далее идут 4 байта смещения и 4 байта длины словарной статьи, потом следующий заголовок словарной статьи и так до конца индексного файла. Следовательно первое что мне нужно, это прочесть весь индексный файл в память (я помещаю его в строку String), после чего уже работаю с ней как с массивом. Но затем мне нужно данные записать в TTntStringList после чего сохранить эту структуру на диск но для этого UTF8 нужно преобразовать в UTF16 не потеряв при этом "юникодность" т.е. словарь может содержать не только англ. и русские бурвы но и например немецкие или испанские.
Anatoly Podgoretsky (2008-06-13 18:58:00) [15]> leonidus (13.06.2008 17:39:07) [7]
Это не UTF8
palva (2008-06-13 18:29:00) [16]
> leonidus (13.06.08 17:39) [7]
У меня ваша строка преобразуется правильно:
Непонятно, почему у вас в результате преобразования была пустая строка. Можете попробовать следующий код:
{$APPTYPE CONSOLE}
var
s: String;
w: WideString;
begin
s :='00databaseinfo'#0#0;
w := UTF8Decode(s);
WriteLn(Length(w)); // 16
WriteLn(Ord(w[16])); // 0
end.
Может быть, я вас неправильно понял. Объясните точнее, что означают ваши слова в посте [3]
> так же ничего не дает.
leonidus (2008-06-13 18:04:00) [17]ZENsan так и не понял что нужно в вашей функции изменить, она вроде не ищет "00" для для завершения своей работы...
и можно "расшифровать" фразу "А когда нет бома, просто делай UTF8Decode и подавай строку эту." ?
ZENsan (2008-06-13 17:45:00) [18]измени просто функцийю если она тебе подходит немного и будет брать строку и после 00..
А когда нет бома, просто делай UTF8Decode и подавай строку эту.
ZENsan (2008-06-13 17:43:00) [19]У тебя UTF-8 without BOM.
leonidus (2008-06-13 17:39:00) [20]Это словарь от программы StarDict, вот его первые байты:
30 30 64 61 74 61 62 61 73 65 69 6E 66 6F 00 00
функция от ZENsan, возвращает строку до первого "00", т.е. :
"30 30 64 61 74 61 62 61 73 65 69 6E 66 6F" только в виде текста "00databaseinfo".
Как ни странно, но в файле нет маркеров $BBEF, $FEFF или $FFFE, но я точно знаю что файл в формате UTF-8.