环境:GCC/G ++ Linux

我在文件系统中有一个非ASCII文件,我将打开它。

现在我有了一个wchar_t*,但是我不知道如何打开它。 (我值得信赖的fopen只打开char*文件)

请帮忙。非常感谢。

有帮助吗?

解决方案

有两个可能的答案:

如果要确保所有Unicode文件名都是可表示的,则可以硬编码文件系统使用UTF-8文件名的假设。这是“现代” Linux桌面应用方法。只需从 wchar_t (UTF-32)带有库函数的UTF-8(UTF-8)(iconv 可以很好地工作)或您自己的实施(但要查找规格,这样您就不会像Shelwien那样出错),然后使用 fopen.

如果您想以更面向标准的方式做事,则应使用 wcsrtombs 转换 wchar_tchar 语言环境编码中的字符串(希望在任何现代系统上都是UTF-8)并使用 fopen. 。请注意,这要求您以前用 setlocale(LC_CTYPE, "") 或者 setlocale(LC_ALL, "").

最后,不是完全答案,而是一个建议:

存储文件名为 wchar_t 琴弦可能是一个可怕的错误。相反,您应该将文件名存储为抽象字节字符串,仅将其转换为 wchar_t 可以在用户界面中显示它们的时间(即使是为此必需的;许多UI工具包本身都使用纯字节字符串并将解释作为您的字符)。这样,您就消除了许多可能的令人讨厌的角落案例,并且您永远不会遇到某些文件由于其名称而无法访问的情况。

其他提示

Linux不是UTF-8,但无论如何它是您的唯一选择

(文件可以拥有您想要的任何东西 里面 他们。)


关于文件名,Linux实际上没有一个字符串编码要担心。文件名是需要终止终止的字节字符串。

这并不是确切地说是Linux是UTF-8,但这确实意味着它与宽字符不兼容,因为它们在字节中的零可能不是端字节。

但是UTF-8保留了无效的前面模型,因此我必须相信,实用方法是用于文件名的“转换为UTF-8”。

文件的内容对于高于Linux内核级别的标准来说是一个问题,因此这里没有任何您可以或想要做的Linux-y。文件的内容将完全是读写和编写的程序的关注点。 Linux只是存储并返回字节流,它可以具有您想要的所有嵌入式NUL。

将WCHAR String转换为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;
}

查看此文档

http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm

我认为Linux遵循POSIX标准,将所有文件名视为UTF-8。

我认为,当您说“文件系统中的非ASCII文件”时,它是包含非ASCII字符的文件的名称,而不是文件本身。文件包含什么并不重要。

您可以使用普通的FOPEN执行此操作,但是您必须匹配文件系统用途的编码。

这取决于Linux的哪个版本以及您使用的文件系统以及设置方式,但是如果幸运的话,文件系统使用UTF-8。因此,请使用您的WCHAR_T(可能是UTF-16编码字符串?),将其转换为UTF-8中编码的char字符串,然后将其传递给FOPEN。

// 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top