【问题标题】:fopen not working in linux for a file with german characters in the namefopen 在 linux 中无法用于名称中包含德语字符的文件
【发布时间】:2012-10-09 22:31:23
【问题描述】:

我用 c 编写了一个代码,用于文件处理。文件名中包含一些德语字符。此代码在 Windows 上运行良好。但它在 Linux 中不起作用。 fopen 给出“无法打开文件”错误。 我检查了文件路径,文件存在那里。另外,我对该文件夹有读写权限。

代码如下。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    const char *fileName = "/users/common/haëlMünchen.txt";

    FILE * pFile;
    char errorMessage[256];
    pFile = fopen (fileName,"r");
    if (pFile != NULL)
    {
        fprintf (stdout,"fopen example",errorMessage);
        fclose (pFile);
    }
    else
    {
    sprintf(errorMessage, "Could not open file %s", fileName);
    fprintf(stdout, "%s\n", errorMessage);
    }
    return 1;
}

对此有何意见?

【问题讨论】:

  • 您的文件和文件系统路径的编码是什么? Linux 只将路径视为一堆字节。我怀疑编码不同,这就是您无法打开它的原因。由于字节不完全匹配,因此它不是同一个文件。您需要正确编码。
  • 可能是 Unicode (UTF-8) 与 CP1252(显示的字符类似于 ISO 8859-1 或 8859-15)。
  • 顺便说一句:记事本是否保留字符 ë 的外观?我将赌注押在字符集编码上(一些系统假定它是 utf-8,因为扩展了 ascii 字符......)
  • 使用ls h*chen.txt | od -t x1 查看文件系统上文件名的十六进制字节。在您的程序中以十六进制打印出fileName 中的字节。寻找不同之处。

标签: c linux unicode fopen


【解决方案1】:

在 Linux 上,您可以将 sprintf 调用替换为

snprintf (errorMessage, sizeof(errorMessage), 
          "Could not open file %s - %m", fileName);

(一般提示是避免sprintf,因为可能会出现缓冲区溢出,并且只使用snprintf)

如果你想避免 GLibc 特定的 %m 格式说明符,并使用更多标准函数,代码

snprintf (errorMessage, sizeof(errorMessage), 
          "Could not open file %s - %s",
          fileName, strerror(errno)); 

不要忘记#include &lt;errno.h&gt;,并仔细阅读errno(3) 手册页。

顺便说一句,您可以避免同时使用 snprintf 和 printf 并简单地编写代码

fprintf (stderr, "Cannot open file %s - %s\n",
        fileName, strerror(errno));

(如乔纳森所提醒,错误报告通常发送至stderr)

然后再次运行您的程序。可能您的字符编码有问题(在源文件中或在文件系统中)。

您也可以在您的程序上使用strace(也许还有ltrace)来了解它正在执行的实际系统调用。

【讨论】:

  • 该问题与 sprintf 无关。问题与带有德语字符的 fopen 有关。 sprintf 仅用于调试目的。
  • 确实,但您使用sprintf 可能很危险。
  • 当函数或系统调用失败时,您几乎总是想告诉用户errno 的含义......
猜你喜欢
  • 1970-01-01
  • 2016-09-03
  • 2012-12-05
  • 2014-03-05
  • 1970-01-01
  • 2016-02-06
  • 2017-01-17
  • 2014-12-04
  • 1970-01-01
相关资源
最近更新 更多