【问题标题】:Reading web pages / unicode阅读网页/unicode
【发布时间】:2009-12-04 14:20:54
【问题描述】:

我在 Delphi 2009 /2010 中有这个功能

它返回垃圾,现在如果我将 char,pchar 类型更改为 Ansichar,Pansichar 它返回文本,但所有外国 unicode 文本都是垃圾。它驱使我香蕉 我已经尝试各种东西 2 天了 我以为我理解了这个 unicode 废话,但我想我没有 请帮忙 谢谢 菲利普·瓦特尔

function GetInetFileAsString(const fileURL: string): string;
const
  C_BufferSize = 1024;
var
  sAppName: string;
  hSession,
    hURL: HInternet;

  Buffer: array[0..C_BufferSize] of Char;
  BufferLen: DWORD;

  strPageContent: string;
  strTemp: string;

begin
  Result := '';
  sAppName := ExtractFileName(Application.ExeName);
  hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil,
    nil, 0);
  try
    hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0);
    try
      strPageContent := '';
      repeat
        InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
        SetString(strTemp, PChar(@buffer), BufferLen div SizeOf(Char));
        strPageContent := strPageContent + strTemp;
      until BufferLen = 0;
      Result := strPageContent;
    finally
      InternetCloseHandle(hURL)
    end
  finally
    InternetCloseHandle(hSession)
  end
end;

【问题讨论】:

    标签: delphi unicode delphi-2009


    【解决方案1】:

    从 Delphi 2009 开始,StringUnicodeString 的别名,它保存 UTF-16 数据。另一方面,HTML 页面通常使用多字节 Ansi 编码(现在通常是 UTF-8,但并非总是如此)进行编码。您当前的代码仅在 HTML 编码为 UTF-16 时才有效,这种情况非常罕见。您不应该直接将原始 HTML 字节读入UnicodeString。您需要首先将整个数据下载到TBytesRawByteStringTMemoryStream 或您选择的其他合适的字节容器中,然后根据中指定的字符集执行 Ansi->Unicode 转换HTTP“内容类型”响应标头。您可以使用Accept-charset 请求标头告诉服务器您希望以哪个字符集发送数据,如果服务器无法使用该字符集,那么它应该发送406 Not Acceptable 响应(尽管它可能仍然发送如果它选择忽略您的请求标头,则以不可接受的字符集成功响应,因此您应该考虑这一点)。

    试试这样的:

    function GetInetFileAsString(const fileURL: string): string;
    const
      C_BufferSize = 1024;
    var
      sAppName: string;
      hSession, hURL: HInternet;
      Buffer: array of Byte;
      BufferLen: DWORD;
      strHeader: String;
      strPageContent: TStringStream;
    begin
      Result := '';
      SetLength(Buffer, C_BufferSize);
      sAppName := ExtractFileName(Application.ExeName);
      hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      try
        strHeader := 'Accept-Charset: utf-8'#13#10;
        hURL := InternetOpenURL(hSession, PChar(fileURL), PChar(strHeader), Length(strHeader), 0, 0);
        try
          strPageContent := TStringStream.Create('', TEncoding.UTF8);
          try
            repeat
              if not InternetReadFile(hURL, PByte(Buffer), Length(Buffer), BufferLen) then
                Exit;
              if BufferLen = 0 then
                Break;
              strPageContent.WriteBuffer(PByte(Buffer)^, BufferLen);
            until False;
            Result := strPageContent.DataString;
            // or, use HttpQueryInfo(HTTP_QUERY_CONTENT_TYPE) to get
            // the Content-Type header, parse out its "charset" attribute,
            // and convert strPageContent.Memory to UTF-16 accordingly...
          finally
            strPageContent.Free;
          end;
        finally
          InternetCloseHandle(hURL);
        end
      finally
        InternetCloseHandle(hSession);
      end;
    end;
    

    【讨论】:

    • 我成功使用了该代码,但是我将缓冲区更改为动态数组声明的缓冲区:TArray;然后设置长度(缓冲区,C_BufferSize)。另外,我在循环之前添加了一个 var 整数参数设置为零,并在每次调用 InternetReadFile 后使用 bufferLen 递增。让我知道下载文件的大小。
    【解决方案2】:

    我的第一个想法是在请求中添加正确的 AcceptEncoding/CharSet 标头:

    例如:

    接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.7

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 2010-12-02
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多