Сохранение строк на диск в Delphi 2009.
-
05-07-2019 - |
Вопрос
У меня есть структура, подобная приведенной ниже, которую необходимо сохранить и загрузить с диска.
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);