Как побайтно прочитать строку WideString в Linux

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
dvpt
новенький
Сообщения: 38
Зарегистрирован: 18.03.2009 10:46:04

Как побайтно прочитать строку WideString в Linux

Сообщение dvpt »

Столкнулся с ситуацией когда компилятор по разному обрабатывает строки WideString в Windows и Linux

Код: Выделить всё

var
  buffer_ic[i] : array[0..MaxKeyCHR] of Char;
  wsbuffer : WideString;
begin
..
   for i := 0 to RecSize-1 do buffer_ic[i] := wsbuffer[i+p+1];
..


В Windows все правильно читает по байтно, т.е. кириличесикие символы раскладывает на два
а в Linux преобразовывает строку в AsciString? и потом получается ерунда!
Кто знает как по байтно прочитать строку WideString?
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

* WideString, в Linux-е, на самом деле UnicodeString.
* UnicodeString работает одинаково в Windows и Linux.
* в Windows тип WideString совместим с системным OleString. Тип UnicodeString, соответственно, с OleString не совместим.

Вывод. Термин "прочитать по-байтно WideString" некорректен. Наверное нужно прочитать WideString посимвольно?!
(при посимвольном чтении начинаются забавы с конвертацией кодировок, а они разрные на Винде и Линухе, от сюда фигня и получается)

Вывод 2:
На самом деле, по-байтное чтение WideString-а, выглядит так:

Код: Выделить всё

var
  buffer_ic[i] : array[0..MaxKeyCHR] of Char;
  wsbuffer : WideString;
begin
..
   for i := 0 to length(wsbuffer)*2-1 do
     buffer_ic[i] := PByteArray(@wsbuffer[1])^[i];
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

dvpt
wsbuffer[i+p+1] имеет тип WideChar, а не Char. В твоем коде происходит неявное преобразование из одной кодировки в другую.
dvpt
новенький
Сообщения: 38
Зарегистрирован: 18.03.2009 10:46:04

Сообщение dvpt »

Спасибо за ответ!

Добавлено спустя 4 часа 47 минут 38 секунд:
Если строка на латинице
s := 'test'; то Length(s) = 4;
Если строка на латинице
s := 'тест'; то Length(s) = 8;
то ее длина в два раза больше
Если строка на смешанная
s := 'testтест'; то Length(s) = 12;
Я пробовал через указатель, но указывает почемуть не на строку:)?
Если объявить строку String тогда получается но только первые 255 символов.

Добавлено спустя 16 минут 11 секунд:
Не найду, в каком модуле объявлен тип UnicodeString для Linux?
Кто знает?
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Я пробовал через указатель, но указывает почемуть не на строку:)?

В фри паскале у строк происходит подсчет ссылок, указатель на символы нужно получать при помощи @(S[1]).
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

dvpt писал(а):Не найду, в каком модуле объявлен тип UnicodeString для Linux?

Должна быть в модуле System.
dvpt
новенький
Сообщения: 38
Зарегистрирован: 18.03.2009 10:46:04

Сообщение dvpt »

Почему компилятор для Windows и для Linux работают со строками WideString по разному?
В Windows компиляторе у меня правильно работает, а в Linux полная галимотья.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

dvpt писал(а):Почему компилятор для Windows и для Linux работают со строками WideString по разному?
В Windows компиляторе у меня правильно работает, а в Linux полная галимотья.

работает компилятор одинаково. Разница между системными кодировками в Window и Linux.

можно ли более конкретный пример (со скриншотами) галиматьи.
Timid
постоялец
Сообщения: 290
Зарегистрирован: 21.11.2007 20:33:15

Сообщение Timid »

dvpt писал(а):Почему компилятор для Windows и для Linux работают со строками WideString по разному?
В Windows компиляторе у меня правильно работает, а в Linux полная галимотья.


Тебе уже ответили - WideString - системнозависим. Он используется для передачи данных в компоненты форм и прочего. В WinForm будет одно, в QT, гноме и кедах - совсем другое. Поэтому в памяти переменная этого типа может содержать совсем разные данные.
Так же как с кодировками CP866 (DOS) и Win1251. Начертание одно, а коды - разные.
dvpt
новенький
Сообщения: 38
Зарегистрирован: 18.03.2009 10:46:04

Сообщение dvpt »

Код: Выделить всё

var
  i : Integer;
  p : DWord;
  wsbuffer : WideString;
  buffer_ic : array[0..MaxKeyCHR] of Char;
begin
  Result := False;
  AssignFile(Source,FileName);
  Rewrite(Source,1);
  wsbuffer := Memo1.Text;
  p := 0;
  while p <= Length(wsbuffer) do begin
    if (Length(wsbuffer) - p) >= Sizeof(buffer_ic)) then begin
      for i := 0 to Sizeof(buffer_ic)-1 do buffer_ic[i] := wsbuffer[i+p+1];
      BlockWrite(Source,buffer_ic,Sizeof(buffer_ic));
    end else begin
      for i := 0 to Length(wsbuffer)-p-1 do buffer_ic[i] := wsbuffer[i+p+1];
      BlockWrite(Source,buffer_ic,Length(wsbuffer)-p);
    end;
    p := p + Sizeof(buffer_ic);
  end;
  CloseFile(Source);
end;


Код упростил. Убрал из него манипуляции с буфером.
Примеры:
Текст "Тест" в Windows записывается в файл в кодировке Unicode и длина файла 8 символов.
Текст "Тест" в Linux записывается в файл в кодировке ???? и длина файла 4 символа, а сам текст символы "????".
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

В Линуксе надо подключать к проекту модуль cwstring...
dvpt
новенький
Сообщения: 38
Зарегистрирован: 18.03.2009 10:46:04

Сообщение dvpt »

Примного благодарен.
Помог модуль cwstring, а тип строки UTF8String и все заработало правильно в Linux и в Windows

Код: Выделить всё

  {$IFDEF MSWINDOWS}
  wsbuffer : WideString;
  {$ENDIF}
  {$IFDEF UNIX}
  wsbuffer : UTF8String;
  {$ENDIF}
Ответить