[英]fopen in Linux (Lubuntu) returns NULL when the file exists
我在使用Oracle的VirtualBox的虚拟机中在Lubuntu上运行它。 我认为这不会影响任何事情,但我认为值得一提。
看起来错误是从附加到由以下函数返回的字符串末尾的奇怪符号出现的:
inline std::string f_settings_get(std::string val){
int index=0;
while(strcmp(val.c_str(),f_settings[0][index].c_str())!=0){
index++;
};
// For debugging purposes - printf("\n%s\t%s",f_settings[0][index].c_str(),f_settings[1][index].c_str());
return f_settings[1][index];
}
我看不出这个函数的问题,因此认为它可能是由存储在变量中的数据引起的。
我一直在尝试使用fopen
在我的程序中打开一个文件,并且遇到了标题中声明的错误。 该代码在Windows中完美运行(我已经考虑了每个操作系统的/
和\\
); 但是,当在Linux上运行时,尽管编译完美,但我得到的错误是该文件不存在。 我在网上查了一下,发现了其他一些问题,例如:
我使用提供的Python脚本检查了第一个,并使用新名称重新创建文件。 这不起作用(Python脚本显示文件名很好)。
我使用chmod -R 777 clesis
将所有权限设置为777并且不起作用(尽管我没想到它是权限问题,因为它说文件不存在)。
我已经调用了完整路径并仔细检查了路径。 它是正确的。
最后,我在代码中运行以下内容以仔细检查:(a)文件是否存在以及(b)我试图打开正确的文件。
tmp_s="";
tmp_s = homeDir+binP+f_settings_get("xxxxx"); // Note, you can easily get whatever variable you want using either f_settings_get or num_settings_get
tmp_file = fopen(tmp_s.c_str(), "r+");
printf("\n Running the following command: /home/xxxxx/programming/xxxxx/bin\n");
std::system("ls -l /home/xxxxx/programming/xxxxx/bin");
getWait();
printf("\n Tried to open: %s", tmp_s.c_str());
if (tmp_file == NULL){
printf("\n");
perror("Error loading dimensions.sim");
printf("Press enter to exit...");
getWait();
exit(1);
}
以下是输出的外观(抱歉审查事情。我向你保证用户名和文件夹拼写相同):
输出显示以下内容:
Filenames Loaded...
Loading Settings from sim file...
++++++++++++++++++++++++++++++++++++++++++++++++++ Settings Loaded...
Loading System Dimensions from sys file...
--------------------------------------------------
Running the following command: /home/xxxxx/programming/xxxxx/bin
total 636
-rwxrwxrwx 1 xxxxx xxxxx 958 Jul 25 20:59 dimensions.sim
Tried to open: /home/xxxxx/programming/xxxxx/bin/dimensions.sim
Error loading dimensions.sim: No such file or directory
Press enter to exit...
如果文件路径直接指定为“bin / dimensions.sim”或“/home/xxxxx/programming/xxxxx/bin/dimensions.sim”,则它可以正常工作。 这让我得出一个混乱的结论。 在将tmp_s
从std::string
转换为c_str
某处,存在导致错误目录路径的问题。 但是,我使用的任何其他文件都不会出现这种情况,我在Windows机器上从未遇到此问题。 因此,我对可能导致它的原因感到困惑。
最后一个观察 - 无论如何使用printf("tmps = %s",tmp_s.c_str());
打印出转换printf("tmps = %s",tmp_s.c_str());
。 这可以清楚地看出不是“怪异”。
您的问题很可能来自杂散回车(十六进制0D
,通常在C中写为\\r
),这在使用unix-y库读取windows-y文件时很常见。 Windows文件的行以CR-LF,hex 0D0A
终止,而unix只使用单个LF,hex 0A
。 对于未以二进制模式打开的文件,Windows C stdio会将CRLF映射到单个LF( \\n
)。 在Unix中,无论文件是以二进制还是ASCII模式打开都没关系,因为不会发生重映射。
结果是在Windows程序上编译的同一程序可以读取Windows文件,在Unix上编译可以读取Unix文件; 在这两种情况下,行终止符看起来都像一个\\n
。 Windows程序通常也可以读取Unix文件。 但是读取Windows文件的Unix程序会在每一行的末尾看到一个杂散的CR, \\r
,hex 0D
。
这特别困扰配置实用程序。 假设您有一个表单的配置文件:
some_setting=27
some_file=dimensions.sim
等等
现在,配置读取器读取每一行,在=
处拆分它,并使用第一部分作为键,第二部分作为值。 它甚至可能将一些值转换为数字。
现在,如果文件是在Windows上创建的(无论它当前是在Windows上还是在笔记本电脑上),Unix配置阅读器将看到some_setting
的值为27\\r
, some_file
的值为dimensions.sim\\r
。 第一个不会导致任何问题,除非配置系统是偏执的,因为atoi
和strtod
转换为第一个非数字字符,并且只要有至少一个数字就不要抱怨。 但是字符串不能用作文件名,因为文件名最后不可能有\\r
。
是什么让这个问题特别阴险,当你试图打印出违规的字符串时, \\r
实际上就像一个回车; 也就是说,它将光标返回到行的开头。 如果下一个输出字符是\\n
,那么\\r
\\n
是完全不可见的。 如果下一个输出是某个消息,它将被覆盖在线上,这非常令人困惑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.