目的:
将Form中若干数据表(TStringGrid)中的数据,存储到一个类型的数据文件中。表中的数据是动态的,具体根据每次的输入情况而定。
当存储完成之后,通过Open可以将该文件的数据重新回填到数据表格中。
我的思路:
1、针对每一个表格,建立一个对应的Record类型,其中有:记录每个StringGrid中已有数据的数目N,和,存放数据的动态数组。
2、然后,将所有的表格放到一个大的Record类型中。
3、利用FileStream输出数据,到文件中。
结果:
一直失败!!!
并提示:Access violation at address 00404548 in module "11.exe". Write of address 00000000.
在论坛上我查看了所有的相关帖子,仍然没有解决,故请各位大侠指教。附源代码如下:
unit DataRec;interface
uses Classes, sysutils,Grids, StdCtrls, ExtCtrls, ComCtrls;type TARec = packed Record //针对第一个表格定义的Record类型
N_A: integer;
Text_A: array of array[0..4] of string;
end; TBRec = packed Record //针对第二个表格定义的Record类型
N_B: integer;
Text_B: array of array [0..3] of string;
end; TCRec = packed Record //针对第三个表格定义的Record类型
N_C: integer;
Text_C: array of array [0..9] of string;
end; TDataRec = packed Record //综合上述三个表格定义的涵盖全部数据的Record类型
Data_A: TARec;
Data_B: TBRec;
Data_C: TCRec;
Data_D: array [0..4] of string; //第四个表格的数据
end;procedure DataSave(FileName:string;S_A,S_B,S_C,S_D:TStringGrid;A,B,C,D:integer);
implementation
var
DataRecord: TDataRec;
DataStream: TFileStream;
//定义关于数据存储的过程
procedure DataSave(FileName:string;S_A,S_B,S_C,S_D:TStringGrid;A,B,C,D:integer);
var
i,j:integer;
begin
with DataRecord do
begin
for i:=0 to 4 do //获取第四个表格的数据,该表格数据数量固定。
Data_D[i]:=S_D.Cells[i,1]; with Data_A do //获取第1个表格的数据。
begin
N_A:= A;
Setlength(Text_A,N_A*4); //为数组分配空间
for i:=0 to N_A-1 do
for j:=0 to 3 do
Text_A[j,i]:=S_A.Cells[j+1,i+1];
end; with Data_B do
begin
N_B:= B;
Setlength(Text_B,N_B*5);
for i:=0 to N_B-1 do
for j:=0 to 4 do
Text_B[j,i]:=S_B.Cells[j+1,i+1];
end; with Data_C do
begin
N_C:= C;
Setlength(Text_C,N_C*10);
for i:=0 to N_C-1 do
for j:=0 to 9 do
Text_C[j,i]:=S_C.Cells[j+1,i+1];
end; end; DataStream:=TFileStream.Create(FileName,fmCreate); //建立数据流文件
try
DataStream.Write(DataRecord,SizeOf(TDataRec)); //实现数据流文件的写入
finally
DataStream.Free;
end;end;
end.然后,在SaveDialog1中调用,该过程!
请各位大虾发表意见!!或者提供别的更好的思路!
先谢过各位了!
将Form中若干数据表(TStringGrid)中的数据,存储到一个类型的数据文件中。表中的数据是动态的,具体根据每次的输入情况而定。
当存储完成之后,通过Open可以将该文件的数据重新回填到数据表格中。
我的思路:
1、针对每一个表格,建立一个对应的Record类型,其中有:记录每个StringGrid中已有数据的数目N,和,存放数据的动态数组。
2、然后,将所有的表格放到一个大的Record类型中。
3、利用FileStream输出数据,到文件中。
结果:
一直失败!!!
并提示:Access violation at address 00404548 in module "11.exe". Write of address 00000000.
在论坛上我查看了所有的相关帖子,仍然没有解决,故请各位大侠指教。附源代码如下:
unit DataRec;interface
uses Classes, sysutils,Grids, StdCtrls, ExtCtrls, ComCtrls;type TARec = packed Record //针对第一个表格定义的Record类型
N_A: integer;
Text_A: array of array[0..4] of string;
end; TBRec = packed Record //针对第二个表格定义的Record类型
N_B: integer;
Text_B: array of array [0..3] of string;
end; TCRec = packed Record //针对第三个表格定义的Record类型
N_C: integer;
Text_C: array of array [0..9] of string;
end; TDataRec = packed Record //综合上述三个表格定义的涵盖全部数据的Record类型
Data_A: TARec;
Data_B: TBRec;
Data_C: TCRec;
Data_D: array [0..4] of string; //第四个表格的数据
end;procedure DataSave(FileName:string;S_A,S_B,S_C,S_D:TStringGrid;A,B,C,D:integer);
implementation
var
DataRecord: TDataRec;
DataStream: TFileStream;
//定义关于数据存储的过程
procedure DataSave(FileName:string;S_A,S_B,S_C,S_D:TStringGrid;A,B,C,D:integer);
var
i,j:integer;
begin
with DataRecord do
begin
for i:=0 to 4 do //获取第四个表格的数据,该表格数据数量固定。
Data_D[i]:=S_D.Cells[i,1]; with Data_A do //获取第1个表格的数据。
begin
N_A:= A;
Setlength(Text_A,N_A*4); //为数组分配空间
for i:=0 to N_A-1 do
for j:=0 to 3 do
Text_A[j,i]:=S_A.Cells[j+1,i+1];
end; with Data_B do
begin
N_B:= B;
Setlength(Text_B,N_B*5);
for i:=0 to N_B-1 do
for j:=0 to 4 do
Text_B[j,i]:=S_B.Cells[j+1,i+1];
end; with Data_C do
begin
N_C:= C;
Setlength(Text_C,N_C*10);
for i:=0 to N_C-1 do
for j:=0 to 9 do
Text_C[j,i]:=S_C.Cells[j+1,i+1];
end; end; DataStream:=TFileStream.Create(FileName,fmCreate); //建立数据流文件
try
DataStream.Write(DataRecord,SizeOf(TDataRec)); //实现数据流文件的写入
finally
DataStream.Free;
end;end;
end.然后,在SaveDialog1中调用,该过程!
请各位大虾发表意见!!或者提供别的更好的思路!
先谢过各位了!
当我进行了修改之后,继续进行Open,使保存的数据能够重新回填到表格之中,其代码如下:
procedure DataOpen(FileName:string;S_A,S_B,S_C,S_D:TStringGrid);
var
i,j: integer;
begin
if FileExists(FileName) then
DataStream:=TFileStream.Create(FileName,fmOpenRead);
try
DataStream.Read(DataRecord,SizeOf(TDataRec));
finally
DataStream.Free;
end; with DataRecord do
begin
for i:=0 to 4 do
S_D.Cells[i,1]:=Data_D[i]; with Data_A do
begin
for i:=0 to N_A-1 do
for j:=0 to 3 do
S_A.Cells[j+1,i+1]:=Text_A[j,i];
end; with Data_B do
begin
for i:=0 to N_B-1 do
for j:=0 to 4 do
S_B.Cells[j+1,i+1]:=Text_B[j,i];
end; with Data_C do
begin
for i:=0 to N_C-1 do
for j:=0 to 9 do
S_C.Cells[j+1,i+1]:=Text_C[j,i];
end; end;end;问题又伴随而来:当数据较多时,回填到表格中的数据,并非原来的数据:在前面的一些单元格中,其内容出现重复,或者顺序错位。然而后面单元格中数据仍可以保持正确!问题出现在哪里??是否仍然是数组出现问题???
初次使用FileStream,还请各位多多指教!
能否说的详细一些,我将记录中所有string换成ShortString换成后,情况仍然没有改变。
其实我要实现的功能算是比较简单的吧,只是将stringgrid和edit中的内容存放在一个文件中,然后调用时,文件中的数据能够重新充填到表格中去。
所以,我想知道,使用Filestream是否是一个行之有效的办法?如果不是,还有其它一些好的思路 或者方法呢?
对文件操作实在是不熟悉,程序历经千辛万苦终于写到了最后,可是还是困难重重;俗话说,外行看热闹,内行懂门道,还请各位多多发言!
谢谢!
前几天我也正好碰到这个问题,今天你问道了就把源程序贴出来好了,不过我的源程序是在C++Builder中写的,不过你也可以方便的把它改成Delphi!保存StringGrid中的内容到文本文件:(其中StringGrid中的每列数据用“,”分割)
void __fastcall TForm1::SaveToFile()
{
//TODO: Add your source code here int iFor ,jFor;
String TempStr,FileName;
TStringList* TempList;
TSaveDialog* Save; Save=new TSaveDialog(this);
TempList=new TStringList;
try
{ TempStr="";
for(iFor=0;iFor<StringGrid1->RowCount;iFor++)
{
for(jFor=0;jFor<StringGrid1->ColCount;jFor++)
{
if(StringGrid1->Cells[jFor][iFor]=="")
StringGrid1->Cells[jFor][iFor]=" ";
TempStr=TempStr+","+StringGrid1->Cells[jFor][iFor];
}
TempList->Add(TempStr);
TempStr="";
} Save->Filter="Îı¾Îļþ(*.txt)|*.txt" ;
Save->DefaultExt="*.txt";
Save->Options.Clear();
Save->Options<<ofOverwritePrompt<<ofCreatePrompt; if(Save->Execute())
{ FileName=Save->FileName;
TempList->SaveToFile(FileName);
}
}
__finally
{
delete TempList;
delete Save;
}}以下是从文件中读取保存的数据到StringGrid
void __fastcall TForm1::ReadFromFile()
{
//TODO: Add your source code here
int iFor,jFor ;
TStringList* TempList;
TStringList* TempStrList;
TOpenDialog* Open;
String FileName;
TempList=new TStringList;
TempStrList=new TStringList;
//TSysCharSet sepChars=TSysCharSet()<<','<<'t' ;
Open=new TOpenDialog(this);
TSysCharSet sepChars;
sepChars<<',';
try
{
Open->Filter="Îı¾Îļþ(*.txt)|*.txt";
Open->DefaultExt="*.txt";
Open->Options<<ofFileMustExist; if(Open->Execute())
{
FileName=Open->FileName;
TempList->LoadFromFile(FileName);
}
StringGrid1->RowCount=TempList->Count; ExtractStrings(sepChars,sepChars,TempList->Strings[0].c_str(),TempStrList);
StringGrid1->ColCount=TempStrList->Count; for(iFor=0;iFor<TempList->Count;iFor++)
{
ExtractStrings(sepChars,sepChars,TempList->Strings[iFor].c_str(),TempStrList);
for(jFor=0;jFor<TempStrList->Count;jFor++)
{
StringGrid1->Cells[jFor][iFor]=TempStrList->Strings[jFor];
}
TempStrList->Clear();
} }
__finally
{
delete TempList;
delete TempStrList;
delete Open;
}
}以上的代码在Win2000+BCB6下通过了没有问题,你就按照你的要求自己给改改吧!
{DataStream.Write(DataRecord,SizeOf(TDataRec)); //实现数据流文件的写入}
这句存储的是什么,你的DataRecord中是动态数组+STRING他们都是指针类型,虽然能DELPHI自管理这种指针,但显然不是简单类型那种方式。
DataStream.Read(DataRecord,SizeOf(TDataRec))
这句读,能保证读到原来的DataRecord?
建议你还是一个个写和读。