DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: will123wi
今日帖子: 21
在线用户: 6
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/10 20:41:54
标题:
读取文本时,多字节编码被截断时如何处理 浏览:752
加入我的收藏
楼主: Windows下的默认编码是Ansi,处理多字节编码如果遇到一个字符被截断,如三字节的Unicode或双字节的GB2312/GB18030只读了一个字节,这种情况正规的处理方式是什么。

问题源自:我用QDAC里的QXML读GB2312编码的文件,有的源文件因为生成时的字段长度有限制,且中英文混杂,有时可能某文本域的最后一个字符被直接截断,只写了一个字节,读到这里时会报错。一般文本编辑器打开这类文件也会报错,而且显示的是一个怪字符。
经常一次性读取几百兆大小的XML文件,偶尔碰到这个问题弹窗时挺崩溃的。我又没办法要求源文件加大字段长度限制。

大家在日常工作中一般是怎么处理的。
----------------------------------------------
-
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2024/3/10 22:01:34
1楼: XML有标头。。
不规范的 总要识别的。
不识别就处理绝对截断啊
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2024/3/10 22:25:51
2楼: xml是一种标准, 不是正则表达式,  为什么会有长度这种说法?
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/10 22:40:09
3楼: 可能没描述清楚

比如<name>namestring</name>
namestring是一个最长50Byte的GB2312字符串,因为有英文等单字节字符,一个超过50Byte的字符串写入时,可能到第49Byte的时候刚好写完一个字符,下一个是双字节的字符,因为XML生成源的问题(多个厂家的不规范写入,我无法控制),第50个字节直接写了双字节字符的第一个字节。

几百万行的XML,一次处理好几个,只是偶尔有一个文件的某行出现这种情况,如果为了避免这种情况,每行都去识别截断,效率太低了。
----------------------------------------------
-
作者:
男 supermay (supermay) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 8:48:47
4楼: <name></name>之间的不就是完整的字串吗?
----------------------------------------------
链接:https://pan.baidu.com/s/12jzmECYKhGCsHBxz8tmB6w 提取码:pelr --来自百度网盘超级会员V9的分享
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 9:06:13
5楼: 所有文本进内存二话不说全部转成unicode再处理
----------------------------------------------
-
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 9:07:41
5楼: 我又看了一下源文件,出错的地方还是我描述错了
因为GB2312对ASCII码(0-127)之后的字符都采用两个字节表示,高位字节和低位字节都大于0x7F

如果读取的是一个大于0x7F的字节,会接着读取后一个字节作为一个字符,如果这个字符出现在字符串中间,无非解析出来就是一个怪异的字符

出错的地方刚好是namestring最后一个字节,解析时就连带把</name>的<作为第二个字节吞了
----------------------------------------------
-
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 9:18:18
6楼: 这种情况,你可以在GB2312编码的情况下, 用字符串替换,将所有的'</'子串,替换为#13'</'子串

若想更保险,可以用正则将'(\</\w+\>)'替换为'\n\1'
----------------------------------------------
-
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 9:40:03
6楼: XMLSpy能正确识别,文本编辑器会老老实实按多字节去显示
此帖子包含附件:
JPEG 图像
大小:81.0K
----------------------------------------------
-
作者:
男 jwj76 (禁卫) ▲△△△△ -
普通会员
2024/3/11 9:53:12
7楼: 用WideString类型可以处理中文字符。
----------------------------------------------
-
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2024/3/11 18:20:47
8楼: gb2312包括后续扩展的gbk其实都可以直接当作ansi处理的,如果出乱码就说明你这个编码不对。至于你说的截断,应该是全角字符占2BYTE,但是你计算长度的时候没有区别导致从中间截断而出现乱码吧?
先转成utf8或者utf16也就是widestring,然后就不会有这种问题了。
----------------------------------------------
--
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/11 19:10:04
9楼: 源生文件就是GB18030的,只是我看基本都用的双字节GB2312部分。
300MB+的XML文件,而且是多个,几乎每天都会更新,转utf8太费事了。
----------------------------------------------
-
作者:
男 jwj76 (禁卫) ▲△△△△ -
普通会员
2024/3/11 21:36:38
10楼: 以下是读取文件的代码
ms:TMemoryStream;
stlist:TStringList ;


ms:=TMemoryStream.Create;
ms.LoadFromFile(filename);
 //读取Unicode编码
     ms.Seek(2,soFromBeginning);
     stlist.LoadFromStream(ms,TEncoding.Unicode);
stlist.Text中就是文字了
----------------------------------------------
-
作者:
男 bahamut8348 (leonna) ★☆☆☆☆ -
普通会员
2024/3/11 23:45:42
11楼: GB18030和GB2312是不一样的哟,你可以把这个GB18030看作国产的UTF8,具体资料可以去查一下。
windows系统可以直接用multibytetowidechar函数转换,参数指定18030编码就是了。
linux则可以根据local函数配套转换,也就是setlocal(...)配合mbstowcs函数,
delphi里应该也会有对应的函数,查一下就没问题了。
----------------------------------------------
--
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
2024/3/12 10:37:12
12楼: GB18030是GBK的超集,GBK是GB2312的超集,它们三者是向下兼容的
GB18030对比GBK多出了4字节编码的字符,所以GB18030可以表达完整的Unicode字符集
----------------------------------------------
-
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/12 10:37:17
12楼: GB18030的双字节部分就是GB2312

我想了一下,按编码去从头开始逐字节解码的思路行不通,因为源文件在写文件时就没有严格按照编码来,这也就是为什么文本编辑器都无法“正确理解”文件,而XMLSpy是按照不完全匹配去解析的,也就是要先向后读结束标签,所以能正确提示并显示,其实已经做了补全修正。
----------------------------------------------
-
作者:
男 bighawk (Hawk) ★☆☆☆☆ -
盒子活跃会员
2024/3/12 11:45:22
13楼: 不知道你们在讨论啥……这种情况下,就别用现成的XML解析类来做了呗。先把 XML 文本当作 ansi 即可,自己解析出字符串,再尝试用UTF8或者ANSI或者其他来转换即可。哪一种类型转换不出错就是哪一种喽
----------------------------------------------
-
作者:
男 mlskin (mlskin) ▲▲▲▲△ -
普通会员
2024/3/12 14:37:13
14楼: 有一个函数,ByteType(),用于判断字符串中的某个字节是单字节字符,双字节字符的第一个字节,还是双字节字符的第二个字节。
除了这个函数,SysUtils单元里面还有其它的一些处理字符函数,可以去看看

https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.SysUtils.ByteType
----------------------------------------------
Delphi MlSkin 它能让你的程序拥有像QQ一样多彩炫丽的外观http://www.pngui.com;http://www.xeframework.com
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行78.125毫秒 RSS