سؤال

ولدي هيكل مثل أدناه التي يحتاجها ليتم حفظها وتحميلها من القرص.

 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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top