dbf读取可能是关于字符集的一个问题,求解

homerlu 2005-10-25 04:28:30
多谢关注:
另一版的讨论:http://community.csdn.net/Expert/topic/4239/4239392.xml?temp=.8460962

/////////////////////////////////////////////////////////////
--------------------------------------------------------------------
测试文件下载:
请大家告诉大家,到这下载,在目录csdn里面的两个文件,test_rus.dbf、test_utf8.dbf
其栏位fullname为我所说的字段,分别为ISO Cyrillic 8859-5编码和utf-8编码
俄文test_rus.dbf和中文test_utf8.dbf

http://vip.sina.com.cn/cgi-bin/mydocument/share_list13.cgi?uid=homerlpx

-----------------------------------------------------------------------
问题:
我的原数据库是dbf文件的(德国客户公司提供的数据),我试用了两种方法进行处理:一、直接通过ado,dbf引擎读取dbf文件,结果数据出现了很多?,读出来的数据同dbf文件中的原数据比较,这些?都是把本不是0x3f的值转成了0x3f。二、通过sql语句将dbf转入mdb文件,发觉mdb文件中的数据已经不对了,那些数据也变成了0x3f。后来我试着用excel软件打开dbf文件,数据也是错误的(0x3f),而用foxpro软件打开dbf文件,里面的数据在界面上开上去是“?”(不能识别,所以显示为?)但察看实际数据却跟原数据相同,这说明foxpro读取成功了。但如何通过ado读取成功呢?

-----------------------------------------------------------------------
我的读取代码:
CString strQuaryValue, strGB;
varTheVarlue = m_pRecordset->Fields->GetItem(_variant_t("fullname"))->Value;
if (varTheVarlue.vt != VT_NULL && varTheVarlue.vt != VT_EMPTY)
{
strQuaryValue = (char*)(_bstr_t)varTheVarlue;
UTF82GB(strQuaryValue, strGB);//自己写的转换函数
}
...

-----------------------------------------------------------------------------
字符转换:
读取出来的数据经下面的函数转换就可以使用了,中文的在中文系统下,俄文的要在俄文系统下看。没有俄文系统的俄文转后可能还是乱码,可以使一下中文的处理,过程是一样的

中文的转换
int UTF82GB(CString &strUni, CString & strGB)
{
char * pszGB = NULL;

char* pszUTF8 = strUni.GetBuffer(0);

wchar_t * pwszUnicode = NULL;

int nLen = MultiByteToWideChar (CP_UTF8, 0, pszUTF8, -1 ,NULL, 0);
pwszUnicode = new wchar_t[nLen];
memset(pwszUnicode, 0, nLen);

MultiByteToWideChar(CP_UTF8, 0, pszUTF8, -1, pwszUnicode, nLen);

nLen = WideCharToMultiByte(936, 0, pwszUnicode, nLen, NULL, 0, NULL, NULL);
pszGB = new char[nLen];
memset(pszGB, 0, nLen);
WideCharToMultiByte(936, 0, pwszUnicode, -1 , pszGB, nLen, NULL, NULL);

strGB = CString(pszGB);
strUni.UnlockBuffer();

delete [] pwszUnicode;
delete [] pszGB;

return strGB.GetLength();
}

ISO Cyrillic 8859-5编码到俄文的转换
int Cyrillic2RU(CString &strCyrillic, CString & strRU)
{
char * pszRU = NULL;

char* pszUTF8 = strCyrillic.GetBuffer(0);

wchar_t * pwszUnicode = NULL;

int nLen = MultiByteToWideChar(28595, 0, pszUTF8, -1 ,NULL, 0);
pwszUnicode = new wchar_t[nLen];
memset(pwszUnicode, 0, nLen);

MultiByteToWideChar(28595, 0, pszUTF8, -1, pwszUnicode, nLen);

nLen = WideCharToMultiByte(1251, 0, pwszUnicode, nLen, NULL, 0, NULL, NULL);
pszRU = new char[nLen];
memset(pszRU, 0, nLen);
WideCharToMultiByte(1251, 0, pwszUnicode, -1 , pszRU, nLen, NULL, NULL);

strRU = CString(pszRU);

delete [] pwszUnicode;
delete [] pszRU;

return strRU.GetLength();
}

...全文
528 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
homerlu 2005-11-13
  • 打赏
  • 举报
回复

问题还没解决,陷入困境了
先结贴给分了
谢谢诸位!
cn_popeye 2005-10-29
  • 打赏
  • 举报
回复
这是把dbf表里的字符读取出来。
现在我需要把阿拉伯文写入dbf,怎么做呀?
如下帖
http://community.csdn.net/Expert/TopicView1.asp?id=4358849
homerlu 2005-10-28
  • 打赏
  • 举报
回复
哦了,我忘了我这个问题

“二、通过sql语句将dbf转入mdb文件,发觉mdb文件中的数据已经不对了,那些数据也变成了0x3f。后来我试着用excel软件打开dbf文件,数据也是错误的(0x3f),而用foxpro软件打开dbf文件,里面的数据在界面上开上去是“?”(不能识别,所以显示为?)但察看实际数据却跟原数据相同,这说明foxpro读取成功了。但如何通过ado读取成功呢?”

其实在我读取之前,也就是说在我将dbf文件转入mdb时,数据就已经不对了。
将其转为mdb的目的就是可以建索引,可以提升检索速度。因为dbf也有索引,但我并不知道vc怎么用。
由dbf转为mdb的sql语法:SELECT * INTO [tablenameinmdb] IN '[mdbfilename]' FROM [dbffilename]

我有些束手无策啊
zsjiaming 2005-10-28
  • 打赏
  • 举报
回复
不知你的软件是如何做的,要做成什么样.
windows系统也是使用unicde编码,winnt 是ucs-2 win2000是utf-16

UTF-16 可以在UCS-2下无损使用

但UTF-8 虽然在网络方面是用的比较多的,但UCS-2和UTF-16对它的支持并不好.

ADO使用的是unicode编码应该是utf-16.所以对于utf-8部分数据会损坏.

如果你是用来做管理系统的,建议你使用utf-16编码,输入的数据不是这种编码就转成这种编码.
输出时当然可以转成对方想要的编码.

sql2000使用的是UCS-2编码形式.

直接支持utf-8的数据库是oracle

如果要用ADO连接数据,看看用2.5版或以上的二个新对象record stream,其它stream有个charset属性可以支持uft-8,具体如何没用过.

zsjiaming 2005-10-26
  • 打赏
  • 举报
回复
af->3f .....原因不太清楚.
可能原因:
AF是第9个字节,这个字节的最高低被干掉了.而前8个字节没问题,我想系统可能把前8个当成双字节字符处理,如果只有一个字节是大于0x7f,所以被转换了.


倒是找到一个方法可以解决3F的问题.

ado 控件里有个recordset对象,此对象有个属性是Charset
把这个属性赋值为"UTF-8"(注意是大写),读取资料应该没问题(对于utf-8这种编码)
VC不知怎么写,不知是不是下面这样:

m_pRecordset->Charset="UTF-8"

十豆三 2005-10-26
  • 打赏
  • 举报
回复
VC不知道。

如果你就这一个表需要转换,可以用上面方法转换了,然后再用VC读。

如果你有很多表,又是不断生成,即要做成接口方式,那就用VFP做一个程序或DLL,然后由VC调用即可。
homerlu 2005-10-26
  • 打赏
  • 举报
回复
不过也是,这是vfp的地盘,不过总算知道vfp的读取过程了
谢谢两位
顺便问一下,知道不知道vc的读取方式
homerlu 2005-10-26
  • 打赏
  • 举报
回复
VFP里的啊,我不会用啊
我晕哦,狂晕
十豆三 2005-10-26
  • 打赏
  • 举报
回复
Strconv是VFP里的函数,不过VFP7以上才有。

*--------------------------------------
以下为此函数的说明:
在单字节, 双字节, UNICODE, 和本地特定表示字符间进行字符表达式转换。

STRCONV(cExpression, nConversionSetting [, nLocaleID])
返回值
字符型。返回转换后的字符表达式。

参数
cExpression
要 STRCONV( ) 转换的字符表达式。
nConversionSetting
转换类型。下表列出 nConversionSetting 值和可执行的转换类型: nConversionSetting 转换
1 将 cExpression 中的单字节转换为双字节
2 将 cExpression 中的双字节转换为单字节
3 将 cExpression 中的双字节 Hiragana 字符转换为双字节的 Katakana 字符
4 将 cExpression 中的双字节 Katakana 字符转换为双字节 Hiragana 字符
5 将双字节转换为 UNICODE(宽字符)
6 将 UNICODE(宽字符)转换为双字节
7 转换为与地区相关的小写形式
8 转换为与地区相关的大写形式
9 转换 cExpression 中的双字节字符到 UTF-8
10 转换 cExpression 中的 Unicode 字符到 UTF-8
11 转换 cExpression 中的 UTF-8 字符到双字节字符。
12 转换 cExpression 中的 UTF-8 字符到 UNICODE 字符。
13 转换 cExpression 中的单字节字符到编码后的 base64 二进制。
14 转换 cExpression 中的单字节字符到解码后的 base64 二进制。
15 转换 cExpression 中的单字节字符到编码后的 hexBinary。
16 转换 cExpression 中的单字节字符到解码后的 hexBinary。

nLocaleID
指定用于转换的 Locale ID。如果 nLocaleID 无效,或计算机不支持,则造成 "Invalid locale ID" 错误。如果省略 nLocaleID,则在默认情况下使用系统的 Locale ID。 nLocaleID 语言
1029 捷克
1031 德国
1033 英语 (默认)
1034 西班牙
1036 法语
1040 意大利语
1045 波兰
1046 葡萄牙语 (巴西)
2070 葡萄牙语 (葡萄牙)

备注
该函数在操作象 Hiragana 和 Katakana 这样的双字节字符集语言时是有用的。
homerlu 2005-10-26
  • 打赏
  • 举报
回复
这确实应该是对的
我得到的结果是“大连?”
不过能否详细介绍一下你的读取过程,你的查询语句我不太会用。谢谢
Strconv是sql里面的函数吗?
十豆三 2005-10-26
  • 打赏
  • 举报
回复
zsjiaming(路口就在不远处)

的方法应该就可以了。
zsjiaming 2005-10-26
  • 打赏
  • 举报
回复
Utf8 中文没问题.因为俄文不能正常显示,所以不知得到的数据是不是正确

中文的这样处理:

Select Strconv(test_utf8.FullName,11) As fullnmae From test_utf8 Into Cursor test_un

得到的test_un中fullname的内容如下,应该是正确,但俄文无法确定...
Liaoyuan Rd. (W.)
liao yuan xi lu
辽源西路
Dalian Rd.
da lian lu
大连路
Xuchang Rd.
xu chang lu
许昌路
Kunming Rd.
kun ming lu
昆明路
Zhoujiazui Rd.
zhou jia zui lu
周家嘴路
Dalian Rd.
da lian lu
大连路
.......................
homerlu 2005-10-26
  • 打赏
  • 举报
回复
多谢你的分析,
我的转换没问题。没错的关键是我读取出来的数据不对
我读取出来的为
E5 A4 A7 E8 BF 9E E8 B7 3F
而数据是E5 A4 A7 E8 BF 9E E8 B7 AF
我发觉出问题的数据都是读取出来变成了3F,不知道什么原因。
zsjiaming 2005-10-26
  • 打赏
  • 举报
回复
仔细看了一下utf-8的编码,它是8位编码,对于一个汉字要3个字节才能存贮.

而楼主能把"大连?",说明你已经正确转换了一部分编码.

对于16进制的双字节0800 - FFFF 转成为: 1110xxxx 10xxxxxx 10xxxxxx
"大连路"对应的UTF-8编码是 E5 A4 A7 E8 BF 9E E8 B7 AF (9个字节)

即然你能转换"大连",那么你要看看什么原因转换不了后一个字?

或者你把ADO读出的数据(原始数据,没转换的)按二进制形式写入一个文件.用winhex或其它二进制编辑软件看看它的编码是不是 E5 A4 A7 E8 BF 9E E8 B7 AF

看看问题出在哪里.
zsjiaming 2005-10-26
  • 打赏
  • 举报
回复
varTheVarlue = m_pRecordset->Fields->GetItem(_variant_t("fullname"))->Value

这是这样把ado中的数据赋直接给varThevarlue的.

这个varThevarlue是什么类型,是VC已经封装的字串类吗?
如果是VC的串类的话,你能不能用其它能支持utf-8的类型
我记得C有一个类型是unsign char ,这个应该支持utf-8吧.因为多年没用C了,帮不上忙.
zsjiaming 2005-10-26
  • 打赏
  • 举报
回复
对C不熟.

首先VC中的字串类是不是对utf-8支持?
如果不支持,你不应该用串这个类型处理,而要自已做一个类来处理这个数据.

其次这个表对方能不能改变数据类型,比如二进制备注字段可能会更好.
这主要原因还是各语言下对字串的支持不是太好

如果VC直接做DBF应该也是可以的,查一下DBF表头格式,直接字段进行字节读取,
这样读取的字节是原始数据.然后处理成其它格式.当然只适合数据转换,不适合数据处理.
homerlu 2005-10-25
  • 打赏
  • 举报
回复
我的转换代码肯定是没问题的,这点我确定
但关键是我通过VC+ado读取出来的数据是错误的

我提供的下载数据中有中文utf8的数据,不一定要用俄文的做测试
但中文的也无法读取正确,现象是一样的
zsjiaming 2005-10-25
  • 打赏
  • 举报
回复
首先要搞清楚......能在简单系统正常显示俄语的字体是什么字休??

vfp中 可以使用 CPCONVERT(原代码页,转成代码页,字串) 转换代码页

但是我看那个表好象本身就是936代码页?,

因为你看到的是??是因为显示字体是宋体.
实际上在应该用西文字体,但不知是哪一个..

如果你找到了能正常显示字体的字体,那么才有可能知道这个字串转换是否正确.

十豆三 2005-10-25
  • 打赏
  • 举报
回复
这说明foxpro读取成功了。但如何通过ado读取成功呢?

*-------------------------------------------------

你想用什么工具(FOXPRO,VC还是...)通过ADO来读取
本系列课程分为,0-理论知识部分    0.1-oca_ocp_ocm相关知识内容(uploading)1-安装部分     1.1单实例命令行安装     1.2单实例图形安装     1.3rac安装     1.4rac(pdb架构)+dg 单实例安装(用rman的duplicate和rman备份2种方式搭建dg)     1.5rac(pdb架构)+rac dg2-迁移部分    2.1单实例之间的迁移    2.2单实迁移到rac    2.3rac迁移到单实例    2.4rac和rac之间的迁移。    2.5关于xtts的迁移方法的使用3-恢复部分   3.1单实例本地恢复   3.2rac本地恢复4-数据库升级部分   4.1 19.3升级到19.13   4.2 12.1.0.2升级到19.3   4.3 12.2.0.1升级到19.3   4.4 19.3的rac升级到19.135-数据库优化部分    5.1如何看懂执行计划    5.2 hash, nest loop,  merge的执行计划各自适用于那种场景?    5.3为什么要用直方图,19c的直方图有frency, balance,  top-frenkency, hybrid?允许最大的bucket是多少?6-数据库asm磁盘操作部分   6-1如何用一条命令迁移rac存储。   6-2如何用笨方法迁移rac存储。   6-3目前asm磁盘是external冗余级别,如何修改为normal的冗余级别。7-数据库工具部分   7.1oem如何进行安装,如何进行纳管数据库,如何使用   7.2如何用oem监控数据库 8-综合实战。   a库是11.2.0.3的单实例数据库,容量有20T。   b库是19.13的rac环境的pdb数据库,容量只有21T.   如何把a库的数据迁移到b库的pdb数据库?   这个综合实战非常考验大家,基本上囊括了数据库复制安装,数据库dg,数据库升级的方方面面。   大家可以自己先想想怎么实现。一课程主题手把手带大家进行实操,在实操中提升自己手把手带大家学习orace 19的ocm课程,学完本课程,至少具有3-5年oracle数据库水平。文档和视频is uploading. 二课程特色 学oracle,找阿伟阿伟出品,必属精品从实战出发,贴近实战,自己实战,实战为王,在实战中提升自己授人以鱼不如授人以渔通过此系列课程可以提高3-5年oracle水平交个朋友,物有所值,诚意满满走心课程,把自己在运维中的坑,提炼知识后,实战给大家 三课程内容 0.理论知识部分(上传中。。。)   0.1数据库监听(动态监听,静态监听,多个ip同时监听1521,一个ip监听多个service_name)   0.2rman 命令中的set rename datafile和 alter database  rename datafile 有啥区别?   0.3    ............1.数据库单实例安装  1.0 安装检查    1.0.1安装包检查    1.0.2修改系统参数    1.0.3数据库用户创建    1.0.4创建目录    1.0.5上传安装软件包    1.0.6修改oracle用户环境变量  1.1 rhel7系统图形安装oracle 19c单实例数据库  1.2 rhel7系统命令行安装       1.2.0命令行安装数据库软件       1.2.1命令行创建non cdb数据库实例       1.2.2命令行创建 cdb数据库实例2.rac数据库安装    1.课程结束成果演示          1.1 用workstation,安装一套rhel7+oracle19c+rac+multipath+共享存储+DNS服务器+DNS客户端+NTP服务器+NTP客户端的生产环境          1.2 怎样打oracle19c的rac补丁(包括GI补丁,oracle补丁,数据库补丁,OJVM补丁,bug补丁)     2.安装openfiler软件,模拟共享存储+配置多路径访问       2.1安装openfiler软件       2.2配置openfiler软件(配置2个虚拟网卡,模拟服务器的2个HBA卡)        2.3创建ocr磁盘       2.4创建mgmt磁盘       2.5创建数据文件磁盘       2.6创建归档日志磁盘     3.安装2台数据库服务器       3.1安装2台数据库服务器RHEL7.5       3.2配置服务器双网卡绑定+配置服务器心跳线     4.安装多路径软件识别共享存储中的磁盘        4.1安装服务器本地yum源        4.2安装iscsi软件,配置多路径配置文件,识别共享存储中的磁盘        4.3识别ocr磁盘        4.4识别mgmt磁盘        4.5识别数据文件磁盘        4.6识别归档日志磁盘     5.oracle19c的rac环境系统参数官方说明        5.1如何配置oracle19c的rac的系统参数(我们参考官方说明)        5.2oracle19c+rac环境Best Practices 官方说明文档     6.安装oracle19c+rac之前的准备工作        6.1修改/etc/hosts文件        6.2配置DNS服务器+DNS客户端+NTP服务器+NTP客户端        6.3创建用户和组        6.4创建目录        6.5修改用户环境变量        6.6安装相关软件包        6.7配置ssh互信        6.9禁用服务器透明大页     7.安装oracle+19c+rac软件       7.1安装GI软件       7.2创建ASM磁盘,主要是数据文件磁盘和归档日志磁盘       7.3安装数据库软件       7.4创建数据库实例       7.5日常常用维护集群命令(启停数据库,启停集群,查看监听,教同学们怎样不死记命令,而且命令还正确)     8.打补丁     8.1打GI和ORACLE的操作系统补丁      8.2打OJVM补丁      8.3打ORA600的bug补丁     9.课程总结和成果演示     9.1课程总结和成果演示3.rac+dg(单实例)数据库安装(pdb架构)     3.1.1dg知识点讲解     3.1.2配置dg监听,密码文件,参数文件。     3.1.2通过rman的duplicate命令进行dg搭建1。     3.1.3通过rman的duplicate命令进行dg搭建2     3.1.4进行数据库切换需要的配置。     3.1.5数据库正常switch over     3.1.6数据库如何fail over     3.1.7dg库failover以后通过闪回快速恢复dg     3.1.8dg库failover以后通过新主库的控制文件快速恢复dg     3.1.9备库归档缺失如何进行解决。     3.1.10recover database和recover standby database是否可以在dg中使用?     3.1.11如何通过rman的备份进行搭建dg。     3.1.12dg库使用静态监听无法监听pdb数据库的service问题如何进行解决?   4.rac+rac dg的实战步骤(pdb架构)(上传中。。。)5.19c单实例数据库通过rman备份进行异机迁移到单实例数据库     5.1通过备份脚本进行数据,归档,控制文件备份     5.2通过备份脚本进行归档,控制文件备份       (注意源库备份目录是/backup/db和/backup/ar)     5.3传输备份文件到目标库        (传输备份文件到目标库的/home/oracle/bk目录)     5.4利用参数文件启动数据库到nomount     5.5利用备份集恢复控制文件,并启动数据库到mount     5.6通过restore database恢复数据库        5.6.1注册目标库备份集到控制文件        5.6.2启动数据库到mount状态,确定recover database的序列号     5.7recover database        5.7.1通过rman 进行recover database        5.7.2通过sql 命令行进行 recover database;     5.8.打开数据库          5.8.1解决打开数据库后,sys用户无法远程监听登录问题          5.8.2修改数据库动态参数启动数据库     5.9.备份的扩展             5.9.1如何知道备份集里面有哪些归档             5.9.2如何从这些备份集中提取归档             5.9.3进行异机数据库迁移时,如何逐步应用归档,并且如何open read only数据库后,继续应用归档             5.9.4为何要进行 open read only进行提前打开验证。               5.10.rman迁移备份的补充             5.10.1如何再rman中设置数据文件,在线日志生成路径。               类似如下命令                    run  6单实例数据库无数据丢失通过rman备份异机迁移到rac数据库和rac数据库通过rman迁移到rac数据库      6.1单实例源库进行数据库升级           19.3的源库升级到19.13版本(包括打数据库补丁和ojvm补丁)      6.2.传输备份文件到目标库           传输备份文件到目标库的/home/oracle/bk目录     6.3.利用参数文件启动数据库到nomount     6.4.利用备份集恢复控制文件,并启动数据库到mount        6.5.通过restore database恢复数据库           注册目标库备份集到控制文件           启动数据库到mount状态,确定recover database的序列号     6.6.recover database          通过rman 进行recover database          通过sql 命令行进行 recover database;     6.7.单实例数据库恢复完成后,配置为rac数据库           注册数据库到集群          修改数据库参数文件到asm     6.8.迁移rac数据库到rac数据库。           单实例数据库异机迁移到rac和,rac数据库异机迁移到rac有啥不一样。           根据上面理论,实施rac数据库异机恢复到rac7数据库本地恢复系列     7.1单实例数据库本地恢复     7.2rac数据库本地恢复8综合实战(uploading)     7.1实战课题:        有一台11.2.0.3的单实例数据库A,数据库容量有20T,无备份。        如何迁移到新搭建的rac环境B(数据库版本是19.13),并且是迁移到rac的pdb数据库中,并且rac数据库的asm容量只有21T.        这次实战包含的知识点。        1-如何在环境B复制数据库A的软件,最好进行复制,因为数据库A的11.2.0.3打了很多补丁,如果安装11.2.0.3软件,会造成版本不一致。        2-如何搭建11.2.0.3的单实例dg。        3-dg归档缺失如何解决。        4-如何升级11.2.0.3单实例到11.2.0.4单实例        5-如何升级11.2.0.4单实例到19.3单实例        6-如何升级19.3单实例到19.13单实例。        7-如何迁移19.13单实例数据库到19.13的rac的pdb数据库中。9数据库升级系列     8.1 单实例19c数据库升级到19.13版本。     8.2 单实例12.2.0.1数据库升级到19.13版本。     8.3 单实例12.1.0.2数据库升级到19.13版本。     8.4 19c数据库rac升级到19.13版本。

2,723

社区成员

发帖
与我相关
我的任务
社区描述
VFP,是Microsoft公司推出的数据库开发软件,用它来开发数据库,既简单又方便。
社区管理员
  • VFP社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧