Boost not finding file - c++

I want to use Boost's filesystem functions. I try
cout << boost::filesystem::file_size(fname.c_str()) << endl;
where fname="file.txt"; and I get the error
boost::filesystem::file_size: No such file or directory
I am sure I have the right path because system("cat file.txt") works. I checked that the folder is not NFS; it is NTFS.
I am using g++ on cygwin on a Windows 7 machine.
EDIT: I also tried
cout << boost::filesystem::file_size(fname);
and using fname="./file.txt"
In the makefile I'm linking using -lboost_system -lboost_filesystem and also using -I /usr/local/opt/boost/include -L /usr/local/opt/boost/lib
UPDATE: I changed it so there is a using namespace boost::filesystem; at the beginning of the file and removed boost::filesystem::" in front of file_size(). Now I have the same error using fname="file.txt" but if I use fname="./file.txt" I get a new error:
boost::filesystem::file_size: Operation not permitted
I have tried different kinds of files (.txt, .dat, .cpp)
The tutorial program tut1.cpp that comes with it and uses the same syntax works, so I'm thinking it could be a compiling problem. I have tried to find the file (presumably a makefile) compiling tut1.cpp with no luck.
tut1.cpp looks like this:
// filesystem tut1.cpp ---------------------------------------------------------------//
// Copyright Beman Dawes 2009
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
// Library home page: http://www.boost.org/libs/filesystem
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: tut1 path\n";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
return 0;
}

Is fname a path? Because, then, just drop the .c_str() member invocation.
It might be that the accessor functions add some Operating System Specific quoting or escaping. (example on linux)
You might assign to a std::string so you can observe the value in a debugger.

Related

C++ removing file with filesystem library doesn't work

I have a russian Roulette script written with C++. If two randomly generated numbers are the same, the script deletes a specified file.
People suggested to me that I should use C++17 for using the <filesystem> library in order to run file-related operations correctly. The removing operation runs if the conditions are matching. The if block runs correctly, but removing the file isn't happening.
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <filesystem>
//include filesystem and replace remove() with filesystem libs remove function
using namespace std;
namespace fs = std::filesystem;
int main(){
int minNumber = 1, maxNumber = 6;
int possibility,chamberNumber;
srand(time(0));
possibility = rand() % (maxNumber - minNumber + 1 ) + minNumber;
chamberNumber = rand() % (maxNumber - minNumber + 1 ) + minNumber;
cout << "First Number: " <<possibility<<endl<<"Second Number: " << chamberNumber<< endl;
if (possibility == chamberNumber){
std::filesystem::remove("C:\\Users\\mypath\\Desktop\\cppRoulette\\delete.txt");
cout << "You're Dead " <<possibility<< endl;
}
// else{
// cout << possibility << endl;
// }
return 0;
}
I use this line to compile my code:
g++ -std=c++17 rulet.cpp -o output
Here is a screenshot of the compiled output. Notice "delete.txt" still stands.
I am using WSL Debian, because I am using VS Code and native terminals don't work proper with g++. I may like smoothness of Linux a bit more, though.
I am looking for a proper and easier way to deal with files, just like in Python. I am attending a C++ crash course, so I am trying to learn it, switching to Python isn't on the table.
Your file path is wrong. I just got your code to work on my system by changing the path from E:\Test\delete.txt to /mnt/e/Test/delete.txt.
Under WSL, all Windows drives (C:, E:, etc.) are mounted under the /mnt directory, in subdirectories that match the drive letter (/mnt/c/, /mnt/e/, etc). In order to convert your Windows path for use in WSL, you need to do the following:
Replace all backslashes (\) with forward slashes (/).
Remove the colon (:) after the drive letter.
Convert the drive letter to lower case.
Prepend the string "/mnt/" to the path.
After this, your program works, and will delete the target file.

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.

boost1.44.0 filesystem v3 can not run properly on solaris sparc 64bit platform

I used boost::filesystem::is_directory() in my program, the problem is when I compile my program with option -DBOOST_FILESYSTEM_VERSION=3, the program cannot run properly. The boost version is 1.44.0.
Specifically, I build the filesystem library by the following command:
./bjam --toolset=gcc define=BOOST_FILESYSTEM_VERSION=3 --with-filesystem stage
I build my program with a command like this.
g++ -I boost_1_44_0_folder test.cpp -o test boost_1_44_0_folder/stage/lib/libboost_filesystem.a boost_1_44_0_folder/stage/lib/libboost_system.a -DBOOST_FILESYSTEM_VERSION=3
When I execute ./test, the result is "is not dir".
But if I build my program with a command like this.
g++ -I boost_1_44_0_folder test.cpp -o test boost_1_44_0_folder/stage/lib/libboost_filesystem.a boost_1_44_0_folder/stage/lib/libboost_system.a
When I execute ./test, the result is "is dir".
And my test code is shown as follows.
test.cpp
#include <boost/filesystem.hpp>
#include <iostream>
using namespace std;
int main() {
namespace bf = boost::filesystem;
bf::path p("/home");
if (!boost::filesystem::is_directory(p)) {
cout << "is not dir" << endl;
} else {
cout << "is dir" << endl;
}
return 0;
}
You may also need to upgrade your Boost version. If you look at the source code (for example: http://svn.boost.org/svn/boost/trunk/boost/wave/util/filesystem_compatibility.hpp) there are lots of changes in the filesystem processing in version 1.0.46 and 1.0.50, with a lot of code looking like this:
#if BOOST_FILESYSTEM_VERSION >= 3
#if BOOST_VERSION >= 105000
return boost::filesystem::complete(p, base);
#else
return boost::filesystem3::complete(p, base);
#endif
#else
return boost::filesystem::complete(p, base);
#endif
FWIW, this code in operations.cpp (http://svn.boost.org/svn/boost/trunk/libs/filesystem/src/operations.cpp) really bothers me:
// both stats now known to be valid
return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino
// According to the POSIX stat specs, "The st_ino and st_dev fields
// taken together uniquely identify the file within the system."
// Just to be sure, size and mod time are also checked.
&& s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
Thus if you're checking if two files are actually the same file with Boost, and they really are the same file but it gets written to or even just touch'd at the wrong moment, Boost will return that the file isn't itself. That, in addition to not properly identifying something as common as a simple directory, does not give me a lot of confidence in the rest of the Boost filesystem implementation.

boost filesystem copy_file "successful" but no files copied

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.

Boost.Filesystem how to find out in which directory your executable is?

So I run my app. I need for it to know where its executable is. How to find path to it using Boost.Filesystem?
boost::filesystem::system_complete(argv[0]);
e.g.
[davka#bagvapp Debug]$ ./boostfstest
/home/davka/workspaces/v1.1-POC/boostfstest/Debug/boostfstest
Note that this gives you the full path including the executable file name.
You cannot, Boost.Filesystem does not provide such functionality.
But starting with Boost 1.61 you can use Boost.Dll and function boost::dll::program_location:
#include <boost/dll.hpp>
boost::dll::program_location().parent_path();
You can't do it reliably with boost::filesystem.
However if you're on windows you can call GetModuleFileName to get the complete path of the executable and then use boost::filesystem to get the directory. ( see parent_path)
As discussed more comprehensively here, the most reliable way to do that is not through boost::filesystem. Instead, your implementation should take into the consideration the operating system on which the application is running.
However, for a quick implementation without portability concerns, you can check if your argv[0] returns the complete path to executable. If positive, you can do something like:
namespace fs=boost::filesystem;
fs::path selfpath=argv[0];
selfpath=selfpath.remove_filename();
From C++ 14 you don't need Boost, you can use the filesystem of the standard library you can do that easily:
(I can confirm this works on Windows and Linux as well)
#include <iostream>
#include <filesystem>
namespace fs = std::experimental::filesystem;
int main()
{
fs::path p = argv[0]; // or "C:executable_name.exe";
std::cout << "Current path is " << fs::current_path() << '\n'
<< "Absolute path for " << p << " is " << fs::absolute(p) << '\n'
<< "System complete path for " << p << " is " << fs::system_complete(p) << '\n';
}
Sample copied from the documentation: https://en.cppreference.com/w/cpp/experimental/fs/absolute
If you mean from inside the executable that you're running, you can use boost::filesystem::current_path()