使用 Delphi 7 得到 HTML,最后我得到一个烦人的零

Using Delphi 7 to get HTML, I get an annoying zero at the end

使用Delphi 7从HTTPS获取HTML,无论我用什么URL,我总是在</html>结束后得到一个零,像这样: "...</html>0".

假设我称之为:

memo1.text := GetUrlContent('http://google.com');

我得到所有 HTML 然后是零:

[],"sbpl":24,"sbpr":24,"scd":10,"sce":5,"stok":"Y2aF9aDK2ABWRqkd17qwTWg63TY"},"d":{},"ZI/YVQ":{},"Qnk92g":{},"U5B21g":{},"DPBNMg":{},"YFCs/g":{}};google.x(null,function(){});(function(){var r=[];google.plm(r);})();(function(){var m=[]
;google.jsc && google.jsc.m(m);})();</script></div></body></html>
0

这个零,你看到了吗??

这是我正在使用的函数:

function GetUrlContent(const Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array[0..1024] of Char;
  BytesRead: dWord;
begin
  Result := '';
  NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(NetHandle) then 
  begin
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);

    if Assigned(UrlHandle) then
      { UrlHandle valid? Proceed with download }
    begin
      FillChar(Buffer, SizeOf(Buffer), 0);
      repeat
        Result := Result + Buffer;
        FillChar(Buffer, SizeOf(Buffer), 0);
        InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
      until BytesRead = 0;
      InternetCloseHandle(UrlHandle);
    end
    else
      { UrlHandle is not valid. Raise an exception. }
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);

    InternetCloseHandle(NetHandle);
  end
  else
    { NetHandle is not valid. Raise an exception }
    raise Exception.Create('Unable to initialize Wininet');
end;

您没有正确处理 InternetReadFile()

  • 您甚至在第一次调用 InternetReadFile() 之前就将 Buffer 附加到 Result

  • 您没有对 InternetReadFile().

  • 的实际调用进行任何错误检查
  • 您假设 InternetReadFile() returns 以 null 结尾的数据,但事实并非如此。将 Buffer 附加到 Result 时,您必须考虑 BytesRead,否则您可能会附加超过 BytesRead 字节数的垃圾。

此外,如果 InternetOpenUrl() 失败,您将泄漏 InternetOpen() 返回的句柄。

试试这个:

function GetUrlContent(const Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array[0..1024] of AnsiChar;
  BytesRead: DWORD;
  Size: Integer;
begin
  Result := '';
  NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(NetHandle) then
    raise Exception.Create('Unable to initialize Wininet');
  try
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
    if not Assigned(UrlHandle) then
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);
    try
      { Proceed with download }
      Size := 0;
      repeat
        if not InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead) then
          raise Exception.CreateFmt('Cannot download from URL %s', [Url]);
        if BytesRead = 0 then Break;
        SetLength(Result, Size + BytesRead);
        Move(Buffer, Result[Size + 1], BytesRead);
        Inc(Size, BytesRead);
      until False;
    finally
      InternetCloseHandle(UrlHandle);
    end;
  finally
    InternetCloseHandle(NetHandle);
  end;
end;

或者:

function GetUrlContent(const Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array[0..1024] of AnsiChar;
  BytesRead: DWORD;
  Data: TStringStream;
begin
  Result := '';
  NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(NetHandle) then
    raise Exception.Create('Unable to initialize Wininet');
  try
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
    if not Assigned(UrlHandle) then
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);
    try
      { Proceed with download }
      Data := TStringStream.Create;
      try
        repeat
          if not InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead) then
            raise Exception.CreateFmt('Cannot download from URL %s', [Url]);
          if BytesRead = 0 then Break;
          Data.WriteBuffer(Buffer, BytesRead);
        until False;
        Result := Data.DataString;
      finally
        Data.Free;
      end;
    finally
      InternetCloseHandle(UrlHandle);
    end;
  finally
    InternetCloseHandle(NetHandle);
  end;
end;