环境:Gcc / G ++ Linux
我在文件系统中有一个非ascii文件,我打算打开它。
现在我有一个wchar_t *,但我不知道如何打开它。 (我信任的fopen只打开char *文件)
请帮忙。非常感谢。
答案 0 :(得分:14)
有两种可能的答案:
如果要确保所有Unicode文件名都可以表示,您可以硬编码文件系统使用UTF-8文件名的假设。这是“现代”Linux桌面应用程序方法。只需将您的字符串从wchar_t
(UTF-32)转换为UTF-8,并使用库函数(iconv
可以正常工作)或您自己的实现(但查找规范,这样您就不会发现它可怕的错误像谢尔文那样),然后使用fopen
。
如果你想以更加面向标准的方式做事,你应该使用wcsrtombs
将wchar_t
字符串转换为语言环境编码中的多字节char
字符串(希望是无论如何在任何现代系统上使用UTF-8并使用fopen
。请注意,这需要您先前使用setlocale(LC_CTYPE, "")
或setlocale(LC_ALL, "")
设置区域设置。
最后,不是答案,而是建议:
将文件名存储为wchar_t
字符串可能是一个可怕的错误。您应该将文件名存储为抽象字节字符串,并且仅将它们及时转换为wchar_t
以便在用户界面中显示它们(如果它甚至是必需的;许多UI工具包本身使用普通字节字符串并且作为你的角色的解释)。通过这种方式,您可以消除许多可能令人讨厌的极端情况,并且您永远不会遇到某些文件由于其名称而无法访问的情况。
答案 1 :(得分:4)
(文件可以包含 in 中的任何内容。)
关于文件名,linux实际上并没有担心字符串编码。文件名是需要以空值终止的字节字符串。
这并不意味着Linux是UTF-8,但它确实意味着它与宽字符不兼容,因为它们可能在一个不是结束字节的字节中为零。
但是UTF-8保留了无空 - 除极端模型,所以我不得不相信实际方法是“转换为UTF-8”来获取文件名。
文件内容是Linux内核级别以上标准的问题,所以这里没有您可以或想要做的任何Linux-y。文件内容完全是读写程序的关注点。 Linux只存储并返回字节流,它可以包含你想要的所有嵌入式数据。
答案 2 :(得分:1)
将wchar字符串转换为utf8 char字符串,然后使用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;
}
答案 3 :(得分:0)
查看此文档
http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm
我认为Linux遵循POSIX标准,该标准将所有文件名视为UTF-8。
答案 4 :(得分:0)
当你说“文件系统中的非ascii文件”时,我认为它是包含非ascii字符的文件的名称,而不是文件本身。文件包含的内容并不重要。
您可以使用普通fopen执行此操作,但您必须匹配文件系统使用的编码。
这取决于Linux的版本以及您正在使用的文件系统以及如何设置它,但如果幸运的话,文件系统可能使用UTF-8。那么拿你的wchar_t(可能是一个UTF-16编码的字符串?),将它转换为以UTF-8编码的字符串,并将其传递给fopen。
答案 5 :(得分:0)
// locals
string file_to_read; // any file
wstring file; // read ascii or non-ascii file here
FILE *stream;
int read = 0;
wchar_t buffer= '0';
if( fopen_s( &stream, file_to_read.c_str(), "r+b" ) == 0 ) // in binary mode
{
while( !feof( stream ))
{
// if ascii file second arg must be sizeof(char). if non ascii file sizeof( wchar_t)
read = fread( & buffer, sizeof( char ), 1, stream );
file.append(1, buffer);
}
}
file.pop_back(); // since this code reads the last character twice.Throw the last one
fclose(stream);
// and the file is in wstring format.You can use it in any C++ wstring operation
// this code is fast enough i think, at least in my practice
// for windows because of fopen_s