fstream: Why must my files contain the path to load properly?

Can you tell me why the files I'm loading in the code below will not load without their full file paths? The files are in the same directory as the executable.

I would like to eventually replace the filename with a user variable, so I can't include the paths in the final version.

I'm using Xcode, and oddly enough the program works fine without paths within Xcode, but when I try running the executable directly from finder, I get a file load error ("Unable to open airship.syx\n" defined in the code below).

Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>

int main () {
	
	char buffer[128]={0};
	long size;

// using the direct filenames didn't work; I had to include the paths as well.
//	ifstream infile ("airship.syx", ios::binary);
//	ofstream outfile ("copy.syx", ios::binary);
	ifstream infile ("/Users/mbuchanan/Documents/opensysex/build/Debug/airship.syx", ios::binary);
	ofstream outfile ("/Users/mbuchanan/Documents/opensysex/build/Debug/copy.syx", ios::binary);
	
	if (!infile)
    {
		cout << "Unable to open airship.syx\n";
		return EXIT_FAILURE;
    }
	
	//get size of file
	infile.seekg (0, ifstream::end);	
	size = infile.tellg();
	infile.seekg(0);
	
	//read content of infile
	infile.read (buffer, size);
	
	//write to outfile
	outfile.write (buffer, size);		
	
	//close files
	outfile.close();
	infile.close();
	
	return 0;
}
Last edited on
If you specify a relative file name, it is relative to the current working directory. Which one that is depends on how the program was started.
It doesn't have anything to do with C++, in any case.
It depends on how the program was started? So the current working directory is not guaranteed to be the directory that the program is run from?

I seem to have bypassed my issue by pulling the path from argv[], removing the program name, appending the filename, and opening that as the path.

It's probably not an elegant "fix", but it'll work for now. Thanks for your help!

New code here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
int main (int argc, char *argv[]) 
{
	
	char buffer[128]={0};
	char parameter[59]={0};

	char a, b=1, i=0;
	jx8p patch={0};
	long size;
	
	string path, filename, filepath;
	size_t end;
	
	//get path
	for(i = 0; argv[i] != 0; i++)
	{
		path += argv[i];
	}
	
	//remove program name
	end=path.rfind("/");
	if(end!=string::npos)
	{
		path.replace (end, 100, "/");
	}
	
	cout << "\nPlease enter input filename: ";
	cin >> filename;
	
	//append filename to path
	filepath.append(path);
	filepath.append(filename);
	cout << filepath;
	ifstream infile;
	
	infile.open(filepath.c_str(), ios::in | ios::binary);
	
	//check if infile opened ok
	if (infile.is_open())
	{
		cout << "\n" << filename << " successfully opened.";
	}
	else
	{
		cout << "\nError opening file " << filename <<" \n";
	}
	//get size of file
	infile.seekg (0, ios::end);	
	size = infile.tellg();
	infile.seekg(0, ios::beg);
	
	//read content of infile
	infile.read (buffer, size);
	
	//write buffered values to header 
So the current working directory is not guaranteed to be the directory that the program is run from?


Correct.

For example, At the command line, it is wherever you are then time. So if you start an executable in a different directory it won't be the exe's directory.

This little bit of code doesn't look quite right to me

1
2
3
4
5
	//get path
	for(i = 0; argv[i] != 0; i++)
	{
		path += argv[i];
	}


arg[0] is generally the path. I would have thought you need to get the app path (arg[0]), remove the file spec, and then append the filename (arg[1]) to it. Handling multiple files would involve more work. (I'm not sure I understand the command line: does it take a file name?)

I am not sure how Mac works, but I do know that the Linux and Windows command lines behave differently depending on how the app was launched. So it sometimes turns up as a full path, and sometimes a relative path. So I convert to to always be a full path with either _fullpath() or realpath() -- the latter should work for OS X.

(where maxPath is defined to _MAX_PATH or PATH_MAX -- not 100% sure about the latter)

1
2
3
4
5
6
7
8
9
10
11
12
13
int
main(int argc, char* argv[])
{
    ....
	
    char basePath[maxPath] = "";
#if defined(_MSC_VER) || defined(__MINGW32__)
    _fullpath(basePath, argv[0], sizeof(basePath));
#else
    realpath(argv[0], basePath);
#endif

    ...


Also,
Last edited on
Topic archived. No new replies allowed.