Powerbuilder:UTF-8的ImportFile(将UTF-8转换为ANSI)

时间:2014-03-11 21:25:02

标签: utf-8 powerbuilder datawindow

我的Powerbuilder版本是6.5,不能使用更高版本,因为这是我支持的。

我的问题是,当我在做dw_1.ImportFile(文件)时,第一行和第一列有一个有趣的字符串,如下所示:



在我尝试打开文件并将其保存到新的文本文件并尝试导入新文件之前我不明白。在没有搞笑字符串的情况下,它完美无缺地工作。

我的结论是发生了这种情况,因为文件是UTF-8(如NOTEPAD ++中所示),新文件是Ansi。我试图导入的文件是由第三方自动提供的,我的用户不希望这样做的额外工作。

如何在powerbuilder中强制将此文件转换为ANSI。如果没有,我可能要做一个命令提示转换,任何想法?

1 个答案:

答案 0 :(得分:3)

奇怪的字符是(可选的)utf-8 BOM,告诉编辑文件是utf-8编码的(因为除非我们在代码127之上遇到转义字符,否则很难知道它) 。你不能把它搞清楚,因为如果你的文件包含127以上的任何字符(重音或任何特殊字符),你显示的数据中仍然会有垃圾(例如:é - > é - > €,...)其中特殊字符将变为2到4个垃圾字符。

我最近需要将一些utf-8编码的字符串转换为" ansi" Windows 1252编码。使用PB10 +版本,utf-8和ansi之间的重新编码就像

一样简单
b = blob(s, encodingutf8!)
s2 = string(b, encodingansi!)

但是string()blob()在PB版本10之前不支持编码规范。

您可以自己阅读文件,跳过BOM,要求Windows通过MultiByteToWideChar() + WideCharToMultiByte()转换字符串编码,然后在ImportString()中加载转换后的字符串}。

获取文件内容的概念证明(使用此读取方法,文件不能大于2GB):

string ls_path, ls_file, ls_chunk, ls_ansi
ls_path = sle_path.text
int li_file
if not fileexists(ls_path) then return

li_file = FileOpen(ls_path, streammode!)
if li_file > 0 then
    FileSeek(li_file, 3, FromBeginning!) //skip the utf-8 BOM

    //read the file by blocks, FileRead is limited to 32kB
    do while FileRead(li_file, ls_chunk) > 0
        ls_file += ls_chunk //concatenate in loop works but is not so performant
    loop

    FileClose(li_file)

    ls_ansi = utf8_to_ansi(ls_file)
    dw_tab.importstring( text!, ls_ansi)
end if

utf8_to_ansi()是一个全局函数,它是为PB9编写的,但它应该与PB6.5一样:

global type utf8_to_ansi from function_object
end type

type prototypes
function ulong MultiByteToWideChar(ulong CodePage, ulong dwflags, ref string lpmultibytestr, ulong cchmultibyte, ref blob lpwidecharstr, ulong cchwidechar) library "kernel32.dll"
function ulong WideCharToMultiByte(ulong CodePage, ulong dwFlags, ref blob lpWideCharStr, ulong cchWideChar, ref string lpMultiByteStr, ulong cbMultiByte, ref string lpUsedDefaultChar, ref boolean lpUsedDefaultChar) library "kernel32.dll"
end prototypes

forward prototypes
global function string utf8_to_ansi (string as_utf8)
end prototypes

global function string utf8_to_ansi (string as_utf8);

//convert utf-8 -> ansi
//use a wide-char native string as pivot

constant ulong CP_ACP = 0
constant ulong CP_UTF8 = 65001

string ls_wide, ls_ansi, ls_null
blob lbl_wide
ulong ul_len
boolean lb_flag

setnull(ls_null)
lb_flag = false

//get utf-8 string length converted as wide-char
setnull(lbl_wide)
ul_len = multibytetowidechar(CP_UTF8, 0, as_utf8, -1, lbl_wide, 0)
//allocate buffer to let windows write into
ls_wide = space(ul_len * 2)
lbl_wide = blob(ls_wide)
//convert utf-8 -> wide char
ul_len = multibytetowidechar(CP_UTF8, 0, as_utf8, -1, lbl_wide, ul_len)
//get the final ansi string length
setnull(ls_ansi)
ul_len = widechartomultibyte(CP_ACP, 0, lbl_wide, -1, ls_ansi, 0, ls_null, lb_flag)
//allocate buffer to let windows write into
ls_ansi = space(ul_len)
//convert wide-char -> ansi
ul_len = widechartomultibyte(CP_ACP, 0, lbl_wide, -1, ls_ansi, ul_len, ls_null, lb_flag)

return ls_ansi
end function