exe does not find a text file in the same directory - c++

I am running an exe that reads text from a file, which is saved in the same directory as the exe.
I am using the _tfopen function, that returns errno 2, which means that the file is missing.
As is already said, the text file is in the same directory as the exe, so Im using only filename of the text file and not the whole path (even though ive tried to use the absolute filepath...).
I am running the exe from a different computer, not the one I am developing on (The release version).
Another application that using the same file, also in the same directory, works perfectly.
Why does the exe cant find the text file?
FILE* fileData;
if ((fileData = _tfopen(_T("Data.txt"), _T("r"))) == NULL)
return false;

You might want to try this: have your program call GetCurrentDirectory() and output the result somewhere to that you can confirm that the program's current directory is truly what you think it is. You could use OutputDebugString() if you are running under a debugger or MessageBox() if not.
When I need to be sure I'm opening a co-located file, I call GetModuleFileName( NULL, szExeFqn, sizeof(szExeFqn)) to get the FQN of the EXE file, strip off the EXE file name and add on the name of the file I need. That way, I'm not making any assumptions that might be false -- after all, it is trivial to have a shortcut set the default directory for a program different from the directory containing the EXE file.
Also, if you run your program from a command line by entering the full path to your program, then the program's current directory is the one you were in when you ran it, not the one where the EXE was found. That's also true if your program is found by searching the PATH environment variable (yes, it still exists in Windows.)
Here's an example of what I've used for more than a decade to do what you've described:
char szHelpFileName[_MAX_FNAME];
char *cp;
GetModuleFileName( NULL, szHelpFileName, sizeof(szHelpFileName) );
cp = strrchr( szHelpFileName, '\\' );
if( cp )
{
cp++; // Point to the char just following the final slash.
}
else
{ // No backslash, is there a colon?
cp = strrchr( szHelpFileName, ':' );
if( cp )
{
cp++; // Point to the char just following the colon.
}
else
{ // I give up. I'll have no path information.
cp = szHelpFileName;
}
}
strcpy( cp, "program.hlp" );
The final result is the name of a help file that is co-located with the EXE. Unless the help file is missing (or its permissions have been scrogged somehow) this always works. I've never had it follow the "paranoia" path where the comment says "I give up."

Usually operating systems open files with relative address based on the current directory, rather than the executable location.
So for example if your executable is in /path/to/exec/executable and you invoke it from /path/to/invoke, it will try to open Data.txt as if it was /path/to/invoke/Data.txt.
You can take a look at this question and its answers to find out how to find the path to executable in Windows. Or this answer for various other operating systems.

It should work even without specifying the full path. Do you launch the executable from Visual Studio? If yes, make sure that the Data.txt file is inside the project directory where the *.vcxproj file or the *.sln file is.

Related

Where would incorrectly named files (rename without specifying the path) be moved to?

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.

Opening a file in the current directory

I'm trying to load files, and previously I was using hardcoded file locations, (like "c:\location\file.txt") but now that a few friends are also using the file, I'd like to allow them to put the executable wherever they want.
my current code looks like:
ifstream myfile;
myfile.open("c:\\client\\settings.cfg");
I'm trying to change it so that the user puts their executable into whatever folder they want, and then they create a folder and put their settings file into it and the exe will load that with their settings.
ifstream myfile;
myfile.open("\\settings\\settings.cfg");
I have some basic error handling in place, and now the program always errors out saying that it can't find the file.
The file structure looks like this:
[ART]
asset.png
[SETTINGS]
settings.cfg
client.exe
This seems like a really simple thing to do, but I can't find any way to do it. Every example and tutorial about reading and writing to files deals only with files in the executable's directory, or hardcoded into c:\folder...
Could anyone point me to how I do this?
The search path for most systems starts with the current working directory and then to a PATH environment variable. So, all you need to do is specify the file/folder without the absolute path markings and it will use the path relative to the working directory:
ifstream myfile;
myfile.open("settings\\settings.cfg");
// ^^ Note the lack of \\ to start the file path
Paths beginning with \ are always relative to the current drive's root directory. If the current drive is C:, then \settings\settings.cfg means C:\settings\settings.cfg.
Note that you can use / in order to avoid escaping everything. So you can use: settings/settings.cfg. This will be relative to the user's current directory. Note however, that this doesn't necessarily correspond to the directory where the executable resides. If you need the directory of the executable, then you need to use a Windows API function to get it:
#include <Windows.h>
// ...
HMODULE module = GetModuleHandleW(NULL);
WCHAR path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
Now if you want to open settings/settings.cfg relative to the directory of the executable, create a path that starts with path and append /settings/settings.cfg to it.

relative path for searching directory with FindFirstFile

in the directory containing my exe I have a folder called "saves".
I want to display the files this directory contains.
I used the code found here:
Listing directory contents using C and Windows
Now the tricky part.
if I use .\\saves\\ as my directory it tells me that the path could not be found.
However if I use ..\\release\\saves\\ it works fine. But that's stupid. I don't want to go to the parent folder and than go back. Especially regarding that I don't know what name the user gives to the directory containing the exe (in my case it's "release" but who knows what the user does :-D).
I read through this: http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#fully_qualified_vs._relative_paths but it didn't help very much.
I also tried saves\\ or .\saves\\ but it doesn't work either.
I hope somebody can tell me how to fix this.
You're actually doing nothing wrong in code -- you've been launching the project from Visual Studio, which sets the Working Directory to the parent of the Release/Debug folders.
Go to Project->Settings(Properties)->Configuration Properties->Debugging->Working Directory
You can also run the exe outside of VS and the relative paths will behave like you expect.
If it is relative from the path to the executable, and not from the path of the current working directory, you could use GetModuleFileName() to obtain the full path to the executable. Then, remove the name of the executable from the end of the path and build the paths using that:
std::string executable_directory_path()
{
std::vector<char> full_path_exe(MAX_PATH);
for (;;)
{
const DWORD result = GetModuleFileName(NULL,
&full_path_exe[0],
full_path_exe.size());
if (result == 0)
{
// Report failure to caller.
}
else if (full_path_exe.size() == result)
{
// Buffer too small: increase size.
full_path_exe.resize(full_path_exe.size() * 2);
}
else
{
// Success.
break;
}
}
// Remove executable name.
std::string result(full_path_exe.begin(), full_path_exe.end());
std::string::size_type i = result.find_last_of("\\/");
if (std::string::npos != i) result.erase(i);
return result;
}
I would use boost::filesystem
http://www.boost.org/doc/libs/1_53_0/libs/filesystem/doc/index.htm.
As a bonus you will get operating system independent code.
I think your mistake was using \\saves\\and forgeting to specify a search parameter/string
You should use:
saves\\*
this will search for any file or folder

How do I use fstream to write to a file above the executable's directory in C++?

I'm trying to write to a file that is not in the directory that the executable is in; I also want it to work no matter where the executable is (I believe that would rule out using ".."). I need this to work on Linux. Thank-you.
This has been asked already, see Get path of executable or Finding current executable's path without /proc/self/exe for a good answer, or search yourself.
Your problem boils down to getting the absolute path to the running executable.
A relative path is usually resolved starting from the running directory, which is not necessarily the executable directory (rather the current directory in the shell from which the executable is launched).
Under linux, you can read the directory of the executable with:
readlink /proc/self/exe
or you could use boost fs::path and fs::system_complete. Then you have to remove from that string the last component, which is the executable name.
Once you have the path of the executable directory, append "/.." to it and you will get the directory above the executable directory.
You can use an absolute path, if you know it ahead of time:
fstream * fs = new fstream("~/config_file");
If the file varies, you can take the path from user input or a configuration file.
Depending on where the file is, whether it moves and where the program is, you may actually be able to use a relative path. From the info you've given, I couldn't tell.
You can do this easily, but you will have to have an absolute path to the file you want to work on, or you will have to create some relative file-structure between your executable and the file you are wanting to access.
Another option is you could, using a forked process or popen(), launch find, and give it the appropriate arguments to locate the document you are wanting to work on, and then use that returned string as the argument to create the fstream object to write to or append to that file.
So for instance, this could look something like:
#include <limits.h>
#include <fstream>
#include <stdio.h>
char buffer[PATH_MAX];
//search the entire file-system starting from the root for "my_specific_file.txt"
FILE* located_file_handle = popen("find / -name my_specific_file.txt -print", "r");
//get the first file returned from the find operation and close the pipe
fgets(buffer, PATH_MAX, located_file_handle);
pclose(located_file_handle);
fstream file(buffer);
If you think there will be more than one file returned from the call to find, then you should cycle though each of them using fgets until you locate the one you want.

Opening a file with a certain program changes that programs working directory?

I have a file saved to my desktop, when I open it with my program the working directory changes to the desktop, this means my program can not load in some files it needs as it searches for these in the working directory. Is there a way I can stop the working directory from changing like this?
There's a flag you can set to avoid the current directory from changing called OFN_NOCHANGEDIR
http://msdn.microsoft.com/en-us/library/ms646839(v=vs.85).aspx
You can just save your working directory at startup and use absolute paths. In fact, it's better to always open files with absolute paths, unless you really want to rely on the current working directory.
You would be better off determining the processes location, then using it as the key for where to find the other files? There are many ways that programs can be launched, which effect the working directory.
See: The answer here for a good description of how to get the processes location and strip out the executable filename (look in the comments)
Essentially, you use:
GetModuleFileName or GetModuleFileNameEx.
and then:
PathRemoveFileSpec to remove the file name
Opening a file doesn't change your current directory. Perhaps you using the common open file dialog? Here is an article that will explain all about how that changes your current directory.
use SetCurrentDirectory to do that.
You can locate the executable by using GetModuleFileName
TCHAR szFileName[MAX_PATH];
GetModuleFileName( NULL, szFileName, MAX_PATH )
... then compute the correct directory
SetCurrentDirectory(path);