VS2017(Win10)与CodeBlocks(Ubuntu)文件创建代码异常问题排查
问题原因与解决方法
首先,咱们来拆解一下为什么同样的代码在Windows和Ubuntu下表现不一样:
核心问题原因
1. Windows与Linux文本文件换行符差异导致读取空元素
你的usernames.txt应该是在Windows环境下创建的,Windows使用\r\n作为换行符,而Ubuntu使用\n。当你在Ubuntu下用getline读取这个文件时:
- 如果文件末尾存在多余的空行(很多Windows编辑器会自动添加),
getline会读取到一个空字符串并把它加入allUsers数组; - 即使没有空行,每行末尾的
\r可能会被保留在读取到的用户名中(getline只会丢弃\n),不过从你描述的生成结果来看,空字符串的可能性更大。
当allUsers数组里混入空字符串后,内层循环就会出现这种情况:比如当i指向正常用户名(如user11),j指向空字符串时,拼接后的文件名就变成了PRIVATEHISTORY/user11.txt,这就是你看到的多余单个用户名文件的来源。
2. 缺少对读取内容的合法性校验
代码里没有检查读取到的用户名是否为空,也没有清理掉可能存在的特殊字符(比如\r),直接把所有读取到的内容加入数组,这就给异常情况开了口子。
解决方法(除删除多余文件外)
方法1:清理读取的用户名数据
在将用户名加入数组前,先去除空白字符并过滤空字符串,从源头避免异常数据:
ifstream fin("usernames.txt"); string user1; while (getline(fin, user1)) { // 移除字符串两端的空白字符(包括\r、\n、空格、制表符) size_t start = user1.find_first_not_of(" \t\r\n"); size_t end = user1.find_last_not_of(" \t\r\n"); if (start == string::npos || end == string::npos) { // 处理后为空,跳过该条数据 continue; } user1 = user1.substr(start, end - start + 1); allUsers.push_back(user1); }
方法2:统一文件换行符格式
把Windows格式的usernames.txt转换成Ubuntu支持的LF格式:
- 在Ubuntu终端执行命令:
dos2unix usernames.txt(如果没有这个工具,先安装sudo apt install dos2unix); - 用VS Code等跨平台编辑器打开文件,右下角切换换行符为
LF后保存。
方法3:提前创建目标目录(避免潜在问题)
虽然这不是直接导致多余文件的原因,但Ubuntu下fopen不会自动创建目录,如果PRIVATEHISTORY不存在,会导致文件创建失败。可以在代码开头添加目录检查与创建逻辑:
#include <sys/stat.h> #include <sys/types.h> // 在循环开始前执行 struct stat st; if (stat("PRIVATEHISTORY", &st) == -1) { // 创建目录,权限设置为755(所有者可读可写可执行,其他用户可读可执行) mkdir("PRIVATEHISTORY", 0755); }
方法4:添加文件创建错误检查
给fopen添加返回值校验,能及时发现路径或权限问题,避免意外行为:
FILE* x = fopen(temp, "w"); if (x == NULL) { perror("Failed to create file"); // 打印具体错误信息 } else { fclose(x); }
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

