怎么把一个如下record 的数据读到一个流文件里,保存到问题;又能顺利的从文件中读取record的数据
  TFileMessage= record
    FileName:AnsiString;
    ISize:Int64;
  end;
  TFiles=array of TFileMessage;
  TGZHeader =  record
    Id1       : Byte;
    Id2       : Byte;
    Method    : Byte;
    Flags     : Byte;
    Time      : Cardinal;
    ExtraFlags: Byte;
    OS        : Byte;
    password:string;
    Files:TFiles;
  end;现在我碰到的问题,能读进去,但是流文件保存成文件后,再读取出来,files的信息就没法正常显示。

解决方案 »

  1.   

    var
     strstream:TStream;
     infilestream,outfilestream:TStream;
     myfile,myfile1:TGZHeader;
     isize:int64;
     i:integer;
    begin
      myfile.id1:=1;
      myfile.Id2:=2;
      myfile.Method:=3;
      myfile.Flags:=4;
      myfile.Time:=5;
      myfile.ExtraFlags:=6;
      myfile.OS:=7;
      myfile.password:='abcdefg';  SetLength(myfile.files,2);
      myfile.files[0].FileName:='124.txt';
      myfile.files[0].ISize:=26;  myfile.files[1].FileName:='4567.txt';
      myfile.files[1].ISize:=231;  outfilestream:=TFileStream.Create('d:\压缩.szip',fmCreate);  //取得长度
      isize:=SizeOf(myfile.Id1)+sizeof(myfile.Id2)+sizeof(myfile.Method)+
             SizeOf(myfile.Flags)+sizeof(myfile.Time)+sizeof(myfile.ExtraFlags)+
             SizeOf(myfile.OS);
      strstream:=TStringStream.Create(myfile.password);
      isize:=isize+strstream.Size;  strstream:=TStringStream.Create(myfile.Files[0].FileName);
      isize:=isize+strstream.Size+sizeof(myfile.Files[1].ISize);  strstream:=TStringStream.Create(myfile.Files[1].FileName);
      isize:=isize+strstream.Size+sizeof(myfile.Files[1].ISize);  strstream.Free;
      outfilestream.Write(isize,SizeOf(isize));
      outfilestream.Write(myfile,isize);
      outfilestream.Position:=0;
      //直接这样读是没问题
      {
      infilestream:=TMemoryStream.Create;  infilestream.CopyFrom(outfilestream,0);  isize:=0;
      infilestream.Position:=0;
      infilestream.Read(isize,SizeOf(isize));
      infilestream.Read(myfile1,isize);
      infilestream.Free;
      }
      outfilestream.Free;
      //从文件读就是有问题,具体就是files那里要么是乱七八糟的信息,要么就是为空
      {
      isize:=0;
      infilestream:=TFileStream.Create('d:\压缩.szip',fmOpenRead or fmShareDenyNone);
      infilestream.Read(isize,SizeOf(isize));
      infilestream.Read(myfile1,isize);
      infilestream.Free;
      }代码比较乱
      

  2.   

    我测试了下,原来读进去的outfilestream 的大小 是56,后来读取文件后的 infilestream 的大小也是56.
      

  3.   

    你把outfilestream关掉再读,不然你写在outfilestream的内容还在内存缓冲区里呢。
      

  4.   

    果然哦,原来还是在缓冲区,那怎么样才能把files 这个动态数组的数据正确的读进流里呢?
      

  5.   

      password:string;
      Files:TFiles;这两个定义,其实是两个指针,SizeOf(password)=4  SizeOf(Files)=4,它们指向的数据都在其它地方.进行内存复制 CopyFrom这些操作操作的时候,你操作的一定要是全部的实际的数据才行。你不能说我将图书馆的查询标签全程搬走了,就代表将所有的书都搬走了。
    先将 password:string; 定义为 password:Array[0..127] of Char; 这个长度应该足够了。
    然后将 Files:TFiles;定义原理 Files:Byte;//这仅是代表你的文件的第一个字节从这里开始。TFileMessage.FileName:AnsiString; 这也搞成 
    TFileMessage.FileName:Array [0..255] of Char; 文件名长度不够的话在加比如你要保存 100个 TFileMessage,它的总长度=Sizeof(TFileMessage)*100;var
      Arr:Array of Byte;
      ArrLen:Integer;
    begin
      ArrLen:=Size(TGZHeader )+Sizeof(TFileMessage)*100 -1;
    减一的原因是 你的 TFiles 将从  Files:Byte;这个位置开始。 Setlength(Arr,Arrlen);//这个长度的内存块将保存你所有的数据。
     接下来就是将这个内存块复制到流中了。end;
     
    你保存是应该不能用 TStream 吧,应该用TMemoryStream.
    也没有必要在定义Arr,直接给 TMemoryStream设置长度,将数据写入就可以了。end;你可以看一下:
    http://topic.csdn.net/u/20110910/00/3d45c96b-0133-4f13-b806-6b26715a39f4.html
    关于内存和指针操作,数据类型转换本质的理解
      

  6.   


    你好,非常感谢你的解答,我按照你的做法,一个个都重新定义成定长,在最后取的时候我本来想算出长度直接取整个files 的数据,但发现取出来的数据都是错误的。但如果我 files 数组做循环,一个个取里面的record 的数据,这样是正确的。能否告知为什么整个取是错误的呢? 谢谢。
      

  7.   


    你好,非常感谢你的解答,我按照你的做法,一个个都重新定义成定长,在最后取的时候我本来想算出长度直接取整个files 的数据,但发现取出来的数据都是错误的。但如果我 files 数组做循环,一个个取里面的record 的数据,这样是正确的。能否告知为什么整个取是错误的呢? 谢谢。
      

  8.   

    我先算出来 数组的长度,然后 算出来整个数组所占的空间,stream.read(files,size) 就这样取~~
      

  9.   

    这样肯定不行啊。
    流的前面保存的是 TGZHeader 结构的数据。要读也是这样你要先将流的指针位置移动到 TGZHeader 结构 Files 的位置,然后在取。
      

  10.   

    额,我就是这个思路来的呢,兄弟,你再帮我看看下面的这个代码呢,谢谢@~~@
    var
      infilestream:TStream;
      isize:Int64;
      i:Integer;
      myfile:TGZHeader;
      file1:TFiles;
    begin
      infilestream:=TFileStream.Create('d:\压缩.szip',fmOpenRead or fmShareDenyNone);
      //先读tgzheader大小
      infilestream.Read(myfile,SizeOf(TGZHeader));
      i:=myfile.Files;//这个是记录files 长度的元素,在读入流的时候记录在Tgzheader的 这个元素中
      SetLength(file1,myfile.Files);
      isize:=i*sizeof(tfilemessage);//算总的files 长度
      //这是一个个读取,读取出来的数据正常
      {
      for I := 0 to myfile.Files-1 do  infilestream.ReadBuffer(file1[i],SizeOf(tfilemessage));
      }
      infilestream.Read(file1[0],isize);
      infilestream.Free;