2Pascal-新时代的Pascal

标题: 关于 字符串的 存储 和 传输 [打印本页]

作者: wang_80919    时间: 2015-11-5 09:17
标题: 关于 字符串的 存储 和 传输
字符串 在 DELPHI 的移动版本中,只存在 string 这一种类型。
string 的编码是 unicode ,也就是过去的 WideString ,虽然官方说两者不天一样。其实效果是一样的。

但是字符串保存在内存中,或者保存在 文件中,不一定使用这个 unicode 编码。
特别是 记事本的默认保存。

你们可自己用记事本 另存为的 功能 来看看, 记事本提供了几种 文本的编码格式。

当选择非 ANSI 格式的时候。被保存的数据中,最前面会出现 BOM 这种数据。 不懂的去百度。

地球上所有的 正规 文本读写工具,都支持 BOM 。例如 记事本 新版本 DELPHI 以及 TStringList TMemo.Items  TInifile 等。
但是也有一些工具 不支持 BOM。比如一些老外的开发工具,他们要求必须是 UTF8 编码,但是不能存在 BOM。

文本文件用 文件流 或内存流加载成流之后,和保存在文件中,没有任何区别。都是数据。

数据 是不考虑编码的。

数据 也不一定就是字符串。

当你 把一个 非 unicode 编码的字符串数据,强加给 string ,就会出现乱码。


但是,如果你将 数据先转码成 unicode 就不会出现 乱码了。

乱码 是 显示的时候,才能发现的问题。


如何 转码呢?
如果你使用  TStringList 来加载 文本文件,而且,文件文件包含正确的 BOM,那么就会自动转码。

如果你知道文件没有 BOM 也知道正确编码,那么你 加载的时候,通过参数使用  TEnCoding.XXXX 来指定 编码。
List.LoadFromFile('c:/tmp.txt', TEncoding.XXXX);
还有很多类支持这样的代码。

对于网络传输,很多时候,不可能包含 BOM。
但是,又需要你转码。
那么 传输的对象,请使用 TByes 来保存。
例如
服务器要求你传输 UTF8 的一个字符串。
那么你可以
var
Data: TBytes;
begin
  Data := TEncoding.UTF8.GetBytes('你的字符串');
  Send(Data);
end;


当你收到一个 无 BOM 编码的数据,但是你知道编码,也可以用 TEncoding.XXXX.GetString(收到的TBytes); 来获取。


对于内存流,如果流内有 BOM,可以直接用 TStringList 来加载。
没有 BOM,但是你知道编码,可以 加载的时候,加 TEncoding 参数。 List.LoadFromStream(ms, TEncoding.XXXX);


对于  indy 类控件。
需要使用  TIdBytes 和 IIdTextEncoding。
IIdTextEncoding 可以通过 IndyTextEncoding(TEncoding) 来转。

在任何情况下,都禁止用 XXXXToYYYY、UTF8Encode 和 UTF8Decode 这些旧的函数。因为全都不如 TEncodiing.编码.函数 这种准确。
使用 TEcnding 的时候,一定要指定编码,否则跨平台会效果不一致。

作者: wang_80919    时间: 2015-11-5 09:23
如果是未知编码的呢?

请大家到群里 下载
FMX IDHTTP Get 从网页获取 字符串,自动识别是否 UTF8 + Fix Glib bug 2014-1108.zip
作者: wang_80919    时间: 2015-11-5 09:23
FMX_IDHTTP_从网页获取_字符串,自动识别是否_UTF8_+_Fix_Glib_bug_2014-1108.zip
http://www.2pascal.com/forum.php ... =1029&fromuid=4
(出处: 2Pascal-新时代的Pascal)





欢迎光临 2Pascal-新时代的Pascal (http://2pascal.com/) Powered by Discuz! X3