Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Unicode
Форум программистов > Системное программирование > Delphi и Pascal > Delphi - FAQ
slavas
Мне нужно отредактировать в TMemo текстовый файл (он в формате Unicode). Каким образом мне его загрузить в Memo?
Просто командой Memo1.Lines.LoadFromFile() отображается что-то непонятное. А потом его ещё и сохранить так чтобы он остался в Unicode?
Пожалуйста работающий примерчик. У меня Дельфи 7
-----
Два дня прошло - ответов нет. Неужто сложный вопрос? Ладно.
Вот что я нашел в моих поисках:
Цитата
UTF-8 и Unicode это немного разные вещи. Доказательством тому служит то, что в Delphi есть функции UTF8ToUnicode и UnicodeToUTF8. smile.gif
Загружать и сохранять файлы с 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. У меня не получается.
Все время какая то проблема с несовместимыми типами.
slavas
Ну и что мне делать? Кто нибудь знает ответ на этот вопрос? Для чего тогда функции WideCharToStrVar, OleStrToStrVar с текстовыми переменными с широкой строкой, если я попросту не могу эти переменные заполнить? Помогите.
etc
Либо используйте компоненты которые поддерживают юникод, либо надо установить соотв. чарсет контролам, либо конвертировать с пом. спец функций
вот их тут есть: AnsiToUtf8, PUCS4Chars, StringToWideChar, UCS4StringToWideString, UnicodeToUtf8, UTF8Decode, UTF8Encode, Utf8ToAnsi, Utf8ToUnicode, WideCharLenToString, WideCharLenToStrVar, WideCharLenToStrVar, WideCharToString, WideCharToStrVar, WideStringToUCS4String ..
slavas
Цитата
либо конвертировать с пом. спец функций
вот их тут есть: AnsiToUtf8, PUCS4Chars, StringToWideChar, ......

Так как раз в этом и проблема! Функции известны, а воспользоваться ими не могу. Попросту текст не могу взять из файла!
Не забываем, что он там в Юникоде (не UTF8). Кстати такой файл можно создать и сохранить в Блокноте, выбрав там Юникод.
А компоненты, поддерживающие Юникод, надо специально искать? или они есть в стандартном Дельфи 7?
slavas
Искал и в Гугде и в Яндексе, еще до вопроса в форуме, и сейчас посмотрел, ничего там в интернете не изменилось. ответа на мой вопрос нет. Повторюсь. Как загрузить из файла текст(букву) (Юникод UTF16) в переменную типа PWideChar? Похоже, только с этим типом работают нужные мне функции преобразования.
etc
Вторая ссылка из пред. поста ведет на компоненты, поддерживающие юникод.
slavas
15 мегов, да... С моей то сотовой связью. Если что нибудь не придумаю, буду качать. Хотелось попроще. Я уже так много знаю об этом Юникоде, что уже в теории могу сам перекодировщик написать. Взять текст как file of byte; первую пару выкидываем-это признак Юникода, далее каждой паре байт соответствует свой символ. Единственный недостаток это составлять для всех символов однозначное соответствие. Большой объем кода получается. Может кто написал проще, без этой таблицы? Пишите.
Спасибо за ответы, Вы дали мне направление, как можно решить эту проблему.
zubr
Код
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.
slavas
Нехило! Проверил, работает. Гораздо лучше, чем мои таблицы. При моём уровне развития такого я бы не смог сделать. Будем изучать, применять в работе. Спасибо. Вопрос закрыт.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Русская версия IP.Board © 2001-2008 IPS, Inc.