إنقاذ السلاسل إلى القرص تحت دلفي 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
ورمز أعلاه يعمل تحت دلفي 7. تحت D2009 حصلت على الكثير من رسائل التحذير عندما كنت جعل المهام بين سلاسل قصيرة ويونيكود. حتى الآن تمكنت من كتابة التعليمات البرمجية دلفي دون أي تحذيرات مترجم أو تلميحات وأريد أن أبقى من هذا القبيل. لذلك أنا بحاجة كانت أنيقة لحفظ سلاسل (لن يونيكود تكون كبيرة ولكن لا حرج) إلى القرص دون الحصول على التحذيرات.
المحلول
وبدلا من ذلك، يمكن أن تقوم بتعريف القابل للتخزين سجل سلسلة قصيرة يونيكود وتنفيذ ضمني "لسلسلة" و "من سلسلة" التحويلات.
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.
[يتم تحرير التعليمات البرمجية أعلاه إلى المجال العام، ويحمل أي التزامات الترخيص.]
نصائح أخرى
وهذه حقول السلسلة هي نفسها في دلفي 2009 كما كانت في كل الإصدارات السابقة. ShortString
ليس نوع يونيكود.
وهكذا يجب أن تكون قادرة على الاستمرار في استخدام هذا السجل كما هو.
وأنت تقول أنها عملت في دلفي 7. هل هو لا م> العمل في دلفي 2009؟ وصف المشكلة التي واجهتك.
هل تقصد أن أقول إن كنت ترغب في يونيكود يعادل طول ثابت إلى ShortString
؟ ليس هناك واحد، لذلك لا يمكن أن يكون لها سجل من هذا القبيل، وأنه عقد القيم يونيكود مثل سلسلة، وحفظه مباشرة إلى القرص.
وأنا لا أعتقد أن هذا يمثل مشكلة كبيرة، على الرغم من حيث أن شكل القرص لا تكون متوافقة مع الشكل الحالي على أي حال: أن شخصياتك تكون كبيرة جدا
ويمكنك استخدام مجموعة من الشخصيات:
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);