简体转繁体乱码

Description of your first forum.

简体转繁体乱码

帖子fuyou » 星期四, 2010年12月9日 09:52


1、重装操作系统之前编译的程序是正常的:在简体系统显示的是简体,繁体系统或英文系统显示的是繁体;用以前的程序现在运行还是正常的。
2、重装操作系统之后对程序重编译后却不正常了:简体系统下使用正常,繁体系统或英文系统下就出现了乱码;
3、怀疑是操作系统设置或delphi第三方控件不同,导致编译后的文件差异,但是什么却不知道。

主要函数如下:
function TSysFunc.GBToBig5(GBStr: string): string;
var
  Len: Integer;
  pGBCHTChar: PChar;
  pGBCHSChar: PChar;
  pUniCodeChar: PWideChar;
  pBIG5Char: PChar;
begin
  pGBCHSChar := PChar(GBStr);
  Len := MultiByteToWideChar(936, 0, pGBCHSChar, -1, nil, 0);
  GetMem(pGBCHTChar, Len * 2 + 1);
  ZeroMemory(pGBCHTChar, Len * 2 + 1);
  //GB CHS -> GB CHT
  LCMapString($804, LCMAP_TRADITIONAL_CHINESE, pGBCHSChar, -1, pGBCHTChar, Len * 2);
  GetMem(pUniCodeChar, Len * 2);
  ZeroMemory(pUniCodeChar, Len * 2);
  //GB CHT -> UniCode
  MultiByteToWideChar(936, 0, pGBCHTChar, -1, pUniCodeChar, Len * 2);
  Len := WideCharToMultiByte(950, 0, pUniCodeChar, -1, nil, 0, nil, nil);
  GetMem(pBIG5Char, Len);
  ZeroMemory(pBIG5Char, Len);
  //UniCode -> Big5
  WideCharToMultiByte(950, 0, pUniCodeChar, -1, pBIG5Char, Len, nil, nil);
  Result := string(pBIG5Char);
  FreeMem(pBIG5Char);
  FreeMem(pGBCHTChar);
  FreeMem(pUniCodeChar);
end;

function TSysFunc.getDisplay(const input: string): string;//****INPUT 即为要显示的原字符
begin
    if (GetOEMCP = 936) then
    begin
      Result := input;
    end
    else if (GetOEMCP = 950) then //繁体系统
    begin
      Result := GBToBig5(input);
    end
    else
    begin
      Result := GBToBig5(input);
    end;

end;
 
 
 

简体转繁体乱码

帖子fuyou » 星期四, 2010年12月9日 09:58


有知道的吗?[:)]
 
 
 

简体转繁体乱码

帖子fuyou » 星期四, 2010年12月9日 12:10


补充:DELPHI 7
 
 
 

简体转繁体乱码

帖子zbdzjx » 星期四, 2010年12月9日 23:29


或者是字体不对???
 
 
 

简体转繁体乱码

帖子Racer_y » 星期五, 2010年12月17日 21:15


这行代码我觉得有问题:
  MultiByteToWideChar(936, 0, pGBCHTChar, -1, pUniCodeChar, Len * 2);
 
这句是假设pGBCHTChar是936(中文简体)代码页下的字符。

从你程序上看,pGBCHTChar实际是从getDisplay的参数“input”传入,也是就说,
当你调用getDisplay函数的时候,你假设参数“input”是中文简体下的字符编码,
但实际上,可能不是。若不是的话,转换出来肯定是乱码。

若你保证“input”一定是中文简体下的字符编码,那我就分析不出原因了,希望有
另外的高人解答:)
 
 
 

简体转繁体乱码

帖子zbdzjx » 星期五, 2010年12月17日 23:05


如果代码一点都没改就不对了,那就和代码没有关了。
感觉应该和unicode有关,是不是需要装个第三方控件来支持unicode,或是系统设一下,能够支持unicode。
 
 
 

简体转繁体乱码

帖子Racer_y » 星期日, 2010年12月19日 11:32


这个问题只能用调试的方法去解决,重新编译一个程序,里面只显示两个汉字,比如“你好”,看看在繁体下显示成什么。

“你好”在代码页936的字符编码为0xE3C4 0xC3BA;
“你好”的unicode的字符编码为0x4F60 0x597D;

也就是说,在函数getDisplay里加调试语句
function TSysFunc.getDisplay(const input: string): string;//****INPUT 即为要显示的原字符
begin
assert(length(input)=4, '长度不为4');
assert(Ord(input[1])=$C4, '非中文简体编码');
assert(Ord(input[2])=$E3, '非中文简体编码');
assert(Ord(input[3])=$BA, '非中文简体编码');
assert(Ord(input[4])=$C3, '非中文简体编码');
....
end.

若出现断言错误,可以确定,传入的字符串编码不是中文简体编码。

若没出现断言错误,但在繁体下显示还是乱码,看看转换成unicode后的编码是否是
0x4F60、0x597D。

...
MultiByteToWideChar(936, 0, pGBCHTChar, -1, pUniCodeChar, Len * 2);
assert(Ord(pUniCodeChar[0])=$4F, '不是期望的unicode编码');
assert(Ord(pUniCodeChar[1])=$60, '不是期望的unicode编码');
assert(Ord(pUniCodeChar[2])=$7d, '不是期望的unicode编码');
assert(Ord(pUniCodeChar[3])=$59, '不是期望的unicode编码');
....

这样用排除法一步步的排除原因。
 
 
 

简体转繁体乱码

帖子fuyou » 星期二, 2010年12月28日 16:18


"INPUT" 是简体,取的是ORACLE数据库中的数据(简体),但是奇怪,在英文系统下不经过转换,直接显示时是乱码
 
 
 

简体转繁体乱码

帖子Racer_y » 星期二, 2010年12月28日 19:09


从逻辑上我觉得这不大可能,但从你描述的情况,这又的确发生了。

这可以用调试的手段去解决。在getDisplay里,写log文件,记录每个input字符的
ASCII码(最好用16进制表示),再记录每个转换后的结果result的每个字符的
ASCII码。

这样,可以看看是不是输入的参数(input)有错,或者是转换的结果(result)有错。
如都没有错,再看看是不是显示的问题(这可能性我觉得很小,最大的可能性是
输入的参数有错)
 
 
 

简体转繁体乱码

帖子fuyou » 星期五, 2010年12月31日 14:14


最后解决的办法是,在 ORASESSION 里将 CHARSET 设成 ZHS16CGB231280,就可以,但为什么以前程序没有这样设置也是可以的呢?