【问题标题】:HTML source code from TWebBrowser - How to detect Stream encoding?来自 TWebBrowser 的 HTML 源代码 - 如何检测流编码?
【发布时间】:2013-01-10 22:12:38
【问题描述】:

基于这个问题:How can I get HTML source code from TWebBrowser

如果我使用具有 Unicode 代码页的 html 页面运行 this code,结果是乱码,因为 TStringStream 在 D7 中不是 Unicode。该页面可能是 UTF8 编码或其他 (Ansi) 代码页编码的。

如何检测 TStream/IPersistStreamInit 是否为 Unicode/UTF8/Ansi?

对于这个函数,我如何始终以 WideString 的形式返回正确的结果?

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;

如果我用 TMemoryStream 替换 TStringStream,并将 TMemoryStream 保存到文件中,一切都很好。它可以是 Unicode/UTF8/Ansi。但我总是想将流返回为 WideString:

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;
var
  // LStream: TStringStream;
  LStream: TMemoryStream;
  Stream : IStream;
  LPersistStreamInit : IPersistStreamInit;
begin
  if not Assigned(WebBrowser.Document) then exit;
  // LStream := TStringStream.Create('');
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream,soReference);
    LPersistStreamInit.Save(Stream,true);
    // result := LStream.DataString;
    LStream.SaveToFile('c:\test\test.txt'); // test only - file is ok
    Result := ??? // WideString
  finally
    LStream.Free();
  end;
end;

编辑:我发现这篇文章 - How to load and save documents in TWebBrowser in a Delphi-like way

这正是我需要的。但它仅适用于 Delphi Unicode 编译器 (D2009+)。阅读Conclusion部分:

显然我们可以做的还有很多。几件事 立刻浮现在脑海。我们改造了一些 Unicode 对 pre-Unicode 的非 ANSI 编码的功能和支持 编译器代码。当前代码与之前的任何内容一起编译 比 Delphi 2009 不会正确将文档内容保存到字符串 如果文档字符集不是 ANSI。

魔法显然在TEncoding 类(TEncoding.GetBufferEncoding)中。但 D7 没有TEncoding。有什么想法吗?

【问题讨论】:

  • 尝试一些支持 Unicode 的 StringList。 jcl.sf.net 库有TWideStringListTJclWideStringList,TNT Unicode 组件有TWideStringList,我认为还有更多。也许他们中的一些人也有 COM IStringList 适配器,一种或另一种方式。尝试这些或尝试在 google 或 torry.net 或其他一些收集器上搜索 Delphi 7 的更多 Unicode StringList 实现
  • MSIE 在 DOM 中引入了 .outerHTML 和 .innerHTML 等属性 所以实际上我敢打赌你必须进入 HTML DOM 树,获取 HTML 标记,然后将其作为 BSTR 又名 WideString 的外部 HTML 属性,无需中间COM 对象。也许你会为此需要一点 JavaScript。搜索诸如“如何在 TWebControl 中单击按钮”之类的主题 - 他们会为您提供示例,如何从 Delphi 端将某些标记定位为 JS 对象以及如何调用其方法/属性。您需要为根 HTML 标记阅读 outerHTML 属性

标签: delphi dom character-encoding delphi-7 twebbrowser


【解决方案1】:

我使用GpTextStream 处理转换(应该适用于所有 Delphi 版本):

function GetCodePageFromHTMLCharSet(Charset: WideString): Word;
const
  WIN_CHARSET = 'windows-';
  ISO_CHARSET = 'iso-';
var
  S: string;
begin
  Result := 0;
  if Charset = 'unicode' then
    Result := CP_UNICODE else
  if Charset = 'utf-8' then
    Result := CP_UTF8 else
  if Pos(WIN_CHARSET, Charset) <> 0 then
  begin
    S := Copy(Charset, Length(WIN_CHARSET) + 1, Maxint);
    Result := StrToIntDef(S, 0);
  end else
  if Pos(ISO_CHARSET, Charset) <> 0 then // ISO-8859 (e.g. iso-8859-1: => 28591)
  begin
    S := Copy(Charset, Length(ISO_CHARSET) + 1, Maxint);
    S := Copy(S, Pos('-', S) + 1, 2);
    if S = '15' then // ISO-8859-15 (Latin 9)
      Result := 28605
    else
      Result := StrToIntDef('2859' + S, 0);
  end;
end;

function GetWebBrowserHTML(WebBrowser: TWebBrowser): WideString;
var
  LStream: TMemoryStream;
  Stream: IStream;
  LPersistStreamInit: IPersistStreamInit;
  TextStream: TGpTextStream;
  Charset: WideString;
  Buf: WideString;
  CodePage: Word;
  N: Integer;
begin
  Result := ''; 
  if not Assigned(WebBrowser.Document) then Exit;
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream, soReference);
    if Failed(LPersistStreamInit.Save(Stream, True)) then Exit;
    Charset := (WebBrowser.Document as IHTMLDocument2).charset;
    CodePage := GetCodePageFromHTMLCharSet(Charset);
    N := LStream.Size;
    SetLength(Buf, N);
    TextStream := TGpTextStream.Create(LStream, tsaccRead, [], CodePage);
    try
      N := TextStream.Read(Buf[1], N * SizeOf(WideChar)) div SizeOf(WideChar);
      SetLength(Buf, N);
      Result := Buf;
    finally
      TextStream.Free;
    end;
  finally
    LStream.Free();
  end;
end;

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多