将字符串从代码页 1252 转换为 1250 并返回
Convert string from codepage 1252 to 1250 and back
我使用 Delphi 7(基于 ANSI)。我需要在代码页之间转换字符串。我在网上找到了一个使用 multiByteToWideChar 和 wideCharToMultiByte 函数的解决方案。但正如我所看到的那样,它不起作用。我可以将 1250 转换为 1252,但另一种方式不太好。
这是我的测试代码:
procedure TForm1.Button1Click(Sender: TObject);
function ANSIToUTF8( text_ : string; codePage_ : cardinal ): string;
var
w : WideString;
sizeMB, sizeWC : integer;
begin
if ( codePage_ <> CONST_codepage_UTF8 ) then
begin
// ANSI_XXXX to UTF16
sizeMB := length( text_ );
sizeWC := multiByteToWideChar( codePage_, 0, PAnsiChar( text_ ), sizeMB, nil, 0 );
setLength( w, sizeWC );
multiByteToWideChar( codePage_, 0, PAnsiChar( text_ ), sizeMB, PWideChar( w ), sizeWC );
// UTF16 to UTF8
sizeMB := wideCharToMultiByte( CONST_codepage_UTF8, 0, PWideChar( w ), sizeWC, nil, 0, nil, nil );
setLength( result, sizeMB );
wideCharToMultiByte( CONST_codepage_UTF8, 0, PWideChar( w ), sizeWC, PAnsiChar( Result ), sizeMB, nil, nil );
end else
result := text_;
end;
function UTF8ToANSI( text_ : string; codePage_ : cardinal ): string;
var
w : WideString;
sizeMB, sizeWC : integer;
begin
if ( codePage_ <> CONST_codepage_UTF8 ) then
begin
// UTF8 to UTF16
sizeMB := length( text_ );
sizeWC := multiByteToWideChar( CONST_codepage_UTF8, 0, PAnsiChar( text_ ), sizeMB, nil, 0 );
setLength( w, sizeWC );
multiByteToWideChar( CONST_codepage_UTF8, 0, PAnsiChar( text_ ), sizeMB, PWideChar( w ), sizeWC );
// UTF16 to ANSI_XXXX
sizeMB := wideCharToMultiByte( codePage_, 0, PWideChar( w ), sizeWC, nil, 0, nil, nil );
setLength( result, sizeMB );
wideCharToMultiByte( codePage_, 0, PWideChar( w ), sizeWC, PAnsiChar( Result ), sizeMB, nil, nil );
end else
result := text_;
end;
procedure testString( s_ : string; icp_ : cardinal );
var
sutf : string;
s1250, s1252 : string;
pc : pchar;
function strToHex( s_ : string; ocp_ : cardinal ) : string;
var
i : integer;
begin
result := '';
for i := 1 to length( s_ ) do
begin
if ( i > 1 ) then
result := result + ', ';
result := result + TStringUtility.byteToHexaDecimalStr( ord( s_[i] ) );
end;
end;
procedure logInput;
var
s : string;
begin
s := 'Input (' + intToStr( icp_ ) + '): ' + strToHex( s_, icp_ );
listbox1.items.add( s );
end;
procedure logOutput( ocp_ : cardinal );
var
s : string;
begin
s_ := utf8toansi( sutf, ocp_ );
s := 'Output (' + intToStr( ocp_ ) + '): ' + strToHex( s_, ocp_ );
listbox1.items.add( s );
end;
begin
logInput;
sutf := ansitoutf8( s_, icp_ );
logOutput( 1250 );
logOutput( 1252 );
listbox1.items.add( '' );
end;
begin
testString( #$f5 + #$fa + #$fb, 1250 ); // õúû in 1250
testString( #f + #$fa + #, 1252 ); // õúû in 1252
end;
记录的结果不是加速的结果。它显示 api 调用将字符串从 1250 转换为 1252,但没有将 1252 转换为 1250。我将默认代码页更改为 1252,结果相同。
Input (1250): $f5, $fa, $fb
Output (1250): $f5, $fa, $fb
Output (1252): f, $fa,
Input (1252): f, $fa,
Output (1250): f, $fa,
Output (1252): f, $fa,
您的尝试是不可能的。 1250 中有一些字符在 1252 中不存在,反之亦然。
考虑您问题中的示例字符。让我们从1250中的$f5
开始。即ő
。现在,该字符在 1252 中不存在,因此系统无法执行您要求它执行的操作。相反,它会尽力而为,并且 returns f
在 1252 中是 o
。
然后从1252转换回1250就没有问题了,因为o
是ASCII码范围,可以正确转换。但是,系统当然无法返回到 ő
,当您转到 1252 时,该信息丢失了。
如果您需要处理 1250 或 1252 中的文本,那么显而易见的解决方案是使用 Unicode。
我使用 Delphi 7(基于 ANSI)。我需要在代码页之间转换字符串。我在网上找到了一个使用 multiByteToWideChar 和 wideCharToMultiByte 函数的解决方案。但正如我所看到的那样,它不起作用。我可以将 1250 转换为 1252,但另一种方式不太好。 这是我的测试代码:
procedure TForm1.Button1Click(Sender: TObject);
function ANSIToUTF8( text_ : string; codePage_ : cardinal ): string;
var
w : WideString;
sizeMB, sizeWC : integer;
begin
if ( codePage_ <> CONST_codepage_UTF8 ) then
begin
// ANSI_XXXX to UTF16
sizeMB := length( text_ );
sizeWC := multiByteToWideChar( codePage_, 0, PAnsiChar( text_ ), sizeMB, nil, 0 );
setLength( w, sizeWC );
multiByteToWideChar( codePage_, 0, PAnsiChar( text_ ), sizeMB, PWideChar( w ), sizeWC );
// UTF16 to UTF8
sizeMB := wideCharToMultiByte( CONST_codepage_UTF8, 0, PWideChar( w ), sizeWC, nil, 0, nil, nil );
setLength( result, sizeMB );
wideCharToMultiByte( CONST_codepage_UTF8, 0, PWideChar( w ), sizeWC, PAnsiChar( Result ), sizeMB, nil, nil );
end else
result := text_;
end;
function UTF8ToANSI( text_ : string; codePage_ : cardinal ): string;
var
w : WideString;
sizeMB, sizeWC : integer;
begin
if ( codePage_ <> CONST_codepage_UTF8 ) then
begin
// UTF8 to UTF16
sizeMB := length( text_ );
sizeWC := multiByteToWideChar( CONST_codepage_UTF8, 0, PAnsiChar( text_ ), sizeMB, nil, 0 );
setLength( w, sizeWC );
multiByteToWideChar( CONST_codepage_UTF8, 0, PAnsiChar( text_ ), sizeMB, PWideChar( w ), sizeWC );
// UTF16 to ANSI_XXXX
sizeMB := wideCharToMultiByte( codePage_, 0, PWideChar( w ), sizeWC, nil, 0, nil, nil );
setLength( result, sizeMB );
wideCharToMultiByte( codePage_, 0, PWideChar( w ), sizeWC, PAnsiChar( Result ), sizeMB, nil, nil );
end else
result := text_;
end;
procedure testString( s_ : string; icp_ : cardinal );
var
sutf : string;
s1250, s1252 : string;
pc : pchar;
function strToHex( s_ : string; ocp_ : cardinal ) : string;
var
i : integer;
begin
result := '';
for i := 1 to length( s_ ) do
begin
if ( i > 1 ) then
result := result + ', ';
result := result + TStringUtility.byteToHexaDecimalStr( ord( s_[i] ) );
end;
end;
procedure logInput;
var
s : string;
begin
s := 'Input (' + intToStr( icp_ ) + '): ' + strToHex( s_, icp_ );
listbox1.items.add( s );
end;
procedure logOutput( ocp_ : cardinal );
var
s : string;
begin
s_ := utf8toansi( sutf, ocp_ );
s := 'Output (' + intToStr( ocp_ ) + '): ' + strToHex( s_, ocp_ );
listbox1.items.add( s );
end;
begin
logInput;
sutf := ansitoutf8( s_, icp_ );
logOutput( 1250 );
logOutput( 1252 );
listbox1.items.add( '' );
end;
begin
testString( #$f5 + #$fa + #$fb, 1250 ); // õúû in 1250
testString( #f + #$fa + #, 1252 ); // õúû in 1252
end;
记录的结果不是加速的结果。它显示 api 调用将字符串从 1250 转换为 1252,但没有将 1252 转换为 1250。我将默认代码页更改为 1252,结果相同。
Input (1250): $f5, $fa, $fb
Output (1250): $f5, $fa, $fb
Output (1252): f, $fa,
Input (1252): f, $fa,
Output (1250): f, $fa,
Output (1252): f, $fa,
您的尝试是不可能的。 1250 中有一些字符在 1252 中不存在,反之亦然。
考虑您问题中的示例字符。让我们从1250中的$f5
开始。即ő
。现在,该字符在 1252 中不存在,因此系统无法执行您要求它执行的操作。相反,它会尽力而为,并且 returns f
在 1252 中是 o
。
然后从1252转换回1250就没有问题了,因为o
是ASCII码范围,可以正确转换。但是,系统当然无法返回到 ő
,当您转到 1252 时,该信息丢失了。
如果您需要处理 1250 或 1252 中的文本,那么显而易见的解决方案是使用 Unicode。