Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 3048|回复: 5

LAZARUS的文本处理基础

[复制链接]

该用户从未签到

发表于 2012-9-11 18:12:38 | 显示全部楼层 |阅读模式
    前两天给LAZ的一个文本问题困扰了,同样的代码:Length('Hellö Wöld'),竟然在不同工程里的执行结果不同。所以好好查了下有关资料,现在整理出来,做个总结。有不对的和欠缺的欢迎大家指正。
    对UNICODE UTF-8 UTF-16不熟的,先补充下理论:http://blog.sina.com.cn/s/blog_5 ... ml#bsh-75-130742395
   

   FREE PASCAL的有关数据类型:
   char               1个字节的字符
   widechar        2个字节的字符
   string             代表char数组。{$H+}是相当于ansistring;{$H-}时或有指明长度时(比如:var lTxt:string[10]),相当于shortstring。
   shortstring     代表长度不超过255个字节的char数组。内部结构包括:长度(1字节)、char数组。
   ansistring      代表不定长的char数组。内部结构包括:引用计数、char数组、文本结束符(值为0,1字节)。
                        对应的指针PChar,表示指向一char数组,结尾有文本结束符(值为0,1字节)。
   unicodestring 代表不定长的widechar数组。内部结构包括:引用计数、widechar数组、文本结束符(值为0,2字节)。
                       对应的指针PUnicodeChar,表示指向一widechar数组,结尾有文本结束符(值为0,2字节)。
   widestring    代表不定长的widechar数组。跟unicodestring类似,差别在于widestring内部结构里没有引用计数,并且在WINDOWS下使用会用WIN特定的功能分配内存以便支持OLE。

  请注意:
  1.FPC会透明处理shortstring、ansistring、unicodestring和widestring互相之间的赋值,但不会处理字符串的编码问题。
     也就是说这四种类型的变量里存放的是ANSI还是UTF-8还是UTF-16,FPC不关心也不处理。估计只处理数据存放的空间之间的转换。
     编码问题需要开发人员使用函数来处理。一般shortstring ansistring存放ANSI和UTF-8,unicodestring widestring存放UTF-16。
  2.一般引用计数就是为了编译器自动分配和自动回收数据所占空间,那么widestring按文档所说就是编译器不会自动回收空间了,是否如此有谁知道?
  3.字符串编码之间的转换,LAZ提供了一堆函数,若使用0.9.30及以前版本的,放在
LCLProc单元里;若使用0.9.31及以后版本的,放在lazutf8单元里。

   ANSI与UTF-8之间的转换用SysToUTF8 UTF8ToSys,UTF-8与UTF-16之间用UTF8ToUTF16
UTF16ToUTF8。


  以下LAZARUS和FREE PASCAL支持的字符串编码方式:
支持的编码方式
RTL(截止至2.6.0 ANSI
FCL(截止至2.6.0 ANSI
LAZARUS(包括LCL)0.9.25以前版本的 ANSI
LAZARUS(包括LCL)0.9.25及其以后版本的 UTF-8(除了gtk 1


  LCL库里大多数是可视控件,所以可视控件里的文本类型属性若要显示正确,从0.9.25开始传进去的需要UTF-8编码的字符串。而
  FREEPASCAL的核心库RTL FCL一直只支持ANSI,也就是程序运行所在操作系统的本地编码。

  说回 Length('Hellö Wöld') 问题,
  'Hellö Wöld'这类字符串常量,最初的编码是由.pas文件(或窗体的.lfm文件)的编码方式决定的。在LAZARUS的编辑窗点鼠标右键 File Settings=>Encoding那里可以设置。
若编码方式是UTF-8,UTF-8是变长的编码方式,英文只占1个字节,其它的占1~6个字节,‘ö’占2个字节,而Length函数属于RTL库,所以长度返回12.
若编码方式是ANSI,保存到文件时,‘ö’不能转换出ANSI对应的,所以用了一个莫名的字符代替。结果运行起来长度返回10.
建议在LAZARUS下,用UTF-8编码,网站上也是推荐用这编码。

详细请看:http://wiki.lazarus.freepascal.org/LCL_Unicode_Support

评分

参与人数 1威望 +7 收起 理由
bugxiong + 7 Lazarus社区有你更精彩!

查看全部评分

回复

使用道具 举报

该用户从未签到

发表于 2012-9-12 07:31:34 | 显示全部楼层
学习了,谢谢LZ
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-9-12 16:32:40 | 显示全部楼层
高文章啊。
求教下
若编码方式是ANSI,保存到文件时,‘ö’不能转换出ANSI对应的,所以用了一个莫名的字符代替。结果运行起来长度返回10.
这个应该怎么解决??
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-9-13 22:47:56 | 显示全部楼层
更正一点:
在看了有关源代码后,发现对于LAZARUS,ANSI编码应该不是本地操作系统的编码体系,因为从转换过程来看没识别当前系统环境。具体是哪套编码标准暂时不清楚,估计DELPHI的ANSI编码应该是本地编码,否则早有BUG汇报了。

对于DELPHI2007,也有类似机制,在编辑窗口点右键File Format=>...就可以将源代码文件按设置的编码规则保存。但DELPHI的编译器能在编译时把字符串常量统一转换成ANSI编码。
然而对于LAZARUS,FPC在编译时并没有把字符串常量统一转换成UTF-8或者ANSI,而是源代码是什么编码那么字符串就是什么编码。

而且,LAZARUS在源代码的处理上好像有BUG:
1.编辑器不能自动识别源代码的编码规则。
2.如果选UTF-8 WITH BOM,LENGTH函数不能正确处理‘Hellö Wöld’
3.如果选ANSI,在编辑源代码时有时会死掉LAZARUS。


所以,如果想源代码在DELPHI和LAZARUS下通用,编码方式只能选UTF-8。
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-9-26 12:16:06 | 显示全部楼层
用UTF8ToAnsiString
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2013-7-25 12:51:31 | 显示全部楼层
回复 支持 反对

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-2 00:19 , Processed in 0.079122 second(s), 13 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表