4

数か月前に同様の質問をしました。Rob Kennedyのおかげで、テキスト全体を に読み込むことができましたRichedit が、削除できませんでしNull charsた。を使用したため、テキストを読み込むことができStreamました。


このコードでは:

var
  strm : TMemorystream;
  str  : UTF8string;
  ss   : TStringstream;

begin
  strm := tmemorystream.Create;

  try
    strm.LoadFromFile('C:\Text.txt');
    setstring(str,PAnsichar(strm.Memory),strm.Size);
    str := StringReplace(str, #0, '', [rfReplaceAll]);  //This line doesn't work at all
    ss  := tstringstream.Create(str);
    Richedit1.Lines.LoadFromStream(ss);
  finally
    strm.Free;
    ss.Free;
  end;
end;

で削除するように変換TMemorystreamし、再度 でロードするように変換しました。stringNull CharsStringReplace()TStringstreamRichedit.lines.LoadFromStream

しかし、私の問題は、をNull Character使用して削除できないことStringReplace()です。他の文字を置き換えることはできますが、できません#0

ヌル文字を直接削除しTMemorystreamてロードする方法はありますRicheditか? どのように?それが不可能な場合、または非常に複雑な場合、テキストを に変換するときにそれらを削除するにはどうすればよいstringですか?

ありがとう。

4

2 に答える 2

10

Sertac の回答は正確であり、それを受け入れる必要があります。パフォーマンスが重要で、ヌル文字のインスタンスが頻繁に発生する大きな文字列がある場合は、ヒープ割り当ての数を減らすようにしてください。これを実装する方法は次のとおりです。

function RemoveNull(const Input: string): string;
var
  OutputLen, Index: Integer;
  C: Char;
begin
  SetLength(Result, Length(Input));
  OutputLen := 0;
  for Index := 1 to Length(Input) do
  begin
    C := Input[Index];   
    if C <> #0 then
    begin
      inc(OutputLen);
      Result[OutputLen] := C;
    end;
  end;
  SetLength(Result, OutputLen);
end;

メモリストリームで直接実行したい場合は、次のように実行できます。

procedure RemoveNullFromMemoryStream(Stream: TMemoryStream);
var
  i: Integer;
  pIn, pOut: PByte;
begin
  pIn := Stream.Memory;
  pOut := pIn;
  for i := 0 to Stream.Size-1 do
  begin
    if pIn^ <> 0 then
    begin
      pOut^ := pIn^;
      inc(pOut);
    end;
    inc(pIn);
  end;
  Stream.SetSize(NativeUInt(pOut)-NativeUInt(Stream.Memory));
end;
于 2013-09-14T13:24:48.537 に答える
8

私が見る限り、すべての検索/置換ユーティリティは、いずれかの時点で入力を PChar にキャストします。この '#0' は終了文字です。したがって、最初の Null の前にある文字列部分を通過することはありません。独自のメカニズムを考案する必要があるかもしれません。簡単な例:

var
  i: Integer;
begin
  Assert(str <> '');
  i := 1;
  while i <= Length(str) do
    if str[i] = #0 then
      Delete(str, i, 1)
    else
      Inc(i);

同様に、ストリームでの置換には、各文字をテストし、それに応じてストリームを調整してから、削除することを決定した後に移動する必要があります。

于 2013-09-14T13:09:23.563 に答える