目的:
    将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中调用,该过程!
请各位大虾发表意见!!或者提供别的更好的思路!
先谢过各位了!

解决方案 »

  1.   

    在发帖子的过程中,我发现部分问题所在:动态数组分配空间时出现错误,原来是Setlength(Text_A,N_A);,所以保存不能完成!
    当我进行了修改之后,继续进行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,还请各位多多指教!
      

  2.   

    string类型是一个指针如果结构里是string保存的将是它的指针地址而不是内容将string换成ShortString先
      

  3.   

    请问:zswang(伴水清清)(专家门诊清洁工),
         能否说的详细一些,我将记录中所有string换成ShortString换成后,情况仍然没有改变。
         其实我要实现的功能算是比较简单的吧,只是将stringgrid和edit中的内容存放在一个文件中,然后调用时,文件中的数据能够重新充填到表格中去。
         所以,我想知道,使用Filestream是否是一个行之有效的办法?如果不是,还有其它一些好的思路 或者方法呢?
         对文件操作实在是不熟悉,程序历经千辛万苦终于写到了最后,可是还是困难重重;俗话说,外行看热闹,内行懂门道,还请各位多多发言!
         谢谢!
      

  4.   

    为什么用FileStream类呢?最简单的办法是用TStringList类的SaveToFile()方法将其保存到文件。具体的做法是建立一个TStringList,将StringGrid中的每一行作为一个Item保存到这个新建的TStringList对象中然后再保存就可以了,要读取的时候用LoadFromFile()。
    前几天我也正好碰到这个问题,今天你问道了就把源程序贴出来好了,不过我的源程序是在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="&Icirc;&Auml;±&frac34;&Icirc;&Auml;&frac14;&thorn;(*.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="&Icirc;&Auml;±&frac34;&Icirc;&Auml;&frac14;&thorn;(*.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下通过了没有问题,你就按照你的要求自己给改改吧!
      

  5.   

    使用Filestream没问题,肯定是编程问题。
    {DataStream.Write(DataRecord,SizeOf(TDataRec));    //实现数据流文件的写入}
    这句存储的是什么,你的DataRecord中是动态数组+STRING他们都是指针类型,虽然能DELPHI自管理这种指针,但显然不是简单类型那种方式。
    DataStream.Read(DataRecord,SizeOf(TDataRec))
    这句读,能保证读到原来的DataRecord?
    建议你还是一个个写和读。