0

私が使用するファイルに何かを書くために、例えばこのコード:

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;

また、I / Oファイルの場合、バイトの配列を使用するので、すべて問題ありませんが、文字列を使用する場合、たとえば次のように宣言します。

InBuf, OutBuf: string  // in delphi xe2 = unicode string

その後、動作しません。そのファイルは何も書かないという意味で。私はその理由を理解しました、または単にそれを理解したと思います。問題は、文字列に静的構造ではなくメモリへのポインタだけが含まれている理由だと思います。正しい?この場合、それを解決するためのいくつかの解決策がありますか?ある意味で、ベクトルではなく文字列を使用してファイルを書き込むことができるようにするために何かを行うことは可能ですか?または、必要に応じてベクトルを使用する必要がありますか?可能であれば、私はできますか?どうもありがとう。

4

4 に答える 4

3

文字列の使用には 2 つの問題があります。まず、RawByteStringバイト サイズの文字要素を確実に使用できるようにする必要があります。Unicode 文字列には 2 バイト幅の要素があります。次に、実際には単なるポインターである文字列を逆参照する必要があります。

しかし、スタックに割り当てられたバイト配列よりも文字列を好むのはなぜだろうか。

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;

注:前のコードでは 65536 バイトのバッファーを宣言しましたが、使用したのは 65535 バイトだけです。おそらくあなたが意図したものではありません。

于 2011-09-28T08:05:00.383 に答える
3

文字列をバッファとして使用するには (これはお勧めしません)、SetLength を使用して内部バッファを割り当てる必要があり、読み取るデータとして InBuf[1] と OutBuf[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...

AnsiString の代わりに TBytes を使用することもできます。使い方はそのままです。

しかし、ここで TBytes、AnsiStrings、または RawByteStrings を動的に割り当てる利点は実際にはありません。スタックベースのバッファを使用してください。マルチスレッド環境では、おそらくもう少し小さくするでしょう。

于 2011-09-28T08:06:31.063 に答える
0

はい、ストリームに/から文字列を保存/ロードできます。次の例を参照してください

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 := '';
于 2011-09-28T08:02:26.673 に答える
0

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() を呼び出すことで簡略化できます。

procedure MyProc (... );
begin
  ...
  CopyFile(PChar(uFileSrc), PChar(uFileTmp), False);
  ...
end; 

いずれにしても、手動でファイル データを読み書きする必要はまったくありません。

于 2011-09-28T18:31:48.217 に答える