问题描述
我想这会看起来像'的做我的功课的之类的问题,但我仍然在'的复制code,使用它,并尝试去了解它的'阶段,这是最积极的事情,我知道张贴这一主题的问题。
我有一个记录:
键入
卡=记录
名称:字符串;
上,右,左,下,马克:单;
IDNumber中:整数;
结束;
和该记录的数组:
VAR
ArrayCard:卡的阵列;
和我想知道如何能这样的一个动态数组被存储/从文件加载到/。
使用这块code的尝试:的
像这样的:
程序TMainFrom.WriteMyData; 瓦尔
FS:TFileStream的;
我,iSize:整数;
TmpPath:字符串; 开始
TmpPath:= TPath.Combine(TPath.GetDocumentsPath,'Cards.dat');
FS:= TFileStream.Create(TmpPath,fmOpenWrite);
iSize:=长度(ArrayCard);
FS.WriteBuffer(iSize,一下SizeOf(iSize));
因为我:= 0〜iSize - 1待办事项
FS.WriteBuffer(ArrayCard [I]中,一下SizeOf(卡));
FS.Free;
结束;
这是它似乎工作至今,但后来我尝试加载它是这样的:
程序TMainFrom.ReadMyData; 瓦尔
FS:TFileStream的;
我,iSize:整数;
TmpPath:字符串;
TempCard:卡; 开始
TmpPath:= TPath.Combine(TPath.GetDocumentsPath,'Cards.dat');
FS:= TFileStream.Create(TmpPath,fmOpenRead);
FS.ReadBuffer(iSize,一下SizeOf(iSize));
SetLength函数(ArrayCard,iSize);
因为我:= 0〜iSize - 1待办事项
开始
FS.ReadBuffer(TempCard,一下SizeOf(卡));
ArrayCard [I]:= TempCard; //它打破了这里...... [观察清单:TempCard价值无法访问
结束;
FS.Free;
结束;
和我得到了模块异常EAccessViolation ...
然后我也尝试过这样的事情:德尔福保存和载入动态数组
它加载的项目的正确数量的数组,但它们都是空的或空白:
程序TMainFrom.SaveCardsToFile;
VAR
流:TStream;
L:整数;
TmpPath:字符串;
ICOUNT:整数;
STRM:内存流;开始
TmpPath:= TPath.Combine(TPath.GetDocumentsPath,'Cards.bin'); 流:= TFileStream.Create(TmpPath,fmCreate);
L:=长度(ArrayCard);
Stream.WriteBuffer(L,一下SizeOf(L));
Stream.WriteBuffer(指针(ArrayCard)^,L *一下SizeOf(卡));
Stream.Free;
结束;程序TMainFrom.LoadCardsFromFile;
VAR
流:TStream;
L:长字;
TmpPath:字符串;开始
TmpPath:= TPath.Combine(TPath.GetDocumentsPath,'Cards.bin'); 流:= TFileStream.Create(TmpPath,fmOpenRead);
Stream.ReadBuffer(L,一下SizeOf(L));
SetLength函数(ArrayCard,L);
Stream.ReadBuffer(指针(ArrayCard)^,L *一下SizeOf(卡));
Stream.Free;
结束;
不要使用包含正常的字符串记录缓冲区操作。相反 ShortString短
,字符串
是唯一的指向字符串内容。所以,你的code保存和加载唯一的指向字符串的内容,而不是字符串。如果装载值指向不可访问内存即可获得访问冲突。
更改code分开保存和记录加载变量,像这样的:
类型
TmyRec =记录
STR:字符串;
我:整数;
程序SaveToStream(流:TStream);
程序LoadFromStream(流:TStream);
结束;{} myRec程序TmyRec.LoadFromStream(流:TStream);
VAR
STRLEN:整数;
STRBUF:TB的;
开始
Stream.Read(STRLEN,一下SizeOf(整数));
SetLength函数(STRBUF,strlen的);
Stream.Read(STRBUF,strlen的); STR:= TEncoding.UTF8.GetString(STRBUF); Stream.Read(我,一下SizeOf(整数));
结束;程序TmyRec.SaveToStream(流:TStream);
VAR
STRBUF:TB的;
STRLEN:整数;
开始
//直集编码类型有助于避免不同平台的问题。
//例如,Windows使用UCS2,Android和iOS - UTF8编码
STRBUF:= TEncoding.UTF8.GetBytes(STR);
STRLEN:=长度(STRBUF); Stream.Write(STRLEN,一下SizeOf(整数));
Stream.Write(STRBUF,strlen的);
Stream.Write(我,一下SizeOf(整数));
结束;
更新:
你了解泛型?相反,动态数组,你可以使用从TList并加载/保存记录的:
类型
TmyRecList =等级(从TList< TmyRec>)
上市
程序SaveToStream(流:TStream);
程序LoadFromStream(流:TStream);
结束;{} TmyRecList程序TmyRecList.LoadFromStream(流:TStream);
VAR
莱恩:整数;
我:整数;
REC:TmyRec;
开始
明确; Stream.Read(LEN,一下SizeOf(整数)); 对于i:= 0至莱恩-1做
开始
Rec.LoadFromStream(流);
添加(REC);
结束;
结束;程序TmyRecList.SaveToStream(流:TStream);
VAR
我:整数;
开始
Stream.Write(计数,一下SizeOf(整数));
对于i:= 0开始计数1做
项目[I] .SaveToStream(流);
结束;程序THeaderFooterForm.FormCreate(发件人:TObject的);
VAR
流:TStream;
REC:TmyRec;
recList:TmyRecList;
开始
流:= TMemoryStream.Create;
尝试
recList:= TmyRecList.Create;
尝试
rec.str:='示范文本;
rec.i:= 123;
recList.Add(REC); rec.str:='其他文本';
rec.i:= 234;
recList.Add(REC); recList.SaveToStream(流);
Stream.Seek(0,soBeginning); recList.LoadFromStream(流);
ShowMessage('这是第二个记录STR值:'+ recList [1]名为.str);
最后
recList.Free;
结束;
最后
Stream.Free;
结束;
I think this will look like 'do my homework' kind of a question, but I'm still at the 'copy code, use it and try to understand it' phase, and this is the most active thing I know of for posting questions of this theme.
I have a record:
type
Card = record
Name: string;
Up,Right,Left,Down,Mark: Single;
IDNumber: Integer;
end;
And array of that record:
var
ArrayCard: array of Card;
And I wanted to know how can a dynamic array of this kind be stored/loaded to/from a file.
Tried using this piece of code: http://www.pascalgamedevelopment.com/showthread.php?6319-save-load-a-dynamic-arraylike this:
Procedure TMainFrom.WriteMyData;
Var
FS : TFileStream;
I,iSize : Integer;
TmpPath: string;
Begin
TmpPath:= TPath.Combine(TPath.GetDocumentsPath, 'Cards.dat');
FS := TFileStream.Create(TmpPath, fmOpenWrite);
iSize:= Length(ArrayCard);
FS.WriteBuffer(iSize,SizeOf(iSize));
For I := 0 To iSize - 1 Do
FS.WriteBuffer(ArrayCard[I],SizeOf(Card));
FS.Free;
End;
An it seems to work so far, but then I try to load it like this:
Procedure TMainFrom.ReadMyData;
Var
FS : TFileStream;
I,iSize : Integer;
TmpPath: string;
TempCard : Card;
Begin
TmpPath:= TPath.Combine(TPath.GetDocumentsPath, 'Cards.dat');
FS := TFileStream.Create(TmpPath, fmOpenRead);
FS.ReadBuffer(iSize,SizeOf(iSize));
SetLength(ArrayCard,iSize);
For I := 0 To iSize - 1 Do
Begin
FS.ReadBuffer(TempCard,SizeOf(Card));
ArrayCard[I] := TempCard; //It Breaks Here...The Watch List: TempCard Inaccessible value
End;
FS.Free;
End;
And I get a Exception EAccessViolation in module...
Then I also tried something like this: delphi Save and Load dynamic arrayIt loads the array with the correct amount of items, but they are all empty or blank:
procedure TMainFrom.SaveCardsToFile;
var
Stream: TStream;
L: Integer;
TmpPath: string;
ICount: Integer;
strm: TMemoryStream;
begin
TmpPath:= TPath.Combine(TPath.GetDocumentsPath, 'Cards.bin');
Stream:= TFileStream.Create(TmpPath, fmCreate);
L:= Length(ArrayCard);
Stream.WriteBuffer(L, SizeOf(L));
Stream.WriteBuffer(Pointer(ArrayCard)^, L * SizeOf(Card));
Stream.Free;
end;
procedure TMainFrom.LoadCardsFromFile;
var
Stream: TStream;
L: LongWord;
TmpPath: string;
begin
TmpPath:= TPath.Combine(TPath.GetDocumentsPath, 'Cards.bin');
Stream:= TFileStream.Create(TmpPath, fmOpenRead);
Stream.ReadBuffer(L, SizeOf(L));
SetLength(ArrayCard, L);
Stream.ReadBuffer(Pointer(ArrayCard)^, L * SizeOf(Card));
Stream.Free;
end;
Do not use buffer operations with records which contains "normal" strings. Instead of shortstring
, string
is only pointer to string content. So, your code saves and loads only pointer to string content, not string. You can get Access Violation if loaded value points to unreachable memory.Change your code to separately save and load variables in record, like this:
type
TmyRec = record
str: string;
i: integer;
procedure SaveToStream(Stream: TStream);
procedure LoadFromStream(Stream: TStream);
end;
{ myRec }
procedure TmyRec.LoadFromStream(Stream: TStream);
var
strLen: integer;
strBuf: TBytes;
begin
Stream.Read(strLen, SizeOf(Integer));
SetLength(strBuf, strLen);
Stream.Read(strBuf, strLen);
str:=TEncoding.UTF8.GetString(strBuf);
Stream.Read(i, SizeOf(Integer));
end;
procedure TmyRec.SaveToStream(Stream: TStream);
var
strBuf: TBytes;
strLen: integer;
begin
// direct set encoding type helps to avoid problems with different platforms.
// for example, Windows uses UCS2, Android and iOS - UTF8 encoding
strBuf:=TEncoding.UTF8.GetBytes(str);
strLen:=Length(strBuf);
Stream.Write(strLen, SizeOf(Integer));
Stream.Write(strBuf, strLen);
Stream.Write(i, SizeOf(Integer));
end;
Update:do you read about generics? Instead of dynamic array, you can use TList and load/save records in it:
type
TmyRecList = class(TList<TmyRec>)
public
procedure SaveToStream(Stream: TStream);
procedure LoadFromStream(Stream: TStream);
end;
{ TmyRecList }
procedure TmyRecList.LoadFromStream(Stream: TStream);
var
Len: integer;
i: Integer;
rec: TmyRec;
begin
Clear;
Stream.Read(Len, SizeOf(integer));
for i := 0 to Len-1 do
begin
Rec.LoadFromStream(Stream);
Add(rec);
end;
end;
procedure TmyRecList.SaveToStream(Stream: TStream);
var
i: Integer;
begin
Stream.Write(Count, SizeOf(Integer));
for i := 0 to Count-1 do
Items[i].SaveToStream(Stream);
end;
procedure THeaderFooterForm.FormCreate(Sender: TObject);
var
Stream: TStream;
rec: TmyRec;
recList: TmyRecList;
begin
Stream:=TMemoryStream.Create;
try
recList:=TmyRecList.Create;
try
rec.str:='sample text';
rec.i:=123;
recList.Add(rec);
rec.str:='another text';
rec.i:=234;
recList.Add(rec);
recList.SaveToStream(Stream);
Stream.Seek(0, soBeginning);
recList.LoadFromStream(Stream);
ShowMessage('this is str value in second record: ' + recList[1].str);
finally
recList.Free;
end;
finally
Stream.Free;
end;
这篇关于德尔福保存/载入动态数组失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!