无法从字符串中删除“空字符”

时间:2013-09-14 12:38:28

标签: delphi null character delphi-xe4

几个月前,我曾问过类似的question几个月。感谢Rob Kennedy我可以将整个文本加载到Richedit 但我无法移除Null chars我可以加载我的文字,因为我使用{{1 }}


现在在这段代码中:

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; 转换为TMemorystreamstring删除Null Chars,然后再将其转换为StringReplace()以使用TStringstream加载Richedit.lines.LoadFromStream

但我的问题是我无法使用Null Character删除StringReplace()。我可以替换其他字符,但不能替换#0

有没有办法直接在TMemorystream中删除空字符并将其加载到Richedit?怎么样?如果它不可能或者非常复杂,我将文本转换为string时如何删除它们?

感谢。

2 个答案:

答案 0 :(得分: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);

在流中替换将同样涉及测试每个字符,然后相应地调整流,然后在决定删除之后再继续。

答案 1 :(得分:8)

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;