Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 是否可以使用字符串数据类型结构写入/读取文件?_Delphi_File_Delphi Xe2 - Fatal编程技术网

Delphi 是否可以使用字符串数据类型结构写入/读取文件?

Delphi 是否可以使用字符串数据类型结构写入/读取文件?,delphi,file,delphi-xe2,Delphi,File,Delphi Xe2,例如,对于在文件中写入内容,我使用以下代码: procedure MyProc (... ); const BufSize = 65535; var FileSrc, FileDst: TFileStream; StreamRead: Cardinal; InBuf, OutBuf: Array [0..bufsize] of byte; begin ..... FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or

例如,对于在文件中写入内容,我使用以下代码:

procedure MyProc (... );
const
  BufSize = 65535;
var
  FileSrc, FileDst: TFileStream;
  StreamRead: Cardinal;
  InBuf, OutBuf: Array [0..bufsize] of byte;
begin
  .....
  FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or fmShareDenyWrite);
  try
    FileDst := TFileStream.Create (uFileTmp, fmCreate);
    try
      StreamRead := 0;
      while ((iCounter < iFileSize) or (StreamRead = Cardinal(BufSize))) 
      begin
        StreamRead := FileSrc.Read (InBuf, BufSize);
        Inc (iCounter, StreamRead);
      end;
    finally
      FileDst.Free;
    end;
  finally
    FileSrc.Free;
  end;
end;
那就不行了。从某种意义上说,该文件不会什么都不写。我已经理解了原因,或者只是想理解它。 我认为问题可能在于为什么字符串只包含指向内存的指针,而不是静态结构;对的 在这种情况下,有什么解决办法吗?从某种意义上说,我可以用字符串而不是向量来写一个文件吗?或者我需要一个向量? 如果可能的话,我能做什么?
非常感谢。

是的,您可以在流中保存/加载字符串,请参见以下示例

var Len: Integer;
    buf: string;
    FData: TStream;

// save string to stream
// save the length of the string
Len := Length(buf);
FData.Write(Len, SizeOf(Len));
// save string itself
if(Len > 0)then FData.Write(buf[1], Len * sizeof(buf[1]));

// read string from stream
// read the length of the string
FData.Read(Len, SizeOf(Len));
if(Len > 0)then begin
   // get memory for the string
   SetLength(buf, Len);
   // read string content
   FData.Read(buf[1], Len * sizeof(buf[1]));
end else buf := '';

是的,您可以在流中保存/加载字符串,请参见以下示例

var Len: Integer;
    buf: string;
    FData: TStream;

// save string to stream
// save the length of the string
Len := Length(buf);
FData.Write(Len, SizeOf(Len));
// save string itself
if(Len > 0)then FData.Write(buf[1], Len * sizeof(buf[1]));

// read string from stream
// read the length of the string
FData.Read(Len, SizeOf(Len));
if(Len > 0)then begin
   // get memory for the string
   SetLength(buf, Len);
   // read string content
   FData.Read(buf[1], Len * sizeof(buf[1]));
end else buf := '';

使用字符串有两个问题。首先,您希望使用
RawByteString
,以确保使用字节大小的字符元素–Unicode字符串包含两个字节宽的元素。其次,你需要取消对字符串的引用,它实际上只是一个指针

但我想知道为什么您更喜欢字符串而不是堆栈分配的字节数组

procedure MyProc (... );
const
  BufSize = 65536;
var
  FileSrc, FileDst: TFileStream;
  StreamRead: Cardinal;
  InBuf: RawByteString;
begin
  .....
  FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or fmShareDenyWrite);
  try
    FileDst := TFileStream.Create (uFileTmp, fmCreate);
    try
      SetLength(InBuf, BufSize);
      StreamRead := 0;
      while ((iCounter < iFileSize) or (StreamRead = Cardinal(BufSize))) 
      begin
        StreamRead := FileSrc.Read (InBuf[1], BufSize);
        Inc (iCounter, StreamRead);
      end;
    finally
      FileDst.Free;
    end;
  finally
    FileSrc.Free;
  end;
end;
程序MyProc(…);
常数
BufSize=65536;
变量
FileSrc,FileDst:TFileStream;
StreamRead:红衣主教;
InBuf:RawByteString;
开始
.....
FileSrc:=TFileStream.Create(uFileSrc、fmOpenRead或fmShareDenyWrite);
尝试
FileDst:=TFileStream.Create(uFileTmp,fmCreate);
尝试
设置长度(InBuf,BufSize);
StreamRead:=0;
而((iCounter

注意:您以前的代码声明了一个65536字节的缓冲区,但您只使用了其中的65535字节。可能不是您想要的。

使用字符串有两个问题。首先,您希望使用
RawByteString
,以确保使用字节大小的字符元素–Unicode字符串包含两个字节宽的元素。其次,你需要取消对字符串的引用,它实际上只是一个指针

但我想知道为什么您更喜欢字符串而不是堆栈分配的字节数组

procedure MyProc (... );
const
  BufSize = 65536;
var
  FileSrc, FileDst: TFileStream;
  StreamRead: Cardinal;
  InBuf: RawByteString;
begin
  .....
  FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or fmShareDenyWrite);
  try
    FileDst := TFileStream.Create (uFileTmp, fmCreate);
    try
      SetLength(InBuf, BufSize);
      StreamRead := 0;
      while ((iCounter < iFileSize) or (StreamRead = Cardinal(BufSize))) 
      begin
        StreamRead := FileSrc.Read (InBuf[1], BufSize);
        Inc (iCounter, StreamRead);
      end;
    finally
      FileDst.Free;
    end;
  finally
    FileSrc.Free;
  end;
end;
程序MyProc(…);
常数
BufSize=65536;
变量
FileSrc,FileDst:TFileStream;
StreamRead:红衣主教;
InBuf:RawByteString;
开始
.....
FileSrc:=TFileStream.Create(uFileSrc、fmOpenRead或fmShareDenyWrite);
尝试
FileDst:=TFileStream.Create(uFileTmp,fmCreate);
尝试
设置长度(InBuf,BufSize);
StreamRead:=0;
而((iCounter

注意:您以前的代码声明了一个65536字节的缓冲区,但您只使用了其中的65535字节。可能不是您想要的。

要使用字符串作为缓冲区(我不建议这样做),您必须使用SetLength来分配内部缓冲区,并且必须将InBuf[1]和extuf[1]作为要读取或写入的数据传递

  var
    InBuf, OutBuf: AnsiString; // or TBytes
  begin
    SetLength(InBuf, BufSize);
    SetLength(OutBuf, BufSize);

    ...

    StreamRead := FileSrc.Read(InBuf[1], BufSize); // if TBytes, use InBuf[0]

    // etc...
您也可以使用TBytes,而不是AnsiString。用法保持不变


但实际上,我认为在这里动态分配tbyte、ansistring或rawbytestring没有任何优势。我宁愿做您已经做过的事情:使用基于堆栈的缓冲区。在多线程环境中,我可能会将其缩小一点。

要使用字符串作为缓冲区(我不建议这样做),您必须使用SetLength来分配内部缓冲区,并且必须将InBuf[1]和extuf[1]作为数据传递给读写

  var
    InBuf, OutBuf: AnsiString; // or TBytes
  begin
    SetLength(InBuf, BufSize);
    SetLength(OutBuf, BufSize);

    ...

    StreamRead := FileSrc.Read(InBuf[1], BufSize); // if TBytes, use InBuf[0]

    // etc...
您也可以使用TBytes,而不是AnsiString。用法保持不变


但实际上,我认为在这里动态分配tbyte、ansistring或rawbytestring没有任何优势。我宁愿做您已经做过的事情:使用基于堆栈的缓冲区。在多线程环境中,我可能会将其缩小一点。

在相关说明中,要将内容从一个
TStream
复制到另一个
TStream
,您只需使用
TStream.CopyFrom()
方法即可:

procedure MyProc (... );
var
  FileSrc, FileDst: TFileStream;
begin
  ...
  FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or fmShareDenyWrite);
  try
    FileDst := TFileStream.Create (uFileTmp, fmCreate);
    try
      FileDst.CopyFrom(FileSrc, 0); // or FileDst.CopyFrom(FileSrc, iFileSize)
    finally
      FileDst.Free;
    end;
  finally
    FileSrc.Free;
  end;
  ...
end; 
可以通过调用CopyFile()来简化:


无论哪种方式,您都不必担心手动读取/写入文件数据

在相关说明中,要将内容从一个
TStream
复制到另一个
TStream
,您只需使用
TStream.CopyFrom()
方法即可:

procedure MyProc (... );
var
  FileSrc, FileDst: TFileStream;
begin
  ...
  FileSrc := TFileStream.Create (uFileSrc, fmOpenRead Or fmShareDenyWrite);
  try
    FileDst := TFileStream.Create (uFileTmp, fmCreate);
    try
      FileDst.CopyFrom(FileSrc, 0); // or FileDst.CopyFrom(FileSrc, iFileSize)
    finally
      FileDst.Free;
    end;
  finally
    FileSrc.Free;
  end;
  ...
end; 
可以通过调用CopyFile()来简化:


无论哪种方式,您都不必担心手动读取/写入文件数据

为什么使用字符串?堆栈分配的字节缓冲区在我看来很好;因为数据都是字符串unicode,所以我需要对它进行操作。只是为了不做太多从字符串unicode到字节数组的转换,并对代码进行semplify。另一个原因是我希望在类中使用“bufsize”变量而不是静态变量。当我使用动态数组并设置它的长度时,我也有同样的问题。到底是什么问题?我假设您不只是将数据从一个文件复制到另一个文件,对吗?在你再次写出数据之前,你需要做一些处理,对吗?嗯,帕斯卡的匈牙利符号系统。。。逐字符读取字符串,遇到#0时停止读取为什么使用字符串?堆栈分配的字节缓冲区在我看来很好;因为数据都是字符串unicode,所以我需要对它进行操作。只是为了不做太多从字符串unicode到字节数组的转换,并对代码进行semplify。另一个原因是我希望在类中使用“bufsize”变量而不是静态变量。当我使用动态数组并设置它的长度时,我也有同样的问题。什么