繁体   English   中英

如何在Linux中使用wchar_t *包含非Ascii字符串的文件打开文件?

[英]How to open a file with wchar_t* containing non-Ascii string in Linux?

环境:Gcc / G ++ Linux

我在文件系统中有一个非ascii文件,我打算将其打开。

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

请帮忙。 非常感谢。

有两个可能的答案:

如果要确保所有Unicode文件名都可表示,则可以对文件系统使用UTF-8文件名的假设进行硬编码。 这是“现代” Linux桌面应用程序方法。 只需使用库函数( iconv可以正常工作)或您自己的实现将wchar_t (UTF-32)的字符串转换为UTF-8即可,也可以使用自己的实现(但是请查看规范,以免您不像Shelwien那样犯错),然后使用fopen

如果您想以更标准的方式进行操作,则应使用wcsrtombs以语言环境的编码将wchar_t字符串转换为多字节char字符串(希望在任何现代系统中均为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字符串转换为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;
}
// 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

查看此文件

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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM