Вопрос

У меня есть структура, подобная приведенной ниже, которую необходимо сохранить и загрузить с диска.

 RSecStructure= packed record
   Name               : string[255];       {NEED UNICODE SUPPORT HERE}
   ScreenName         : string[255];
   OrigFileName       : string[255];                    
   Prim               : string[255];                                           
   ParentVersion      : integer;
   sTag1              : string[255];      
   sTag2              : string[255];
   sTag3              : string[255];
   sTag4              : string[255];
   DateAdd            : TDateTime;
   DateModify         : TDateTime;
  end;

До сих пор я использовал что-то вроде этого для сохранения структуры:

function
var F: FILE;
    Hdr: RSecStructure;
begin
...
 BlockWrite (F, Hdr, SizeOf(Hdr));   
...
end

Приведенный выше код работал в Delphi 7.В D2009 я получал много предупреждающих сообщений, когда делал назначения между короткими строками и строками в Юникоде.До сих пор мне удавалось писать код Delphi без каких-либо предупреждений или подсказок компилятора, и я хочу оставаться таким.Поэтому мне нужен элегантный способ сохранять строки (Юникод подойдет, но не критично) на диск без предупреждений.

Это было полезно?

Решение

Кроме того, вы можете объявить сохраняемую короткую строковую запись в юникоде и реализовать неявные преобразования «в строку» и «из строки».

program TestShortUnicodeString;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TShortUnicodeString = record
  private
    Data: array [0..255] of char; //WARNING - NOT initialized to an empty string
  public
    class operator Implicit(const sus: TShortUnicodeString): string; inline;
    class operator Implicit(const ws: string): TShortUnicodeString; inline;
  end;

class operator TShortUnicodeString.Implicit(const sus: TShortUnicodeString): string;
begin
  Result := StrPas(sus.Data);
end;

class operator TShortUnicodeString.Implicit(const ws: string): TShortUnicodeString;
begin
  // too long strings are silently truncated
  StrPLCopy(Result.Data, ws, Length(Result.Data)-1);
end;

type
  TTestRec = record
    ws1: TShortUnicodeString;
    ws2: TShortUnicodeString;
  end;

var
  f    : file;
  test1: TTestRec;
  test2: TTestRec;

begin
  test1.ws1 := '6*9 =';
  test1.ws2 := ' 42';
  AssignFile(f, 'test.dat');
  Rewrite(f, 1);
  BlockWrite(f, test1, SizeOf(test1));
  CloseFile(f);
  AssignFile(f, 'test.dat');
  Reset(f, 1);
  Assert(FileSize(f) = SizeOf(test2));
  BlockRead(f, test2, SizeOf(test2));
  CloseFile(f);
  Writeln(string(test2.ws1), string(test2.ws2));
  Readln;
end.

[Приведенный выше код является общедоступным и не имеет лицензионных обязательств.]

Другие советы

Эти строковые поля в Delphi 2009 такие же, как и во всех предыдущих версиях. ShortString не является типом Юникода.

Таким образом, вы сможете продолжать использовать эту запись как есть.

Вы говорите, что это сработало в Delphi 7.Имеет ли это нет работаешь в Делфи 2009?Опишите проблему, с которой вы столкнулись.

Вы хотите сказать, что вам нужен Unicode фиксированной длины, эквивалентный ShortString?Его нет, поэтому вы не можете иметь такую ​​запись, хранить в ней строковые значения Unicode и сохранять ее непосредственно на диск.

Однако я не думаю, что это серьезная проблема, поскольку формат вашего диска в любом случае не будет совместим с вашим текущим форматом:ваши персонажи были бы слишком большими.

Вы можете использовать массив символов:

type
  TSecStructure = packed record
    Name               : array[0..255] of UnicodeChar;
    ScreenName         : array[0..255] of UnicodeChar;
    OrigFileName       : array[0..255] of UnicodeChar;
    Prim               : array[0..255] of UnicodeChar;
    ParentVersion      : integer;
    sTag1              : array[0..255] of UnicodeChar;
    sTag2              : array[0..255] of UnicodeChar;
    sTag3              : array[0..255] of UnicodeChar;
    sTag4              : array[0..255] of UnicodeChar;
    DateAdd            : TDateTime;
    DateModify         : TDateTime;
  end;

Это будет не так удобно, как реальные строковые типы, но для большинства целей подойдет.

Вы также можете использовать обычный UnicodeString тип:

type
  TSecStructure = record
    Name               : UnicodeString;
    ScreenName         : UnicodeString;
    OrigFileName       : UnicodeString;
    Prim               : UnicodeString;
    ParentVersion      : integer;
    sTag1              : UnicodeString;
    sTag2              : UnicodeString;
    sTag3              : UnicodeString;
    sTag4              : UnicodeString;
    DateAdd            : TDateTime;
    DateModify         : TDateTime;
  end;

Вы больше не можете сохранить это непосредственно на диск, но вы также больше не ограничены 255 символами.Вам придется хранить каждое строковое поле отдельно.Обязательно сохраните также длину строки, иначе вы не будете знать, где заканчивается одна строка и начинается следующая, когда придет время загрузить файл позже.

Вы можете сохранить существующую структуру (строка [255]), существующий формат файла и даже правильно читать данные, не записанные в Юникоде, ранее сохраненные с помощью следующего:

перед записью данных:

...
record.Name:= UTF8EncodeToShortString(Name);

после прочтения данных:

...
Name:= UTF8ToString(record.Name);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top