如何检测流编码?

基于这个问题:如何从TWebBrowser获取HTML源代码

如果我使用具有Unicode代码页的html页面运行此代码,结果就是乱码,因为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:testtest.txt'); // test only - file is ok
    Result := ??? // WideString
  finally
    LStream.Free();
  end;
end;

编辑:我发现这篇文章 - 如何加载和保存TWebBrowser中的文件类似Delphi的方式

这确实是我需要的。 但它只适用于Delphi的Unicode编译器(D2009 +)。 阅读结论部分:

显然我们可以做更多事情。 有几件事立刻浮现在脑海。 我们将一些Unicode功能和对非ANSI编码的支持复制到pre-Unicode编译器代码中。 如果文档字符集不是ANSI,那么使用早于Delphi 2009的任何东西进行编译时的当前代码将不会正确地将文档内容保存为字符串。

TEncoding类( TEncoding.GetBufferEncoding )显然是神奇的。 但D7没有TEncoding 。 有任何想法吗?


我使用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;
链接地址: http://www.djcxy.com/p/91055.html

上一篇: How to detect Stream encoding?

下一篇: Weird error "Type information missing for class Tmyclass"