I'm ashamed for not being able to solve this but i can't make this work. I have this brief test:
std::string archnom = "../data/uniform.txt";
ifstream archin(archnom.c_str());
ASSERT(archin.good());
The assert is throwing error. For some reason it's not locating the uniform.txt file. The project structure is:
project
---> data/uniform.txt
---> a.out
---> main.txt
I've already tried changing archnom as follows without success:
std::string archnom = "/data/uniform.txt";
std::string archnom = "./data/uniform.txt";
std::string archnom = "../data/uniform.txt";
std::string archnom = "data/uniform.txt";
What is the problem here?
In a terminal, you can type ./build/a.out to launch the a.out program with ./ as the current working directory.
When you do this, relative filepaths that are used in your program are relative to the ./ dir -- not the one which contains the program.
For example, if I want to open ex.txt when running ./build/a.out (and ex.txt is in the same directory as build), my program should have the relative path ./ex.txt - not ../ex.txt.
std::string archnom = "../data/uniform.txt";
Tells the program that uniform.txt can be found by going back one directory and then up into data.
But in what directory does the program start looking? Good question. That location is called the Working Directory, and unfortunately it MOVES. Typically the working directory starts as the directory the program is run from, not where the program is. For added excitement your program can change the working directory while running.
So if your program is at /home/bob/code and the uniform.txt file is at /home/bob/data and you run the program from /home/bob/code with ./program all is good. The working directory is /home/bob/code and the program goes back one folder and then up into data.
What if you were in /home/bob/workspace and you ran ../code/program. The working directory is /home/bob/workspace and the program goes back one folder and into data.
But what if you run the program from / with /home/bob/code/program? The working directory is /. You can't really go back anywhere, can you?
Let's try a less extreme case: /etc. Program goes back to / and forward to... rats. No data directory.
If the uniform.txt file is always going to be in the same place and this place is guaranteed, use a fixed path. If uniform.txt is going to be somewhere near the installation directory of the program, your program needs to know where it is and that takes OS specific code.
You need to make sure the current working directory is where you expect it to be. You can do that by using _chdir (win32) or chdir (gcc) and by using argv[0] (which contains the path to the currently running executable).
I showed how to do this in my answer to another question here :
Change the current working directory in C++
Related
Hey, I've been writing a program (a sort of e-Book viewing type thing) and it loads text files from a folder within the folder of which the executable is located. This gives me a bit of a problem since if I run the program from another directory with the command "./folder/folder/program" for example, my program will not find the text, because the working directory isn't correct. I cannot have an absolute directory because I would like the program to be portable. Is there any way to get the precise directory that the executable is running from even if it has been run from a different directory. I've heard could combine argc[0] and getcwd() but argc is truncated when there is a space in the directory, (I think?) so I would like to avoid that if possible.
I'm on Linux using g++, Thanx in advance
EDIT - don't use getcwd(), it's just where the user is not where the executable is.
See here for details.
On linux /proc/<pid>/exe or /proc/self/exe should be a symbolic link to your executable. Like others, I think the more important question is "why do you need this?" It's not really UNIX form to use the executable path to find ancillary files. Instead you use an environment variable or a default location, or follow one of the other conventions for finding the location of ancillary files (ie, ~/.<myapp>rc).
When you add a book to your library you can remember its absolute path.
It is not a bad when your program rely on the fact that it will be launched from the working dir and not from some other dir. That's why there are all kinds of "links" with "working dir" parameter.
You don't have to handle such situations in the way you want. Just check if all necessary files and dirs structure are in place and log an error with the instructions if they are not.
Or every time when your program starts and doesn't find necessary files the program can ask to point the path to the Books Library.
I still don't see the reason to know your current dir name.
#include <boost/filesystem/convenience.hpp>
#include <iostream>
#include <ostream>
int main(int argc, char** argv)
{
boost::filesystem::path argvPath( argv[0] );
boost::filesystem::path executablePath( argvPath.parent_path() );
boost::filesystem::path runPath( boost::filesystem::initial_path() );
std::cout << executablePath << std::endl;
std::cout << runPath << std::endl;
return 0;
}
You can get the path of the running program by reading the command line. In linux you can get the command line by reading /proc folder as /proc/PID/CommandLine
argv[0] is not truncated when there are spaces. However, it will only have the program name and not the path when a program is run from a directory listed in the PATH environment variable.
In any case, what you are trying to do here is not good design for a Unix/Linux program. Data files are not stored in the same directory as program files because doing so makes it difficult to apply proper security policies.
The best way to get what you want in my opinion is to use a shell script to launch the actual program. This is very similar to how Firefox launches on Linux systems. The shell places the name of the script into $0 and this variable will always have a path. Then you can use an environment variable or command line argument to give your program the location of the data files, like this:
dir=`dirname "$0"`
cd "$dir/../data/"
"$dir/real-program"
And I would arrange your program so that it's files are somewhat like this:
install-dir/bin/program
install-dir/bin/real-program
install-dir/etc/config
install-dir/data/book-file.mobi
If this has already been answered elsewhere, I'm sorry, I couldn't find it.
I have an interesting problem whereby I have a compiled program, prog.exe, which reads a file prog.cfg which contains the config. If I open prog.exe by double-clicking on it, everything's good. However, if I open it from a command line or batch file, I first have to set the directory. For example, if I have my program in a progs folder on the desktop, and from the desktop run progs\prog.exe, it doesn't load the config because it's looking for the config on the desktop ie in the current working directory.
This is fine if you know about it, but it's just another hoop for users to jump through. Is there a way in c++ to backtrack to the command used to launch the program to deduce whether the config file will be in the current working directory or not?
Alternatively, am I asking completely the wrong question?
Many thanks!
You can use GetModuleFileName(nullptr, buf, bufsize) to get a path to the executable.
Note that the standard main function's argv[0] is not guaranteed to provide that path, and when it provides a path, is not guaranteed to provide a programmatically usable representation of the path.
if i understand you correctly, you always want your .exe read your .cfg file from the folder your .exe located? right?
try argv[0].
argv[0] is your full .exe path when you run your exe, and it is a parameter of main function.
I'm trying to use Mac Instruments Time Profiler to optimize my code for building a MandelBox. I found how to make my executable my target process, but when the program runs, it gives me an error in the Console window saying it cannot find the .txt file associated with the program.
Do I need to tell the profiler where to look to find the file? The text file is already in the same directory as the executable. Any thoughts? Thanks.
This problem is not unique to Instruments. The same thing would presumably happen if your current working directory was something other than the location of your program. For example, if you were to do cd / ; /path/to/yourprogram.
You either need to make your program find its own location and then find its text file as a sibling in the containing directory or take the path of the text file as an argument. Or, you will always have to set the working directory to your program's location before invoking it.
That last approach is an immediate workaround for the problem with Instruments. On the panel where you choose the target executable, you can also configure various parameters, such as arguments, environment variables, and the working directory. Set the working directory to the directory that contains the text file and it should work.
I have made a simple scoring system which upon correct answer, stores the numbers of the player in the file.
I have used the file name like this :
ofstream outfile ("C:\Aadam\Desktop\Project\Scores.txt",ios::app);
But the problem with this approach is that what if I move the program over to a USB and try to run it in another computer. Now it will look in the directory I specified above but there is no Scores.txt file in there.
What I want to do is to give it a path which is in the project folder. So when I move the program, it shouldn't make a difference because I will move the whole project folder.
Of course I can do this :
ofstream outfile ("Scores.txt",ios::app)
which will always look in the project directory and it will work fine as long as I run the program from the IDE but what if I run the program from the .exe file which is two directories down like
"C:\Aadam\Desktop\Project\bin\Debug\Project.exe"
Now in this case, it can't open the file.
So if you know a good way to open files and kindly, Show me the Way.....
You can parse argv[0] (it will contain path used to invoke your executable - absolute or relative) and replace executable name in it with "Scores.txt"
The easiest way is to pass the file path to program as an argument.
When you run a program from IDE, the project directory is considered as current working directory. If the program is run from the command line, the current working directory is from where the command is being run.
If you run the exe file,ofstream outfile ("Scores.txt",ios::app) will create a file named "Scores.txt" in the same directory as your program.
I accidentally made a big blunder:
In my C++ program, I did:
std::string oldFilePath = "/Users/blah/somepath/foo.xml";
std::string newFileName = "foo.xml" //Blunder! Forgot to prefix the new path!
int status = rename(oldFilePath.c_str(), newFileName.c_str());
I forgot to prefix the new path, and just put the filename (without a path) for the new name that the file should be renamed to. As a result the file has vanished from the old path, and I don't know where its gone to!
Where is the file ? Is there a way to recover it ? (Time Machine is disabled for this folder, so I can't do that!)
EDIT: Where would the compiled file generated by Xcode for a C++ application be ?
EDIT: If you're running the program through xcode, it should be in:
~/Library/Developer/Xcode/DerivedData//Build/Products/Debug/
Don't forget the ~ in the above path!
If the operation succeeded (status == 0), the file would be in the current directory of the process when it was run. It is hard to predict where that might be, but $HOME is one plausible candidate (maybe /Users/blah/foo.xml). You should be able to find it, either with the find command or with Spotlight.
I don't use the XCode UI (or other IDEs), in part because I don't like the lack of control over things like 'where the program is put' and 'what is the current directory when I run the program' (and for the rest because I'm a dinosaur). AFAIK, the executable should be in a directory underneath the folder where you created the project. Again, Spotlight or find should be able to help you, at least if you chose a distinctive name for the program. The project directory is another place to look for the foo.xml file too.