Unicode

  • Автор темы slavas
  • Дата начала
Статус
Закрыто для дальнейших ответов.
S

slavas

#1
Мне нужно отредактировать в TMemo текстовый файл (он в формате Unicode). Каким образом мне его загрузить в Memo?
Просто командой Memo1.Lines.LoadFromFile() отображается что-то непонятное. А потом его ещё и сохранить так чтобы он остался в Unicode?
Пожалуйста работающий примерчик. У меня Дельфи 7
-----
Два дня прошло - ответов нет. Неужто сложный вопрос? Ладно.
Вот что я нашел в моих поисках:
UTF-8 и Unicode это немного разные вещи. Доказательством тому служит то, что в Delphi есть функции UTF8ToUnicode и UnicodeToUTF8. :)
Загружать и сохранять файлы с Unicode (или UTF-8, Вы уж там определитесь сами, с чем хотите работать) можно как и любые другие текстовые файлы. Файл он и в Африке файл, вне зависимости от его содержимого. А вот как работать с этим самым содержимым - это уже Ваша проблема. Например FAR сначала перекодирует UTF-8 в DOS кодировку, после чего Вы можете его править. При сохранении происходит перекодировка в обратном порядке - из DOS в UTF-8.
В Delphi для перекодировок есть специальные функции. Две из них я Вам привёл. Для работы с UTF-8 есть функции UTF8ToAnsi и AnsiToUTF8. Они соответственно перекодируют из UTF8 в кодировку ANSI и обратно.
Таким образом можно составить простейший алгоритм по работе с файлом в кодировке UTF-8.
1. Открываете файл обычным образом.
2. Читаете файл построчно.
3. Перекодируете прочитанную строку в ANSI.
4. Заносите перекодированную строку, например, в TMemo.
5. Редактируете, а потом делаете всё в обратном порядке.

Var
f: TextFile;
s: UTF8string;
Begin
//Открываем файл
Assign(F, 'файл.txt');
Reset(F);
While not Eof(F) Do
Begin
ReadLn(F, s); //Считываем строку из файла
Memo1.Lines.Add(UTF8ToAnsi(s)); //Заносим строку в Мемо с перекодировкой
End;
...
End;
Помогите это дело перевести для случая с Unicode. У меня не получается.
Все время какая то проблема с несовместимыми типами.
 
S

slavas

#2
Ну и что мне делать? Кто нибудь знает ответ на этот вопрос? Для чего тогда функции WideCharToStrVar, OleStrToStrVar с текстовыми переменными с широкой строкой, если я попросту не могу эти переменные заполнить? Помогите.
 
E
#3
Либо используйте компоненты которые поддерживают юникод, либо надо установить соотв. чарсет контролам, либо конвертировать с пом. спец функций
вот их тут есть: AnsiToUtf8, PUCS4Chars, StringToWideChar, UCS4StringToWideString, UnicodeToUtf8, UTF8Decode, UTF8Encode, Utf8ToAnsi, Utf8ToUnicode, WideCharLenToString, WideCharLenToStrVar, WideCharLenToStrVar, WideCharToString, WideCharToStrVar, WideStringToUCS4String ..
 
S

slavas

#4
либо конвертировать с пом. спец функций
вот их тут есть: AnsiToUtf8, PUCS4Chars, StringToWideChar, ......
Так как раз в этом и проблема! Функции известны, а воспользоваться ими не могу. Попросту текст не могу взять из файла!
Не забываем, что он там в Юникоде (не UTF8). Кстати такой файл можно создать и сохранить в Блокноте, выбрав там Юникод.
А компоненты, поддерживающие Юникод, надо специально искать? или они есть в стандартном Дельфи 7?
 
S

slavas

#6
Искал и в Гугде и в Яндексе, еще до вопроса в форуме, и сейчас посмотрел, ничего там в интернете не изменилось. ответа на мой вопрос нет. Повторюсь. Как загрузить из файла текст(букву) (Юникод UTF16) в переменную типа PWideChar? Похоже, только с этим типом работают нужные мне функции преобразования.
 
E
#7
Вторая ссылка из пред. поста ведет на компоненты, поддерживающие юникод.
 
S

slavas

#8
15 мегов, да... С моей то сотовой связью. Если что нибудь не придумаю, буду качать. Хотелось попроще. Я уже так много знаю об этом Юникоде, что уже в теории могу сам перекодировщик написать. Взять текст как file of byte; первую пару выкидываем-это признак Юникода, далее каждой паре байт соответствует свой символ. Единственный недостаток это составлять для всех символов однозначное соответствие. Большой объем кода получается. Может кто написал проще, без этой таблицы? Пишите.
Спасибо за ответы, Вы дали мне направление, как можно решить эту проблему.
 
Z

zubr

#9
Код:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

TMemoWithUnicod = class(TCustomMemo)
private
FMemStream: TMemoryStream;
public
procedure LoadFromUnicodFile(const FileName: string);
procedure SaveToUnicodFile(const FileName: string);

constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

var
MemoWithUnicod:TMemoWithUnicod;

constructor TMemoWithUnicod.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMemStream := TMemoryStream.Create;
end;

destructor TMemoWithUnicod.Destroy;
begin
FMemStream.Free;
inherited Destroy;
end;

procedure TMemoWithUnicod.LoadFromUnicodFile(const FileName: string);
var
wbuf: PChar;
zag: Word;
begin
FMemStream.LoadFromFile(FileName);
If FMemStream.Size < 2 then
exit;
FMemStream.Position := 0;
FMemStream.Read(zag, 2);
If zag <> $FEFF then
exit;

FMemStream.Position := 2;
wbuf := StrAlloc(FMemStream.Size);
try
ZeroMemory(wbuf, FMemStream.Size);
FMemStream.Read(wbuf^, FMemStream.Size-2);
Lines.Text := WideCharToString(PWideChar(wbuf));
finally
StrDispose(wbuf);
end;
end;

procedure TMemoWithUnicod.SaveToUnicodFile(const FileName: string);
var
dest: PWideChar;
zag: Word;
begin
FMemStream.Clear;
FMemStream.Position := 0;
zag := $FEFF;
FMemStream.Write(zag, 2);

FMemStream.Position := 2;
GetMem(dest, (Length(Lines.Text)+1)*2);
try
ZeroMemory(dest, (Length(Lines.Text)+1)*2);
StringToWideChar(Lines.Text, dest, Length(Lines.Text)+1);
FMemStream.Write(dest^, Length(Lines.Text)*2);
FMemStream.SaveToFile(FileName);
finally
FreeMem(dest);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MemoWithUnicod := TMemoWithUnicod.Create(Self);
MemoWithUnicod.Parent := Self;
MemoWithUnicod.Left := 20;
MemoWithUnicod.Top := 20;
MemoWithUnicod.ScrollBars := ssVertical;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
MemoWithUnicod.LoadFromUnicodFile('MyUnicodFile.txt');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
MemoWithUnicod.SaveToUnicodFile('MyUnicodFile.txt');
end;

end.
 
S

slavas

#10
Нехило! Проверил, работает. Гораздо лучше, чем мои таблицы. При моём уровне развития такого я бы не смог сделать. Будем изучать, применять в работе. Спасибо. Вопрос закрыт.
 
Статус
Закрыто для дальнейших ответов.