본문 바로가기

프로그래밍/Delphi

문자열에서 Null문자 제거하기

1. 개요

  TInetHTTP (WininetHTTP Suite) 컴포넌트를 이용하여 웹페이지를 요청할때 응답 헤더가 이상하게 넘어오는 경우가 Delphi XE이상버전에서 발생 한다 예를 들어 INetHttp.QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF)를 호출하여 얻은 응답 헤더에 "Content-Type"에 대한 문자열이 "'C'#0'o'#0'n#0't'#0'e'#0'n'#0't'#0 ..." 식으로 리턴 된다. 이 문자열을 직접 사용하고자 하면 문자열 변수에 다음과 같이 담게 되는데

     ResponseHeader := INetHttp.QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF);

그러면 결과는 자동으로 널 스트링을 인지하고 TypeCasting 되어서 ResponseHeader에는 'C'만 들어가서 정상적인 헤더 처리가 곤란해 진다. 이 때에 해당 널 값을 제거해 주는 방법을 고찰 해 보자


2. SetLength를 이용한 Null Char(#0) 제거 방법


function RemoveNullChars(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;

3. Delete를 이용한 방법


function RemoveNullChars(const Input: string): string;
var
  i: Integer;
begin
  Assert(Input<> '');
  i := 1;
  while i <= Length(Input) do
    if Input[i] = #0 then
      Delete(Input, i, 1)
    else
      Inc(i);
  result := Input;
end;


4. TMemoryStream을 대상으로 제거하기


procedure RemoveNullCharsFromMemoryStream(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;

5. 성능 문제


  위 함수 호출은 순식간에 처리 되기 때문에 성능에큰 영향을 미치지는 않지만 성능이 조금 높은 것을 치자면 SetLength를 이용한 방법이 Delete를 이용한 방법보다 거의 3배 정도 빠르게 동작을 한다(10000회 / 31ms)