請問如何使用MemorySteam將內含動態陣列的結構存檔再讀出? |
答題得分者是:jow
|
dky
一般會員 ![]() ![]() 發表:12 回覆:30 積分:13 註冊:2004-06-24 發送簡訊給我 |
程式碼如下
遇到的問題是當讀出時, 動態陣列大小為0 如果將test2.xAry 一樣設定為100, 讀出後,一樣歸0 [code delphi] type _test = record a, b, c, d :Integer; xAry :array of Boolean; end; var test1, test2 :_test procedure FormCreate(Sender: TObject); begin SetLength(test1.xAry, 100); end; procedure Button1Click(Sender: TObject); var pmem :TMemoryStream; begin pmem := TMemoryStream.Create; pmem.Size := SizeOf(test1); pmem.Position := 0; pmem.Write(test1, pmem.Size); pmem.SaveToFile('C:\1.dat'); FreeAndNil(pmem); end; procedure Button1Click(Sender: TObject); var pmem :TMemoryStream; begin pmem := TMemoryStream.Create; pmem.LoadFromFile('C:\1.dat'); pmem.Position := 0; pmem.Read(test2, pmem.Size); FreeAndNil(pMem); end; [/code] 編輯記錄
dky 重新編輯於 2008-07-01 16:45:20, 註解 無‧
|
jow
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
隨手寫些測試碼,提供你參考...
![]() [code delphi] unit fMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type p_test = ^_test; _test = record a, b, c, d :Integer; e: Char; xAry :array of Boolean; end; p_test_packed = ^_test_packed; _test_packed = packed record a, b, c, d :Integer; e: Char; xAry :array of Boolean; end; TForm1 = class(TForm) Button1: TButton; Button2: TButton; ListBox1: TListBox; Button3: TButton; Button4: TButton; Button5: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); private public end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var A: _test; begin //比較 record 與 packed record 的差異 ShowMessage('SizeOf(_test)=' IntToStr(SizeOf(_test))); ShowMessage('SizeOf(_test_packed)=' IntToStr(SizeOf(_test_packed))); ShowMessage('SizeOf(A.xAry)=' IntToStr(SizeOf(A.xAry))); SetLength(A.xAry, 100); try ShowMessage('LengthOf(A.xAry)=' IntToStr(Length(A.xAry))); ShowMessage('SizeOf(A.xAry[])=' IntToStr(SizeOf(Boolean)*Length(A.xAry))); finally A.xAry := nil; end; end; procedure TForm1.Button2Click(Sender: TObject); var I: Integer; A, B: _test; L: TStringList; begin //alignment: use for-loop SetLength(A.xAry, 100); try for I := 0 to Length(A.xAry)-1 do A.xAry[I] := Boolean(I mod 2); SetLength(B.xAry, 100); try for I := 0 to Length(A.xAry)-1 do B.xAry[I] := A.xAry[I]; //Show Result L := TStringList.Create; try for I := 0 to Length(B.xAry)-1 do if B.xAry[I] then L.Add(Format('%d: TRUE', [I])) else L.Add(Format('%d: FALSE', [I])); ListBox1.Items.Text := L.Text; finally FreeAndNil(L); end; finally B.xAry := nil; end; finally A.xAry := nil; end; end; procedure TForm1.Button3Click(Sender: TObject); var I, Size: Integer; A, B: _test; L: TStringList; begin //alignment: memory move SetLength(A.xAry, 100); try for I := 0 to Length(A.xAry)-1 do A.xAry[I] := Boolean(I mod 2); Size := SizeOf(Boolean) * Length(A.xAry); SetLength(B.xAry, 100); try //alignment: memory move Move(Pointer(A.xAry)^, Pointer(B.xAry)^, Size); //Show Result L := TStringList.Create; try for I := 0 to Length(B.xAry)-1 do if B.xAry[I] then L.Add(Format('%d: TRUE', [I])) else L.Add(Format('%d: FALSE', [I])); ListBox1.Items.Text := L.Text; finally FreeAndNil(L); end; finally B.xAry := nil; end; finally A.xAry := nil; end; end; procedure TForm1.Button4Click(Sender: TObject); var pBool: ^Boolean; I, Size, Len, Len2: Integer; A: _test; L: TStringList; M: TMemoryStream; begin //write to file M := TMemoryStream.Create; try SetLength(A.xAry, 100); try Size := SizeOf(Boolean) * Length(A.xAry); for I := 0 to Length(A.xAry)-1 do A.xAry[I] := Boolean(I mod 2); M.Write(Pointer(A.xAry)^, Size); M.SaveToFile('1.DAT'); finally A.xAry := nil; end; finally FreeAndNil(M); end; //Show Result use TMemoryStream if FileExists('1.DAT') then begin M := TMemoryStream.Create; try M.LoadFromFile('1.DAT'); pBool := M.Memory; L := TStringList.Create; try Len := M.Size div SizeOf(Boolean); Len2 := Len; while (pBool <> nil) and (Len > 0) do begin if pBool^ then L.Add(Format('%d: TRUE', [Len2-Len])) else L.Add(Format('%d: FALSE', [Len2-Len])); Inc(pBool); Dec(Len); end; ListBox1.Items.Text := L.Text; finally FreeAndNil(L); end; finally FreeAndNil(M); end; end; end; procedure TForm1.Button5Click(Sender: TObject); var I, Size: Integer; A, B: _test; L: TStringList; M: TMemoryStream; begin //write to file M := TMemoryStream.Create; try SetLength(A.xAry, 100); try Size := SizeOf(Boolean) * Length(A.xAry); for I := 0 to Length(A.xAry)-1 do A.xAry[I] := Boolean(I mod 2); M.Write(Pointer(A.xAry)^, Size); M.SaveToFile('1.DAT'); finally A.xAry := nil; end; finally FreeAndNil(M); end; if FileExists('1.DAT') then begin SetLength(B.xAry, 100); try Size := SizeOf(Boolean) * Length(B.xAry); M := TMemoryStream.Create; try M.LoadFromFile('1.DAT'); M.Read(Pointer(B.xAry)^, Size); finally FreeAndNil(M); end; //Show Result L := TStringList.Create; try for I := 0 to Length(B.xAry)-1 do if B.xAry[I] then L.Add(Format('%d: TRUE', [I])) else L.Add(Format('%d: FALSE', [I])); ListBox1.Items.Text := L.Text; finally FreeAndNil(L); end; finally B.xAry := nil; end; end; end; end. [/code] |
dky
一般會員 ![]() ![]() 發表:12 回覆:30 積分:13 註冊:2004-06-24 發送簡訊給我 |
感謝您的回覆
![]() 我找到問題點了, 動態Array的部份,要另外write到MemoryStream裡,不過當我把array of Boolean 改成 array Of String 時, 可以正確的把資料抓出,但是在把array 內容顯示出來時,都會出現錯誤"Invalid pointer operation" 在delphi 裡,是可以看到資料有進入到array裡, 程式碼如下 [code delphi] p_xt = ^_xt; _xt = record a, b :Integer; xAry :array of String; c :String; end; procedure TfMain.Button6Click(Sender: TObject); var i, Size: Integer; at, bt: _xt; pMem: TMemoryStream; begin Listbox2.Clear; Listbox3.Clear; Edit4.Text := ''; Edit5.Text := ''; Edit6.Text := ''; at.a := StrToInt(Edit1.Text); at.b := StrToInt(Edit2.Text); at.c := Edit3.Text; pMem := TMemoryStream.Create; try SetLength(at.xAry, 100); try for i := 0 to Length(at.xAry) -1 do begin at.xAry[i] := IntToStr(GetTickCount) '@' IntToStr(i); Listbox2.AddItem(at.xAry[i], nil); end; Size := SizeOf(String) *Length(at.xAry); pMem.Write(at, SizeOf(at)); pMem.Write(Pointer(at.xAry)^, Size); pMem.SaveToFile('C:\1.DAT'); finally at.xAry := nil; end; finally FreeAndNil(pMem); end; if FileExists('C:\1.DAT') then begin try pMem := TMemoryStream.Create; try pMem.LoadFromFile('C:\1.DAT'); pMem.Position := 0; pMem.Read(bt, SizeOf(bt)); Size := SizeOf(String) *Length(bt.xAry); pMem.Read(Pointer(bt.xAry)^, Size); for i := 0 to Length(bt.xAry) -1 do begin Listbox3.AddItem(bt.xAry[i], nil); end; Edit4.Text := IntToStr(bt.a); Edit5.Text := IntToStr(bt.b); Edit6.Text := bt.c; finally FreeAndNil(pMem); end; finally bt.xAry := nil; end; end; end; [/code] 感謝 m(_ _)m |
jow
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
|
dky
一般會員 ![]() ![]() 發表:12 回覆:30 積分:13 註冊:2004-06-24 發送簡訊給我 |
搞定了
![]() [code delphi] p_xt = ^_xt; _xt = record a, b :Integer; xAry :array of ShortString; c :ShortString; end; procedure TfMain.Button6Click(Sender: TObject); var i, Size, tmp: Word; at, bt: _xt; pMem: TMemoryStream; begin Listbox2.Clear; Listbox3.Clear; Edit4.Text := ''; Edit5.Text := ''; Edit6.Text := ''; at.a := StrToInt(Edit1.Text); at.b := StrToInt(Edit2.Text); at.c := Edit3.Text; pMem := TMemoryStream.Create; try SetLength(at.xAry, 100); try for i := 0 to Length(at.xAry) -1 do begin at.xAry[i] := IntToStr(GetTickCount) '@' IntToStr(i); Listbox2.AddItem(at.xAry[i], nil); end; Size := SizeOf(ShortString) *Length(at.xAry); tmp := Length(at.xAry); pMem.Write(at, SizeOf(at)); pMem.Write(tmp, SizeOf(Word)); pMem.Write(Pointer(at.xAry)^, Size); pMem.SaveToFile('C:\1.DAT'); finally at.xAry := nil; end; finally FreeAndNil(pMem); end; if FileExists('C:\1.DAT') then begin try pMem := TMemoryStream.Create; tmp := 0; try pMem.LoadFromFile('C:\1.DAT'); pMem.Position := 0; pMem.Read(bt, SizeOf(bt)); pMem.Read(tmp, SizeOf(Word)); Size := SizeOf(ShortString) *tmp; SetLength(bt.xAry, tmp); pMem.Read(Pointer(bt.xAry)^, Size); for i := 0 to Length(bt.xAry) -1 do begin Listbox3.AddItem(bt.xAry[i], nil); end; Edit4.Text := IntToStr(bt.a); Edit5.Text := IntToStr(bt.b); Edit6.Text := bt.c; finally FreeAndNil(pMem); end; finally bt.xAry := nil; end; end; end; [/code] |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |