I want to create a file at a given path that is relative to the current directory. The following code behaves erratically. I some times see the file created and some times do not. That may be because of the change in the current directory. Here's the code.
//for appending timestamp
timeval ts;
gettimeofday(&ts,NULL);
std::string timestamp = boost::lexical_cast<std::string>(ts.tv_sec);
//./folder/inner_folder is an existing directory
std::string filename = "./folder/inner_folder/abc_"+timestamp+ ".csv";
std::ofstream output_file(filename);
output_file << "abc,efg";
output_file.close();
Now, the problem is the file is created only in some cases. That is when I have as a command line argument an input file from the current directory, it works fine.
./program input_file
If I have something like this, it does not work
./program ./folder1/input_file
I tried giving the full path as an argument for ofstream, I still don't see the files created.
What is the correct way to do this? Thanks
ofstream will not create missing directories in the file path, you must ensure the directories exist and if not create them using OS specific api or boost's file system library.
Always check the result of IO operations, and query system error code to determine reason for failures:
if (output_ file.is_open())
{
if (!(output_file << "abc,efg"))
{
// report error.
}
}
else
{
const int last_error = errno;
std::cerr << "failed to open "
<< filename
<< ": "
<< strerror(last_error)
<< std::endl;
}
Related
I am doing a openGL porject and readering my shaders from .vert and .frag glsl files. I am using CMake with an extension for auto ninja file generation as well. This is my readfile code:
std::string readFile(const char *filePath) {
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
if(!fileStream.is_open()) {
std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while(!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
I spent a long time thinking I was crazy because from my build dir I was doing ./app/NAME_OF_APP.exe but the shaders were not being applied just black. It was only when I clicked on it from within the file explorer that it worked so I cd'ed into build/app/ and called ./NAME_OF_APP.exe and boom it worked. Why is this behavior happening? does the starting dir effect the relative pathing of the actual application? seems odd to me. thanks.
If you run a program from a command line the current directory is whatever directory is current in that command prompt. If you run a program from explorer the current directory is the directory that houses the executable.
You could use a function like GetModuleFileName (with NULL as the hModule parameter) to get the path to the executable and then chop off at the last \ and then change to that directory and then the program would not depend on the directory the program is run from.
I want to get file's content and print it in console, but the code bellow works only if I use full path and I don't want that, I am using Visual Studio 2022
int main() {
std::ifstream file("folder/file.txt");
std::string content = "";
if (file.is_open()) {
while (file) {
std::string line;
std::getline(file, line);
content += '\n' + line + '\n';
}
}
else {
std::cout << "Failed to open file" << std::endl;
}
std::cout << content << std::endl;
return 0;
}
output: Failed to open file
but if I use full path like: "C:\Users\User\...\folder\file.txt" it will work.
Some of the shorter comments give clues to the problem, but I'll provide a longer answer.
Many IDEs -- including Visual Studio -- do NOT have the current directory as your project area. Instead, the current directory when you run your program is in a build area.
Imagine your project is in C:\Users\You\MyProgram. You put the file there (or in a subdirectory), and when you run your program from the IDE, you expect to find it. And it's not there.
That's because the IDE actually sets the current directory to somewhere else. (I'm not sure where -- I don't use Visual Studio.) If you do this:
cout << std::file_system::current_path() << endl;
it should give you a clue.
I've got a method to read a vector of bools from a file:
std::vector<bool> OPCConnector::getAlarmVector() {
std::vector<bool> data;
std::ifstream DataFile(filepath);
if (DataFile) {
bool value;
while (DataFile >> value) {
data.push_back(value);
std::cout << value;
}
}
return data;
}
The filepath variable is an object property that is assigned through the constructor:
OPCConnector::OPCConnector(std::string fpth) {
filepath = fpth;
}
And in the main() function, the constructor is called:
std::vector<bool> activations;
std::string filepath = "alarmes.txt";
OPCConnector opcc = OPCConnector(filepath);
activations = opcc.getAlarmVector();
Now, I've checked what the folder of the executable is via GetModuleFileNameA(), and I made sure that the file is in the same directory and has the same name (also, I made sure that the extension isn't part of the file name, like "alarmes.txt.txt").
I debugged the first method getAlarmVector() and it never gets past the if (DataFile) condition, as if it won't find file.
I run the code using Visual Studio 2019, and nothing happens. The vector remains empty. Error is No such file or directory.
Default working directory is $(ProjectDir) and it's exactly where my file is.
Edit: I've also tried using both relative and absolute paths, none work.
Edit 2: I've also checked the directory using GetCurrentDirectory() and copied the .txt file there too, and it isn't working.
SOLUTION: Strangely enough, I deleted the file and created it again with the same name, and it worked. Thanks for the answers.
My guess: your current working directory isn't what you think it is, especially if you're running from an IDE. I know of several IDEs where the current working directory is some build directory (it varies by IDE) unless you specifically change it.
I'm fairly sure Visual Studio is one such IDE.
Here's a tiny example program I wrote;
$ cat Foo.cpp
#include <iostream>
#include <fstream>
int main(int, char **) {
std::ifstream file { "Foo.cpp" };
if (file) {
std::cout << "File opened.\n";
}
else {
std::cout << "File not opened.\n";
}
}
Compile and run it:
$ g++ --std=c++17 Foo.cpp -o Foo && Foo
File opened.
Current folder and folder-of-exe-file are different things (sometimes). Try to specify full name of file (with disk, all folders, etc.).
You can check errors of file open operation by calling
if (!DataFile) { ... }
The std::filesystem library can help you resolve file and path related issues.
#include <filesystem>
// (in some function)
std::filesystem::path filepath = "alarmes.txt";
if ( !exists(filepath) )
{
std::cout << "File path " << filepath << " at absolute location "
<< absolute(filepath) << " does not exist\n";
}
See it on Compiler Explorer
You can get an error code (and get a description of error in internet) if you use C-function fopen. If open is failed, you get the nullptr as result of fopen and errno will contain code of error.
im having trouble figuring out why my files wont copy. Here's a brief portion of the code:
(dir_itr is directory_iterator & root is a path)
if (!(is_directory(dir_itr->path())))
{
cout << "copying: " << dir_itr->path().filename() << endl;
try
{
copy(dir_itr->path(), root);
remove(dir_itr->path());
} catch (filesystem_error& ex) {
//more code
The results are as follows in the command window:
boost::filesystem::copy_file: The operation completed successfully:
"C:\Documents and Settings\R\Desktop\New Folder\New Folder (2)\New Bitmap Image 3.bmp",
"C:\Documents and Settings\R\Desktop\New Folder"
However no files are copied over.
I am basically just trying to move said file from folder c:\x\y\file.file to c:\x
I'm assuming why i cant move it is because i need a full file name and not just a directory or something? If this is the case, how do i convert path root to string so i can add a file name to it? (im gettin a thousand errors if i even try, they're so long i cant scroll all the way back up the window to see where it starts)
Perhaps boost::filesystem::system_complete can help:
(Sorry, I'm on my Mac and not windows but it shows a way to get the absolute path from a relative path). Good luck.
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
int main(int argc, char *argv[]) {
boost::filesystem::path cwd(".");
boost::filesystem::path resolved = boost::filesystem::system_complete(cwd);
std::cout << cwd << std::endl;
std::cout << resolved << std::endl;
}
Outputs:
"."
"/private/var/folders/qw/x23nm9f11fxc45rgddb04n_w0000gn/T/CodeRunner/."
Got back to working on this and I added/changed the following:
try
{
string temp = root.string() + "\\" + dir_itr->path().filename().string();
path p(temp);
copy(dir_itr->path(), p);
remove(dir_itr->path());
//more code
And it seemed to work. I guess my assumption of needing to include the file name when copying was correct.
I'm working on VTK (Qt on ubuntu 10.04).
I'm trying to read a .vtk file having 3D image. As I could understand, this
http://www.vtk.org/Wiki/VTK/Examples/Cxx/IO/GenericDataObjectReader
makes it possible to read any vtk file. However, it does not work. All I get is :
Starting /home/taha/Downloads/VTK/Examples/qtcreator-build/GenericDataObjectReader...
Usage: /home/taha/Downloads/VTK/Examples/qtcreator-build/GenericDataObjectReader InputFilename
/home/taha/Downloads/VTK/Examples/qtcreator-build/GenericDataObjectReader exited with code 1
1) Does the code I'm using work properly? Should I change something?
Even though I know that I need to pass the filename as arguments, I may not know how to do it from command prompt. I searched on internet in detail for this but the ways I'm following might be wrong.
2) How could one pass filename as arguments to program in C++?
If you desire to call the compiled programm from the example given from vtk-wiki simply open up a shell/dos window and type:
yourExecutable.exe path-to-file.vtk
As the output stated above, you did not match the requirements for the example to run (2 parameters).
One parameter (the first) is the usage (to what program you call) and the second one containing the path to the vtk-file you want to read.
If you don't want to call it with parameters you could change the given example to this:
int main ( int argc, char *argv[] )
{
// simply set filename here (oh static joy)
std::string inputFilename = "setYourPathToVtkFileHere";
// Get all data from the file
vtkSmartPointer<vtkGenericDataObjectReader> reader =
vtkSmartPointer<vtkGenericDataObjectReader>::New();
reader->SetFileName(inputFilename.c_str());
reader->Update();
// All of the standard data types can be checked and obtained like this:
if(reader->IsFilePolyData())
{
std::cout << "output is a polydata" << std::endl;
vtkPolyData* output = reader->GetPolyDataOutput();
std::cout << "output has " << output->GetNumberOfPoints() << " points." << std::endl;
}
return EXIT_SUCCESS;
}
and simply replace setYourPathToVtkFileHere with the (preferably absolute) your path.