2011-11-08 16 views
1

私はそれを独自のSaveToStreamメソッドでクラスとして宣言する必要がありますか?構造体をストリームに書き込む方法は?

(私は今ゲッターに&セッターを追加するかもしれませんが)それは

+2

[ファイルへの複雑なレコードの書き込み]の可能な重複(http://stackoverflow.com/questions/4533376/執筆 - 複合 - レコード - ファイル) –

答えて

4

は、あなたがこのような構造を記述するために、次の記録今

type 
    TMyRecord = record 
    FirstName: string[100]; // 100 characters max. for First name 
    LastName: string[100]; // 100 characters max. for Last name 
    Age: Byte; 
    DateOfBirth: TDateTime; 
    end; 
const 
    // if you are using Delphi 2009 and above, 
    // then either change *string[100]* to *AnsiString[100]* or use a different 
    // approach to save the string, read bellow 
    szMyRecord = SizeOf(TMyRecord); // storing it will make your code run faster if you write a lot of records 

を、持っていると仮定したデータのみ、無機能でありますストリームの場合は、次のようにする必要があります。

procedure WriteRecord(
    const ARecord: TMyRecord; 
    const AStream: TStream // can be a TMemoryStream, TFileStream, etc. 
); 
begin 
    AStream.Write(ARecord, szMyRecord); 
end; 

FirstNameを "stするために、

type 
    TMyRecordWithVeryLongStrings = record 
    LenFirstName: Integer; // we store only the length of the string in this field 
    LenLastName: Integer; // same as above 
    Age: Byte; 
    DateOfBirth: TDateTime; 
    FirstName: string; // we will ignore this field when writing, using it for value 
    LastName: string; // same as above 
    end; 

const 
    // we are ignoring the last two fields, since the data stored there is only a pointer, 
    // then we can safely assume that (SizeOf(string) * 2) is the offset 
    szMyRecordWithVeryLongStrings = SizeOf(TMyRecordWithVeryLongStrings) - (SizeOf(string) * 2); 

// the difference between this method and above is that we first write the record 
// and then the strings 
procedure WriteRecord(
    ARecord: TMyRecordWithVeryLongStrings; 
    AStream: TStream // can be a TMemoryStream, TFileStream, etc. 
); 
const szChar = sizeof(char); 
begin 
    // ensure the length of first and Last name are stored in "Len + Name" field 
    ARecord.LenFirstName := Length(ARecord.FirstName); 
    ARecoord.LenLastName := Length(ARecord.Lastname); 
    // write the record 
    AStream.Write(ARecord, szMyRecordWithVeryLongStrings); 
    // write First name value 
    AStream.Write(
    Pointer(ARecord.FirstName)^, // value of first name 
    szChar * ARecord.LenFirstName 
); 
    // repeat as above for last name 
    AStream.Write(
    Pointer(ARecord.LastName)^, // value of first name 
    szChar * ARecord.LenLastName 
); 
end; 

今:リング文字列[100] 『あるいは、例えば、文字列フィールドを記述するための特別なメソッドを使用して」姓の文字は保存されません、あなたは私が行ったように姓を宣言する必要があります』 「長い文字列」を読んで、あなたが最初のレコードの読み取り:私は(それが役に立てば幸い

procedure ReadRecord(
    ARecord: TMyRecordWithVeryLongStrings; 
    AStream: TStream 
); 
begin 
    AStream.Read(Arecord, szMyRecordWithVeryLongStrings); 
    // now read first and last name values which are right after the record in the stream 
    AStream.Read(Pointer(ARecord.FirstName)^, szChar * ARecord.LenFirstName); 
    AStream.Read(Pointer(ARecord.,LastrName)^, szChar * ARecord.LenLastName); 
end; 

を:

+0

+1とそのような包括的な例のおかげで!私はそれをコピー/ペーストしてテストし、私がそれを働かせたらあなたに答えを与えるでしょう。ありがとう!! – Mawg

+3

これは短い文字列(文字列[xx])でのみ機能することに注意してください。彼らはアンシだけです。他のすべての文字列はポインタであり、それらを書き込むためにはさらに多くの作業が必要です。 –

+0

Delphi 2009以降、ショートストリングは廃止されました。これは、IMHOはレコードを保存するための良い選択肢ではなく、スペースを浪費します。 –

8

http://code.google.com/p/kblib/ - あなたは(一定の大きさに文字列を制限する必要がこれを試していない、と複雑で動作することができレコード、1行でロード/セーブ)。

同様の質問:

+3

+1重複した質問が見つかりました。おそらくリスト[このOpenSourceユニット](http://blog.synopse.info/post/2011/03/12/TDynArray-and-Record-compare/load/save-using-fast-RTTI)に追加する価値がある - XE2までのDelphi 5で動作します。 –

+0

@Arnaud Bouchez - ありがとう、kblibのメインページへのリンクを追加しました:) – kibab

+1

+1 soem great links – Mawg

関連する問題