运行环境: Gcc/G++ Linux
我在文件系统中有一个非ascii文件,我要打开它。
现在我有了一个wchar_t*,但是我不知道怎么打开它。(my trusted fopen仅打开char*文件)
请帮帮忙。非常感谢。
发布于 2011-01-13 12:11:59
有两种可能的答案:
如果您希望确保所有Unicode文件名都是可表示的,则可以对文件系统使用UTF-8文件名这一假设进行硬编码。这就是“现代”的Linux桌面应用程序方法。只需使用库函数(iconv会工作得很好)或您自己的实现(但请查看规范,这样您就不会像谢尔文那样弄错),将字符串从wchar_t (UTF-32)转换为UTF-8,然后使用fopen。
如果您希望以更面向标准的方式进行操作,则应该使用wcsrtombs将wchar_t字符串转换为区域设置编码中的多字节char字符串(在任何现代系统上都希望是UTF-8 ),并使用fopen。请注意,这要求您事先使用setlocale(LC_CTYPE, "")或setlocale(LC_ALL, "")设置区域设置。
最后,不是一个确切的答案,而是一个建议:
将文件名存储为wchar_t字符串可能是一个可怕的错误。相反,您应该将文件名存储为抽象的字节字符串,并且只将它们及时转换为wchar_t,以便在用户界面中显示它们(如果有必要的话;许多UI工具包本身使用纯字节字符串,并将其解释为字符)。通过这种方式,您可以消除许多可能的令人讨厌的情况,并且您永远不会遇到某些文件由于名称而无法访问的情况。
发布于 2011-01-13 11:40:19
Linux不是UTF-8,但无论如何它是文件名的唯一选择
(文件中可以包含您想要的任何内容。)
关于文件名,linux实际上并不需要担心字符串编码。文件名是需要以null结尾的字节字符串。
这并不意味着Linux是UTF-8,但它确实意味着它与宽字符不兼容,因为它们可能在不是结束字节的字节中有零。
但是UTF-8保留了除末尾以外的无空值模型,所以我必须相信实用的方法是将文件名“转换为UTF-8”。
文件的内容是Linux内核级别以上的标准的问题,所以这里没有任何Linux-y可以或想要做的事情。文件的内容将只由读取和写入它们的程序关注。Linux只是存储和返回字节流,它可以包含您想要的所有嵌入式nuls。
发布于 2011-01-13 11:14:19
将wchar字符串转换为utf8字符串,然后使用fopen。
typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;
int UTF16to8( wchar_t* w, char* s ) {
uint c;
word* p = (word*)w;
byte* q = (byte*)s; byte* q0 = q;
while( 1 ) {
c = *p++;
if( c==0 ) break;
if( c<0x080 ) *q++ = c; else
if( c<0x800 ) *q++ = 0xC0+(c>>6), *q++ = 0x80+(c&63); else
*q++ = 0xE0+(c>>12), *q++ = 0x80+((c>>6)&63), *q++ = 0x80+(c&63);
}
*q = 0;
return q-q0;
}
int UTF8to16( char* s, wchar_t* w ) {
uint cache,wait,c;
byte* p = (byte*)s;
word* q = (word*)w; word* q0 = q;
while(1) {
c = *p++;
if( c==0 ) break;
if( c<0x80 ) cache=c,wait=0; else
if( (c>=0xC0) && (c<=0xE0) ) cache=c&31,wait=1; else
if( (c>=0xE0) ) cache=c&15,wait=2; else
if( wait ) (cache<<=6)+=c&63,wait--;
if( wait==0 ) *q++=cache;
}
*q = 0;
return q-q0;
}https://stackoverflow.com/questions/4676327
复制相似问题