Ubuntu16.04下CMake构建的C++程序无法读取文件问题求助
排查CMake构建后C++文件读取失败的问题
嘿,我来帮你搞定这个文件读取的麻烦——核心问题出在相对路径的基准是程序运行时的工作目录,不是可执行文件的存放目录,再加上CMake构建后的目录结构变化,直接导致路径指向错误了。
先理清楚你的目录结构(根据你的配置推测)
从你的CMake代码和描述来看,项目结构应该是这样的:
Azienda/ ├── include/ │ └── HEADER.h ├── src/ │ └── 你的cpp源文件 ├── data/ │ ├── dipendenti.txt │ ├── clienti.txt │ └── prodotti.txt └── build/ # 你执行cmake的目录 ├── bin/ │ └── azienda # 编译出的可执行文件 └── CMake生成的其他文件
举个例子:如果你在build/bin目录下运行./azienda,程序的工作目录是build/bin,这时候代码里的../data/dipendenti.txt会指向build/data/dipendenti.txt——但你的data目录明明在项目根目录Azienda/data,自然找不到文件。
你之前把data移到bin目录,却没改代码里的路径,那../data还是会找build/data,而不是build/bin/data,这就是为什么问题依旧。
两种靠谱的解决方案
方案一:让CMake自动同步data目录到输出目录
修改你的CMakeLists.txt,在ADD_EXECUTABLE(azienda ${SRCS})后面加上这段代码:
add_custom_command(TARGET azienda POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/data $<TARGET_FILE_DIR:azienda>/data )
这段代码的作用是:每次编译完可执行文件后,自动把项目根目录下的data文件夹复制到可执行文件所在的bin目录里。
之后把代码里的路径改成./data/dipendenti.txt(因为现在data和可执行文件同级了),运行时就能正确读取文件了。
方案二:用绝对路径彻底解决(传递项目根目录给代码)
如果你不想复制data目录,希望它留在项目根目录,可以让CMake把项目根目录的绝对路径传给代码:
- 先修改CMakeLists.txt,在
ADD_EXECUTABLE之前添加编译定义:
add_definitions(-DPROJECT_ROOT="${PROJECT_SOURCE_DIR}")
- 然后修改代码里的文件读取部分,用绝对路径拼接:
#include <string> // ... std::string data_path = std::string(PROJECT_ROOT) + "/data/"; std::ifstream di(data_path + "dipendenti.txt"); std::ifstream di_clienti(data_path + "clienti.txt"); std::ifstream di_prodotti(data_path + "prodotti.txt");
这样不管你在哪个目录运行程序,都会直接指向项目根目录下的data文件夹,完全不受工作目录影响。
额外要检查的点
- 文件权限:确保你的程序能读取data目录和里面的txt文件,终端执行
ls -l data/查看权限,必要时用chmod +r data/*.txt调整。 - 文件内容:有时候文件看似存在,但实际是空的,或者格式和代码预期不符,导致程序判断为空——可以用
cat data/dipendenti.txt直接查看内容确认。 - 运行时的工作目录:如果你在项目根目录运行
build/bin/azienda,那工作目录是项目根目录,此时../data会指向项目根目录的上级目录,这也会出错——所以要么注意运行时的工作目录,要么用上面的方案彻底解决。
内容的提问来源于stack exchange,提问作者AllBrokenWings
相关产品推荐
相关产品推荐

