C++ C++;将UTF8字符数组转换为CP1250
我在将UTF8编码的字符数组转换为CP1250编码的字符数组时遇到问题 我尝试创建一个静态iconv库,但在编译UTF8->CP1250代码时,它总是失败C++ C++;将UTF8字符数组转换为CP1250,c++,visual-studio,static-libraries,iconv,C++,Visual Studio,Static Libraries,Iconv,我在将UTF8编码的字符数组转换为CP1250编码的字符数组时遇到问题 我尝试创建一个静态iconv库,但在编译UTF8->CP1250代码时,它总是失败 1>foo.obj : error LNK2001: unresolved external symbol libiconv_close 1>foo.obj : error LNK2001: unresolved external symbol libiconv_open 1>foo.obj : error LNK2001:
1>foo.obj : error LNK2001: unresolved external symbol libiconv_close
1>foo.obj : error LNK2001: unresolved external symbol libiconv_open
1>foo.obj : error LNK2001: unresolved external symbol libiconv
我还尝试了许多编译过的静态库,但总是出现相同的错误
无论是否设置了/MD
或/MT
我不坚持使用iconv。这个问题还有其他简单的解决办法吗?谢谢既然您在Windows中编码,为什么不使用Windows API呢。使用
MultiByteToWideChar
将无损转换为UTF-16。然后使用WideCharToMultiByte
向下转换为例如CP 1250
附录:下面的代码似乎正常工作
#include <assert.h> // assert
#include <iostream> // std::wcout, std::wcerr
#include <iterator> // std::begin, std::end
#include <string> // std::string, std::wstring
#include <stddef.h> // ptrdiff_t
#include <stdexcept> // std::system_error
#include <stdlib.h> // EXIT_SUCCESS
#include <string.h> // memcmp
#include <system_error> // std::system_error etc.
// Example of how to include Microsoft's <windows.h>.
// More support stuff is generally needed for more serious code.
#undef UNICODE
#define UNICODE
#undef NOMINMAX
#define NOMINMAX
#undef STRICT
#define STRICT
#include <windows.h> // E_FAIL, etc.
namespace cppx {
using std::begin;
using std::end;
using std::error_code;
using std::string;
using std::system_error;
using std::system_category;
typedef unsigned char Byte;
typedef ptrdiff_t Size;
template< class Type >
auto size( Type const& c )
-> Size
{ return end( c ) - begin( c ); }
auto hopefully( bool const condition ) -> bool { return condition; }
auto fail(
string const& message,
int const code = 0
)
-> bool
{
throw system_error(
error_code( code, system_category() ), message
);
}
} // namespace cppx
namespace data {
using cppx::Byte;
using cppx::hopefully;
using cppx::fail;
using std::string;
using std::wstring;
char const utf8_bom[] = "\xEF\xBB\xBF";
template< class Type, int n >
auto dummy()
-> Type&
{ static Type the_dummy; return the_dummy; }
auto utf16_from_utf8( char const* bytes, int length )
-> wstring
{
if( length >= 3 && ::memcmp( bytes, utf8_bom, 3 ) == 0 )
{
bytes += 3; length -= 3;
}
assert( length >= 0 );
if( length == 0 ) { return L""; }
int const buffer_size = ::MultiByteToWideChar(
CP_UTF8,
0, // flags, must be 0 for UTF-8
bytes,
length,
nullptr, // output buffer
0 // buffer size
);
hopefully( buffer_size > 0 )
|| fail( "MultiByteToWideChar (1st call)", ::GetLastError() );
wstring result( buffer_size, L'#' );
int const n_encoding_values = ::MultiByteToWideChar(
CP_UTF8,
0, // flags, must be 0 for UTF-8
bytes,
length,
&result[0], // output buffer
buffer_size
);
hopefully( n_encoding_values > 0 )
|| fail( "MultiByteToWideChar (2nd call)", ::GetLastError() );
assert( n_encoding_values <= buffer_size );
result.resize( n_encoding_values ); // Possible down-sizing.
return result;
}
auto utf16_from_utf8( Byte const* const bytes, int const length )
-> wstring
{
return utf16_from_utf8( reinterpret_cast<char const*>( bytes ), length );
}
auto sbcs_from(
wchar_t const* const s,
int const length,
unsigned const codepage = ::GetACP(),
bool& used_default_char = dummy<bool, 1>()
)
-> string
{
assert( codepage != CP_UTF8 );
if( length == 0 ) { return ""; }
DWORD const flags = WC_NO_BEST_FIT_CHARS; // Must be 0 for UTF-8.
char const* const default_char = "\x7F"; // ASCII DEL
int const buffer_size = WideCharToMultiByte(
codepage,
flags,
s,
length,
nullptr, // buffer
0, // buffer size
default_char,
nullptr
);
hopefully( buffer_size > 0 )
|| fail( "WideCharToMultiByte (1st call)", ::GetLastError() );
string result = string( buffer_size, '#' );
BOOL defaulted = false;
int const n_bytes = WideCharToMultiByte(
codepage,
flags,
s,
length,
&result[0], // buffer
buffer_size,
default_char,
&defaulted
);
hopefully( n_bytes > 0 )
|| fail( "WideCharToMultiByte (2nd call)", ::GetLastError() );
assert( n_bytes <= buffer_size );
result.resize( n_bytes );
used_default_char = !!defaulted;
return result;
}
auto sbcs_from(
wstring const& s,
unsigned const codepage = ::GetACP(),
bool& used_default_char = dummy<bool, 1>()
)
-> string
{
if( s.length() == 0 ) { return ""; }
return sbcs_from( &s[0], s.length(), codepage, used_default_char );
}
} // namespace data
void cpp_main()
{
using cppx::Byte;
using cppx::fail;
using cppx::size;
using std::string;
using std::wstring;
auto const infobox = MB_ICONINFORMATION | MB_SETFOREGROUND;
Byte const utf8_bytes[] = // UTF-8 with BOM, as if from a file.
{
0xEF, 0xBB, 0xBF, 0x42, 0x6C, 0xC3, 0xA5, 0x62, 0xC3, 0xA6,
0x72, 0x73, 0x79, 0x6C, 0x74, 0x65, 0x74, 0xC3, 0xB8, 0x79,
0x21, 0x20, 0xE6, 0x97, 0xA5, 0xE6, 0x9C, 0xAC, 0xE5, 0x9B,
0xBD, 0x20, 0xD0, 0xBA, 0xD0, 0xBE, 0xD1, 0x88, 0xD0, 0xBA,
0xD0, 0xB0, 0x21, 0x0D, 0x0A, 0x0D, 0x0A, 0x48, 0x75, 0x6E,
0x67, 0x61, 0x72, 0x69, 0x61, 0x6E, 0x20, 0x61, 0x6C, 0x70,
0x68, 0x61, 0x62, 0x65, 0x74, 0x3A, 0x0D, 0x0A, 0x41, 0x20,
0xC3, 0x81, 0x20, 0x42, 0x20, 0x43, 0x20, 0x43, 0x73, 0x20,
0x44, 0x20, 0x44, 0x7A, 0x20, 0x44, 0x7A, 0x73, 0x20, 0x45,
0x20, 0xC3, 0x89, 0x20, 0x46, 0x20, 0x47, 0x20, 0x47, 0x79,
0x20, 0x48, 0x20, 0x49, 0x20, 0xC3, 0x8D, 0x20, 0x4A, 0x20,
0x4B, 0x20, 0x4C, 0x20, 0x4C, 0x79, 0x20, 0x4D, 0x20, 0x4E,
0x0D, 0x0A, 0x4E, 0x79, 0x20, 0x4F, 0x20, 0xC3, 0x93, 0x20,
0xC3, 0x96, 0x20, 0xC5, 0x90, 0x20, 0x50, 0x20, 0x28, 0x51,
0x29, 0x20, 0x52, 0x20, 0x53, 0x20, 0x53, 0x7A, 0x20, 0x54,
0x20, 0x54, 0x79, 0x20, 0x55, 0x20, 0xC3, 0x9A, 0x20, 0xC3,
0x9C, 0x20, 0xC5, 0xB0, 0x20, 0x56, 0x20, 0x28, 0x57, 0x29,
0x20, 0x28, 0x58, 0x29, 0x20, 0x28, 0x59, 0x29, 0x20, 0x5A,
0x20, 0x5A, 0x73, 0x0D, 0x0A
};
wstring const text = data::utf16_from_utf8( utf8_bytes, size( utf8_bytes ) );
::MessageBox( 0, text.c_str(), L"Original text:", infobox );
string const sbcs_text = data::sbcs_from( text, 1250 );
WORD const hungarian = MAKELANGID(
LANG_HUNGARIAN, SUBLANG_HUNGARIAN_HUNGARY
);
DWORD const hungarian_locale_id = MAKELCID( hungarian, SORT_DEFAULT );
SetThreadLocale( hungarian_locale_id )
|| fail( "SetThreadLocale", ::GetLastError() );
DWORD thread_cp = 0;
::GetLocaleInfo(
::GetThreadLocale(), // Not LOCALE_USER_DEFAULT,
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
reinterpret_cast<wchar_t*>( &thread_cp ),
sizeof( thread_cp )/sizeof( wchar_t )
)
|| fail( "GetLocaleInfo", ::GetLastError() );
//::MessageBox( 0, std::to_wstring( thread_cp ).c_str(), L"Codepage:", MB_SETFOREGROUND );
assert( thread_cp == 1250 );
::MessageBoxA( 0, sbcs_text.c_str(), "SBCS codepage 1250 text:", infobox );
}
auto main()
-> int
{
using namespace std;
try
{
cpp_main();
return EXIT_SUCCESS;
}
catch( system_error const& x )
{
auto const code = x.code().value();
cerr << "!" << x.what() << " (code: " << code << ")" << endl;
return code;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
return E_FAIL;
}
}
#包含//断言
#包括//std::wcout、std::wcerr
#包括//标准::开始,标准::结束
#包括//std::string、std::wstring
#包括//ptrdiff\t
#包括//标准::系统错误
#包括//退出\成功
#包括//memcmp
#包括//标准::系统错误等。
//如何包含Microsoft的示例。
//对于更严肃的代码,通常需要更多的支持材料。
#未定义UNICODE
#定义UNICODE
#未定义NOMINMAX
#定义NOMINMAX
#未定义严格
#定义严格
#包括//E\u失败等。
命名空间cppx{
使用std::begin;
使用std::end;
使用std::error\u代码;
使用std::string;
使用std::系统错误;
使用std::system_类别;
typedef无符号字符字节;
typedef ptrdiff\t大小;
模板<类类型>
自动大小(const&c类型)
->大小
{返回结束(c)-开始(c);}
自动(布尔常量条件)->bool{return condition;}
自动失效(
字符串常量和消息,
int常量代码=0
)
->布尔
{
抛出系统错误(
错误代码(代码,系统类别()),消息
);
}
}//名称空间cppx
命名空间数据{
使用cppx::Byte;
使用cppx::希望;
使用cppx::fail;
使用std::string;
使用std::wstring;
字符常量utf8\U bom[]=“\xEF\xBB\xBF”;
模板<类类型,int n>
自动虚拟()
->类型&
{静态键入_伪;返回_伪;}
从utf8自动执行utf16(字符常量*字节,整数长度)
->威斯汀
{
如果(长度>=3&&::memcmp(字节,utf8\U bom,3)==0)
{
字节+=3;长度-=3;
}
断言(长度>=0);
如果(长度==0){返回L”“;}
int const buffer_size=::MultiByteToWideChar(
CP_UTF8,
0,//标志对于UTF-8必须为0
字节,
长度,
nullptr,//输出缓冲区
0//缓冲区大小
);
希望(缓冲区大小>0)
||失败(“MultiByteToWideChar(第一次调用)”,::GetLastError();
wstring结果(缓冲区大小,L'#');
int const n_编码值=::MultiByteToWideChar(
CP_UTF8,
0,//标志对于UTF-8必须为0
字节,
长度,
&结果[0],//输出缓冲区
缓冲区大小
);
希望(n_编码值>0)
||失败(“MultiByteToWideChar(第二次调用)”,::GetLastError();
断言(n\u编码\u值)
{
从utf8返回utf16(重新解释转换(字节),长度);
}
自动sbcs_从(
wchar_t const*const s,
int常量长度,
无符号常量代码页=::GetACP(),
bool&used\u default\u char=dummy()
)
->串
{
断言(代码页!=CP_UTF8);
如果(长度==0){return”“;}
DWORD const flags=WC\u NO\u BEST\u FIT\u CHARS;//对于UTF-8必须为0。
char const*const default_char=“\x7F”//ASCII DEL
int const buffer_size=WideCharToMultiByte(
代码页,
旗帜,
s
长度,
nullptr,//缓冲区
0,//缓冲区大小
默认字符,
nullptr
);
希望(缓冲区大小>0)
||失败(“WideChartMultiByte(第一次调用)”,::GetLastError();
字符串结果=字符串(缓冲区大小“#”);
BOOL defaulted=false;
int const n_bytes=宽图表多字节(
代码页,
旗帜,
s
长度,
&结果[0],//缓冲区
缓冲区大小,
默认字符,
&违约
);
希望(n_字节>0)
||失败(“WideChartMultiByte(第二次调用)”,::GetLastError();
断言(n_字节)字符串
{
如果(s.length()==0){return”“;}
从(&s[0],s.length(),代码页,used_default_char)返回sbcs_;
}
}//名称空间数据
无效cpp_main()
{
使用cppx::Byte;
使用cppx::fail;
使用cppx::size;
使用std::string;
使用std::wstring;
自动常量信息框=MB|U图标信息| MB|U设置前景;
字节常量utf8_bytes[]=//带BOM的UTF-8,就像来自文件一样。
{
0xEF、0xBB、0xBF、0x42、0x6C、0xC3、0xA5、0x62、0xC3、0xA6、,
0x72、0x73、0x79、0x6C、0x74、0x65、0x74、0xC3、0xB8、0x79、,
0x21、0x20、0xE6、0x97、0xA5、0xE6、0x9C、0xAC、0xE5、0x9B、,
0xBD,0x20,0xD0,0xBA,0xD0,0xBE,0xD1,0x88,0xD0,0xBA,
0xD0、0xB0、0x21、0x0D、0x0A、0x0D、0x0A、0x48、0x75、0x6E、,
0x67、0x61、0x72、0x69、0x61、0x6E、0x20、0x61、0x6C、0x70,
0x68、0x61、0x62、0x65、0x74、0x3A、0x0D、0x0A、0x41、0x20,
0xC3、0x81、0x20、0x42、0x20、0x43、0x20、0x43、0x73、0x20、,