C++: boost/filesystem: some questions - c++

I am using Boost library in C++ running in Ubuntu enviroment. I have some questions that I am not clear about:
fs::is_directory
namespace fs = boost::filesystem;
fs::path full_path(fs::initial_path<fs::path>() );
full_path = fs::system_complete(fs::path( "temp/"));
if(fs::is_directory(full_path ))
{
cout << "the path is a directory" << endl;
}
else
{
cout << "the path is not a directory" << endl;
}
=> I am sure that the moment I am running the program, there is a directory temp at the same location with the executable file. But it is always returned: "the path is not a directory" ?
fs::last_write_time
Is this fs::last_write_time(path) be able to get the last date time of modifying for the given path for BOTH either a directory or a file?
If it is true also for a directory, is that true for only the directory when it was created or the last date time if I add a file to inside the folder as well?
fs::directory_iterator
fs::directory_iterator dir(full_path) => how can I check whether this 'dir' has any sub directories or not?
Is there any way in boost::fileSystem to check if a file is opening?
Thanks in advance and I hope you could help me to make my mind clear!

Seems like that should work. Why don't you put a cout << fullpath before the if to make sure the path really contains what you think it does?
I've never used last_write_time. Can't help you with that one.
You have to iterate over the directory's contents and use fs::is_directory(dir->status()) to determine whether a given directory entry is a directory or not. (assuming dir is your directory iterator)
I don't believe there is anything in boost::filesystem to tell you if a file is open or not.

re 4.: Can't you find out if a file is currently open by simply calling [boost::filesystem|std]::fstream::is_open()?

Related

mkdir() isnt working with absolute filepath

I am using a raspberry pi to store data collected from a rocket launch. I am trying to create a directory which has the date and time built in, to hold multiple text and .csv files which hold interesting data. My code looks like:
string date = getDateTime(); //Returns a string like "Launch_2017_04_28_23:31:03"
string dated_directory = "~/Launch_System_Cpp/Source_Code/Launch_Data/" + date;
cout << dated_directory << endl;
if (mkdir(dated_directory.c_str(), ACCESSPERMS )) {
cout << "ERROR creating dated directory" << endl;
}
The executable itself is located in ~/Launch_Code_Cpp/.
I have been able to get this working with relative references, but I want this code to work no matter the directory it was run from. I haven't been able to get it working with absolute references; it always enters the if statement, and the directory doesn't exist when the program exits.
Can you tell me what I may be doing wrong when I try to make this directory? Is there a better way to make this directory?
The ~ character is converted to the home directory by the shell. Since you're not using a shell, you need to expand that yourself.

C++ char* relative file path? (Qt)

I am trying to play a .mod audio file in an executable. I am using the 3rd party BASSMOD .dll. I can get the audio file to play when I provide the full path to the file, but I cannot get it to play when providing a relative path. Here are some snippets.
main.cpp
#include <QCoreApplication>
#include "bassmod.h"
// define file location
const char* file = "C:/Users/Downloads/test4/console/music.mod";
void startMusic() {
BASSMOD_Init(-1, 44100, 0);
BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);
BASSMOD_MusicPlayEx(0,-1,TRUE);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
startMusic();
return a.exec();
}
bassmod.h (relevant snippet)
BOOL BASSDEF(BASSMOD_MusicLoad)(BOOL mem, void* file, DWORD offset, DWORD length, DWORD flags);
The function I'm concerned about is BASSMOD_MusicLoad. As this project stands, the .mod file will play no problem. However, when I try to change the absolute path of the .mod file to a relative path ("music.mod"), the file fails to play. Why is that? I have the .mod file in the same directory as the executable as well as in the directory containing the .pro file -- that didn't seem to be the issue.
Also, maybe I'm missing something related to how files are opened in C++. It looks like the MusicLoad function requires that the second parameter be of type void*. I'm sure there are many different things I could be doing better here. Ideally, I'd like to be able to have file store the relative path to the .mod file and have it play that way so I don't have to hard code an absolute path. In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc, but then I would have to use QFile, I believe, which won't work because I need the type to be void*.
Any help for a beginner would be much appreciated.
EDIT 01: Thank you all for your help! I got it to work (using relative file path, at least). There are two ways to do this. Here's what I did and how I tested it:
The first case makes the assumption that BASSMOD (or whatever external dll you're using) does not handle relative paths.
const char* file = "C:/debug/music.mod"; // same dir as .exe
QFileInfo info("music.mod");
QString path = info.absoluteFilePath();
const string& tmp = path.toStdString();
const char* raw = tmp.data();
Those are the test items I set up. When I run BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);, it works as expected. That's when I hard-code the full absolute path.
When I ran BASSMOD_MusicLoad(FALSE,(void*)raw,0,0,BASS_MUSIC_RAMPS);, it didn't work. So I decided to print out the values for everything to see where it's messing up:
cout << "Qstring path: ";
qDebug() << path;
cout << "string& tmp: ";
cout << tmp << endl;
cout << "raw: ";
cout << raw << endl;
cout << "full char* file: ";
cout << file;
startMusic();
...returns this:
Qstring path:
"C:/myApp/build-Debug/music.mod"
string& tmp:
C:/myApp/build-Debug/music.mod
raw:
C:/myApp/build-Debug/music.mod
full char* file:
C:/myApp/build-Debug/debug/music.mod
Note the difference? When I hard-code the full path to the file, I found that (thanks to #FrankOsterfeld and #JasonC) the current working directory was actually not where the .exe (/debug) or .pro files were located. It was actually in the same directory as the Makefile.
So I just changed it to this: QFileInfo info("./debug/x.m"); and it worked.
Even though the problem wound up being me not knowing where the current working directory was, the solutions by #Radek, #SaZ, and #JasonC helped to find another way to solve this (plus it showed me how to get the working dirs and convert between types). This is a good reference for people who would want to use QFileInfo to determine where you actually are in the filesystem. I would have used this solution if the dll I was using did not handle relative paths well. However...
I wondered if I could apply the same solution to my original code (without using QFileInfo and converting types, etc). I assumed that BASSMOD did not handle relative paths out of the box. I was wrong. I changed the file variable to const char* file = "./debug/x.m"; It worked!
Thanks for the help, everyone!
However, I would still like to get this to work using music.mod from a Qt resources file. Based on the replies, though, it doesn't look like that's possible unless the 3rd party library you're using supports the Qt resource system.
I have the .mod file in the same directory as the executable.
In Qt Creator the default initial working directory is the directory that the .pro file is in, not the directory that the .exe ends up in.
Either put your file in that directory (the one that probably has all the source files and such in it as well, if you used the typical setup), or change the startup directory to the directory the .exe file is in (in the Run Settings area).
Although, based on your new comment below, I guess the problem is deeper than that... I can't really tell you why BASS doesn't like relative filenames but you can convert a relative path to an absolute one before passing it to BASS. There's a lot of ways to do that; using Qt's API you could:
#include <QFileInfo>
...
const char* file = "music.mod"; // Your relative path.
...
BASSMOD_MusicLoad(...,
(void*)QFileInfo(file).absoluteFilePath().toAscii().data(),
...);
In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc
You won't be able to do that because loading resources from .qrc files is a Qt thing and BASS presumably does not use Qt internally (just like e.g. you could not open a resource with fopen), and doesn't understand how to load resources embedded by Qt. I am not familiar with BASS but a cursory glance at this documentation shows that it also has the ability to play data from an in-memory buffer. So one approach would be to use Qt to load the resource into accessible memory and pass that buffer instead.
In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc, but then I would have to use QFile, I believe, which won't work because I need the type to be void*.
Why do you only belive? Read Qt Doc. It will work. Don't use class QFile but QFileInfo.
QFileInfo info(:/resourcePrefix/name);
QString path = info.absoluteFilePath();
void* rawPtr = (void*)path.toStdString().c_str();

Ifstream doesnt find file in subfolder

It seems like a simple problem, but I just did not manage to figure it out, even with the help of the Internet.
So basically, because my project became rather big on files, I wanted to clean up the working directory by creating subfolders. So I moved e.g. shader files to Ressources/Shaders/ .
Now I just wanted to load them in as usual with the new path, but I always get an error.
ifstream fin("Ressources/Shaders/texture.vs");
does not work. as well as
.\\Ressources\\Shaders\\textures.vs
./Ressources/Shaders/textures.vs
/Ressources/Shaders/textures.vs
\\Ressources\\Shaders\\textures.vs
Ressources/Shaders/textures.vs
Ressources\\Shaders\\textures.vs
I also tried without capital letters.
while
"texture.vs"
worked when it still was in the working directory.
I appreciate any tips.
In Visual Studio, you can check what your current working directory is (this path must match the path of the file you are trying to open):
char * dir = getcwd(NULL, 0);
cout << dir << endl;
Then you can check if your file exists by trying to open it (capitalization shouldn't matter):
ifstream fin("Ressources\\Shaders\\texture.vs");
if (fin)
cout << "File Exists" << endl;
else
cout << "File Doesn't Exist" << endl;
If your paths are correct, this should work.
If you want to see what path you're actually accessing you can do the following:
char * dir = getcwd(NULL, 0);
printf("%s\\Ressources\\Shaders\\texture.vs", dir);

Xcode c++ cant access file through code

I have added an image "padimage.png" to my resources folder and set add to target and make copy if needed checked. Then in my c++ code I have the following code to check if it can reach the file
std::ifstream my_file("padimage.png");
if (my_file.good())
{
std::cout << "could read file \n";
} else {
std::cout << "could not read file \n";
}
This fails meaning I can't reach the file. I have checked in the debug build folder and the image is there under the resources folder, I have also tried alternative paths to the file like "resources/padimage.png" || Resources/padimage.png || ../Resources/padimage.png etc. etc.
I am fairly new to c++ still so I don't quite understand how it is suppose to find files or what path it searches relative to. Also I am sure this is quite an easy problem but I somehow can't solve it.
All help is much appreciated.
Just for your own sanity, do the following before anything else.
char wd[1024];
std::cout << getcwd(wd, sizeof(wd)) << std::endl;
You may be surprised at where you are, and thus why you can't open your file. When running from the IDE you can specify the location of your working directory under the Product/Edit Schemes... area of Xcode (among other places).
Thanks to a suggestion from WhozCraig I have managed to get it working by using the root of the project and then creating a standalone file next to the application like so:
./padimage.png
however this is not ideal. This means I would have resources outside of the project.
But after some trial and error I managed to navigate into the programs package contents by using .app to the package name;
./ProjectName.app/Contents/Resources/padimage.png

Use of `ofstream` appears not to create nor write to file

At the end of a simulation, I want to write some results as an appended row to a data file. The code I am using is the following, where you can assume that outFile was correctly allocated as an std::ofstream, that output_file is a std::string containing a valid path to a file that does not yet exist, and that the variables printed out to the file are just int types that get values during the simulation.
outFile.open(output_file.c_str(), std::ios::out | std::ios::app );
outFile << num_nodes << ", " << tot_s << ", " << tot_c << ", " << tot_d << std::endl;
outFile.close();
I've checked whether it correctly opens the file with the ofstream::is_open() function and it returns false. However, I can't figure out why. I've tried it with many different file names and directory paths, all of which I have checked and they are valid (no typos, etc.)
The file being written is just into a folder on the desktop where I create files all the time, so I don't see how it could be a permissions issue. If it was a permissions issue, how can I check that?
Otherwise, what else can be preventing it from writing to the file?
Added:
Following up on the comments, after adding a call to perror(), it is displaying the "No such file or directory" error. The file path in question is:
/home/ely/Desktop/Evolutionary_Dynamics/GamesOnCycle/data/test.data
I want this file to be created, and all the directories in that path exist, it's all spelled correctly, etc., and there are no weird permission issues with the GamesOnCycle folder or its data subfolder. Note that it is a linux system (Ubuntu 11.04) so the forward slashes are correct for the file path, unless I'm missing something that C++ has to have w.r.t. file paths.
This could be happening due to several reasons.
1) The file is already open.
2) All the directories in the file path are not created.
3) Lack of file permissions.
For an additional reference, please see When will ofstream::open fail?
This may sound bad, but are you on windows or linux? If windows, for your file path, do you have it defined with double "\" in your string, or just one? If just one, you aren't putting the characters in your path that you think you are. To be safe, use the "/" character.
So if you had this:
string pathname = "C:\Users\me\Desktop";
That is NOT a valid path. You are escaping "\U", "\m" and "\D" into your string. You'd need this:
string pathname = "C:\\Users\\me\\Desktop";
or
string pathname = "C:/Users/me/Desktop";
The "/" isn't an escape character.
It's what seems likely to me.