boost filesystem copy_file "successful" but no files copied - c++

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.

Related

ifstream won't find file even though it's in the same directory

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.

How to make relative file path work in visual studio using cmake?

We are working on a c++ project using CMake. In the project we are referencing some resource files like resources/file.txt (located directly inside the project folder) using the std::ifstream class. The problem now is that, while our other team members can reference these files as they use Linux, I cannot (I am using Visual Studio 2017).
How can I set up CMake or Visual Studio so I can reference these files without changing their paths? I am still a pretty big novice using CMake but I didn't find anything that worked.
EDIT:
Minimal code showing the issue:
#include <iostream>
#include <fstream>
#include <string>
std::string read_file(std::string filename)
{
std::string result = "";
std::ifstream file(filename);
if (!file.is_open())
{
std::cout << "Could not open file " << filename.c_str() << "." << std::endl;
return result;
}
std::string line;
while (getline(file, line))
result += line + '\n';
return result;
}
int main(int argc, char *argv[])
{
std::string fileContent = read_file("src/Test_File.txt");
if (fileContent.compare(""))
{
std::cout << fileContent.c_str() << std::endl;
}
return 0;
}
This program should load the "Test_File.txt" located inside the src folder with the folder structure being:
src
main.cpp
CMakeList.txt
Test_File.txt
CMakeList.txt
The problem here is that the program cannot find the Text_File.txt while the other team members don't have such issue. Absolute paths of course work but they are obviously not the way to go.
I've already tried to set the working directory using the
VS_DEBUGGER_WORKING_DIRECTORY parameter with set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") after add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp") but that does not seem to work either.
After some more tries I have got it working thanks to #Tsyvarev. As states in this question they brought up, setting "currentDir" worked. For me it didn't work before because "name" and "projectTarget" were improperly set.
I now added "currentDir": "${workspaceRoot}" after fixing the "name" and "projectTarget" values and it worked.

Somthing of bad understanding in "SetCurrentDirectory" ("windows.h") in CPP

I don't know what's happened here. Here is the code sample:
#include<stdio.h>
#include<iostream>
#include<string>
#include <Windows.h>
using namespace std;
int main()
{
char my_current_path[1024];
string current_path(R"(C:)");
if (!SetCurrentDirectory(current_path.c_str()))
cout << "cant change to that directory.";
GetCurrentDirectory(1024, my_current_path);
std::cout << my_current_path << endl;
system("pause");
return 1;
}
What I'm doing here is trying to change the directory to some directories.
There is two strange things with my code.
(1 Strange thing)
When I try to change to "c:" like that:
#include<stdio.h>
#include<iostream>
#include<string>
#include <Windows.h>
using namespace std;
int main()
{
char my_current_path[1024];
string current_path(R"(C:)");
if (!SetCurrentDirectory(current_path.c_str()))
cout << "cant change to that directory.";
GetCurrentDirectory(1024, my_current_path);
std::cout << my_current_path << endl;
system("pause");
return 1;
}
It's not working and not changing the path (and its the good thing.) but its not show me the message that shown when the directory isn't changed:
cout << "cant change to that directory.";
Why is that? (When I try to change something like "efef:" or "exist?" it is showing me that's messege. But Why here it doesn't show me, and also doest change the current working directory?
(Second Strange thing)
When I change the directory to "G:" Its for some reason working..
#include<stdio.h>
#include<iostream>
#include<string>
#include <Windows.h>
using namespace std;
int main()
{
char my_current_path[1024];
string current_path(R"(G:)");
if (!SetCurrentDirectory(current_path.c_str()))
cout << "cant change to that directory.";
GetCurrentDirectory(1024, my_current_path);
std::cout << my_current_path << endl;
system("pause");
return 1;
}
That code compiled, showing that I successfully changed the directory to "G:".
After changing to that path, I'm trying to change to "C:" (Which before, didn't did anything) and now its working! but in strange way, its not moving to "C:\" But to:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE
And its weird that before its not worked, and now when I'm in "G:" path and trying to move to "c:" again, then its move to path that I didn't even wanted!
If you want to specify the root directory on a drive, you must include a backslash, i.e., C:\.
The syntax you are using, C:, has a different meaning. The command shell separates the concepts of the current drive and the current directory on each drive, so that you can switch between drives quickly without having to retype the full path each time. This feature was introduced (a long time ago) for backwards compatibility reasons (see below) but is actually very useful; power users will sometimes map multiple drive letters to the same drive or network share specifically in order to take advantage of this functionality.
Although only the command shell keeps track of the current directory for each drive, the Win32 API knows how to look them up, and does so whenever you specify a drive but no path. As a special case, if the drive specified is the current drive, it expands to the actual current directory rather than the saved current directory.
So in your example the incomplete path C: is expanded to the current directory for the C drive; since your current directory is already on the C drive, SetCurrentDirectory(R"(C:)") is a no-op. If you want to change to the root directory, you should use SetCurrentDirectory(R"(C:\)") instead.
In your testing, there was no saved current directory for the G: drive, and it was not the current drive, so the effect was to set the current directory to G:\, i.e., you got the behaviour you expected but not for the reason you were expecting. If you had launched the program from the command shell and a current directory had been saved for the G drive, you'd have wound up there instead.
The same thing applies to opening files; C:file.txt will open file.txt from the current directory for the C drive, whereas C:\file.txt will open file.txt from the root directory.
See Raymond Chen's blog post, Why does each drive have its own current directory? for a discussion of the history of this feature.
you can use the two APIs for retrieving and setting the current directory: GetCurrentDirectory() and SetCurrentDirectory() only provide a valid path for the latter:
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char czCurDir[MAX_PATH] = "";
char czNewDir[MAX_PATH] = "";
// retrieve the current directory
GetCurrentDirectory(MAX_PATH, czCurDir);
cout << "Current directory: " << czCurDir << endl;// C:\Users\Raindrop7\Desktop\New folder
// set the value for the new directory NB: C:\\ not C:\ because the first backslah is an escape character
strcpy(czNewDir, "C:\\");
// set the current directory to "C:\"
SetCurrentDirectory(czNewDir);
// retrieve the current directory
GetCurrentDirectory(MAX_PATH, czCurDir);
cout << "current directory: " << czCurDir << endl;// C:\
return 0;
}
First change drive to single F or G drive-
Example::
if( !SetCurrentDirectory("F:") )
{
cout <<"can't open the directory"<< endl;
}
then give full path-
Example::
if(!SetCurrentDirectory("F://Python_Django_Webdevelopment//StudentManagement"))
{
cout <<"can't open the directory"<< endl;
}
It works for me.

Cannot open file with relative path? (C++ ifstream)

I know this seems like a simple question, but I tried everything I can think of to no avail to something that shouldn't have been a problem in the first place.
This is a small C++ program that opens a file. When I open it with its absolute filepath, it works fine. With a relative path, however, it stops working.
Here's the file path of the program and the files I'm trying to read:
C++ program: "/Users/Baggio/C++/Lab0/Lab0/Lab0/main.cpp"
Files: /Users/Baggio/C++/Lab0/Lab0/Lab0/result.txt, /Users/Baggio/C++/Lab0/Lab0/Lab0/dict.txt
Here's the code snippet:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, const char * argv[]) {
// string dict_filename = "/Users/Baggio/C++/Lab0/Lab0/Lab0/dict.txt";
// string result_filename = "/Users/Baggio/C++/Lab0/Lab0/Lab0/result.txt";
string dict_filename_string = "dict.txt";
string result_filename_string = "result.txt";
const char* dict_filename = dict_filename_string.c_str();
const char* result_filename = result_filename_string.c_str();
// open files
ifstream dict_file(dict_filename, ifstream::in);
ifstream result_file(result_filename, ifstream::in);
if (!dict_file || !result_file) {
cerr << "File could not be opened." << endl;
exit(1);
}
}
Result of execution
File could not be opened.
I'm sure I've done all the includes right, and the data types right for the ifstream constructor arguments. The only thing I can think of worth mentioning is the system I'm on: I'm on a Mac and I'm using XCode6 as my IDE.
Also, I've tried to move the files' location (results.txt and dict.txt) to these locations to no avail:
/Users/Baggio/C++/Lab0/Lab0/Lab0/
/Users/Baggio/C++/Lab0/Lab0/
/Users/Baggio/C++/Lab0/
/Users/Baggio/C++/
Thanks for your help guys!! Any suggestions or thoughts appreciated.
Print out your current working directory when you run the program:
char buffer[256];
char *val = getcwd(buffer, sizeof(buffer));
if (val) {
std::cout << buffer << std::endl;
}
This will tell you where you are running your program from and thus why the path doesn't match for relative paths. A relative path is relative to the current working directory, not to where your binary is located.
If you want to make the path relative to the location of the binary then you will have to do that yourself. Many programming languages offer this as an option, but it is not built-in to C++. You can do this by finding the executable using the argv[0] from main. Then you need to drop the file component of the executable path and replace it with the file name that you are interested in.
Since C++17, you can use std::filesystem::current_path() instead of getcwd.
std::cout << std::filesystem::current_path() << std::endl;

Create a file at a given path using C++ in Linux

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;
}