Passing relative path to ifstream c++ - c++

I am working on dev c++. I am using file stream to open a file which is already placed in a folder. Below is my code.
int main(){
ifstream file; // File stream object
string name; // To hold the file name
//Write the path of the folder in which your file is placed
string path = "C:\\Users\\Faisal\\Desktop\\Programs\\";
string inputLine; // To hold a line of input
int lines = 0; // Line counter
int lineNum = 1; // Line number to display
// Get the file name.
cout << "Enter the file name: ";
getline(cin, name);// Open the file.
string fileToOpen = path + name + ".txt";
file.open(fileToOpen.c_str(),ios::in);// Test for errors.
if (!file){
// There was an error so display an error
// message and end the PROGRAM.
cout << "Error opening " << name << endl;
exit(EXIT_FAILURE);
}
// Read the contents of the file and display
// each line with a line number.
// Get a line from the file.
getline(file, inputLine, '\n');
while (!file.fail()){
// Display the line.
cout << setw(3) << right << lineNum<< ":" << inputLine << endl;
// Update the line DISPLAY COUNTER for the next line.
lineNum++;// Update the total line counter.
lines++;// If we've displayed the 24th line, pause the screen.
if (lines == 24){
cout << "Press ENTER to CONTINUE...";
cin.get();
lines = 0;
}
// Get a line from the file.
getline(file, inputLine, '\n');
}
//Close the file.
file.close();
return 0;
}
My file is in the same folder where my program resides i.e. in my C:\\Users\\Faisal\\Desktop\\Programs\\. However, I want to use a relative path, so whoever runs the program can access the file.
How can I pass the relative path?
Any help would be highly appreciated.

Consider using /tmp directory on unices and System.IO.Path.GetTempPath() on Windows.
How to get temporary folder for current user
If you decide to use current working directory, you need to find current working directory executable cwd which is not at the same place on all platforms.
How do I get the directory that a program is running from?
Check out https://en.cppreference.com/w/cpp/filesystem/current_path also

Related

Can't open file properly in C++

I'm trying to read each line from a .geom file and save that in a string.
The user shall input the correct (absolute) filepath and then, until now, should get the content of the .geom file printed out on the console.
The problem is that under every circumstance it seems impossible to open the file via my c++ program.
Everytime I check if the file is opened via is_open() it responds with false.
The program, my IDE and the .geom file are all on the same drive and i am currently using windows. The IDE im using is Codeblocks and the executable is build in it.
This is my complete code until now:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//a function to check if the given file has the .geom extension
bool isGeom(string file){
if(file.substr(file.find_last_of(".") + 1) == "geom") {
return true;
} else {
return false;
}
}
//main func
int main()
{
string filepath, geomInput, line;
cout << "----- GeomView2obj -----" << endl;
cout << "Please enter a valid file path to a .geom file to convert it to an .obj file: \n" << endl;
//get file path by user
getline(cin, filepath);
//declare stream and open file if possible
ifstream geomFile (filepath.c_str());
if(!geomFile.is_open()){
cout << "\nERR: The given file path is invalid or the file does not exist!" << endl;
return 1;
}
if(!isGeom(filepath)){
cout << "\nERR: The given file is not a .geom file!" << endl;
return 1;
}
//read chars from geom file
while(getline(geomFile, line)){
geomInput.append(line + "\n");
}
//print string --- DELETE
cout << geomInput;
geomFile.close();
return 0;
}
I also tried to first declare my ifstream and then opening the file.
I also turned the user input off and entered an absolute path where every folder was seperated with two backslashes \\ instead of one.
I also copied the file to the folder the compiled program lies in and giving the program a relative path to the file as an input, but that also did not help.
Any form of help is much appreciated!

Cannot find input file [duplicate]

This question already has an answer here:
Cannot open input file
(1 answer)
Closed 7 years ago.
I am trying to create a program that asks the user for the name of a file, then opens the file, adds the sum of all the integers listed on the file, then writes that sum on an output file.
After writing my code and saving the testfile1.txt into the same folder as the program, the program keeps giving me the: "could not access testfile1" (message I output to notify myself that it is unable to open the testfile1.txt).
Here is what I have so far (skipped the lines with description blocks):
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
ifstream inputFile;
ofstream outputFile;
string testfile1;
string sum;
int total = 0;
int num;
cout << "Please input name of file." << endl;
cin >> testfile1;
cin.get();
inputFile.open(testfile1.c_str());
if (inputFile.fail()) {
inputFile.clear();
cout << "could not access testfile1" << endl;
return(1);
}
while (!inputFile.eof()) {
inputFile >> num;
total = total + num;
inputFile.close();
}
outputFile.open(sum.c_str());
outputFile << total << endl;
outputFile.close();
if (outputFile.fail()) {
cout << "could not access file." << endl;
return 1;
}
return 0;
}
Question:
How can I make this program find and open the testfile1.txt?
Note:
I am pretty sure that when prompted for the file name, I did not misspell.
Here are few remarks that will help you figure out the possible problem:
1.You could reduce some lines of code by attaching your streams to a file during definition, instead of defining them and then use open, like so:
ifstream inputFile(testfile1.c_str());
2.To check if a file is open (and handle if it couldn't):
if (!inputFile) error ("Can't open input file: ", testfile1);
and:
if (!outputFile) error ("Can't open output file: ", sum);
right after the definition.
3.All open files are implicitly closed at the end of the program (or a function that contains them), so there is no need to explicitly close() them.
4.To read the contents of the input file and sum them:
int sum = 0;
string line;
// read a line
while (getline(inputFile, line)) {
stringstream ss(line);
// assuming you are reading integers separated by white space
int num = 0;
// extract each number on the line
while (ss >> num) total += num;
// reset line
line.erase();
}
Note: test and modify your code according to your specific needs. A side note: you could probably omit: cin.get(); in your code.
use getline (std::cin,name);
for input name
and use proper function of ostream for reading and writing.
you'r getting input wrong at line 21 and line 22

ifstream opens files named by cin but not when pulled from an array. Any difference between cin and a regular string definition?

TL;DR File names stored as strings in array (using new) - ifstream won't open them (perror returns "No such file or directory"). Swap out array variable with a call to the user to name the file (using cin) - ifstream opens the file. Why? How do I get the array to work?
Things to Know
All files exist in folders with naming scheme run20### where
All files are named S20###.ABC where ### is the same from the parent directory and ABC can go from 001-999. These are all text files (there are no .txt extensions though) that CAN be opened by ifstream and getline.
I'm writing a program that's going to pull information from up to 150 files. An early version I wrote had the user input the file name (using cin). ifstream took the stored name and opened the file successfully every time. Obviously, I don't want to type 150 file names in so the program stores all of the file names as strings in an array for the program to pull from. However, when it goes to open the file (in the correct path and with the correct file name and extension), the error I get from perror returns "No such file or directory." If I just do a quick swap of the variables though so that the file name comes from cin, the file opens. Why would cin work and the array version not? Is there any way to get the array to work?
I've also tried something similar where there is no array. Instead, in the for loop that would pull the files from the array, the file gets named each time.
Here's the code (sorry about the headers, couldn't get it to format right):
#include <iostream>
#include <array>
#include <string>
#include <ctime>
#include <cstring>
#include <fstream>
#include <sstream>
using namespace std;
int main() {
//--------------------------Initial setup----------------------------------
cout << "Please give the full name of the folder you would like to open in the /Users/lucas/HPS/TDCData directory" << endl << endl;
string sFolderName;
cin >> sFolderName;
// Create path. I have mine here but you'll have to change it to something you'll
// use if you want to run the code
string sPathName = "/Users/lucas/HPS/TDCData/" + sFolderName;
//----------------Create file name array------------------------------------
// Get naming base from the folder name given
string sFileBase = "S20";
for (int i = 5; i <= sFolderName.length(); i++){
sFileBase = sFileBase + sFolderName[i];
}
//Specify range since different directories have different numbers of files
cout << "Files must be named S20###.ABC" << endl;
cout << "Specify a range for ABC" << endl;
int iFloor;
int iCeiling;
cout << "Floor: " << endl;
cin >> iFloor;
cout << "Ceiling: " << endl;
cin >> iCeiling;
// Define an array to store names and then store them
string *aFiles;
int iFilesSize = iCeiling - iFloor + 1;
aFiles = new string [iFilesSize];
cout << "Array created" << endl;
for (int i = iFloor; i <= iCeiling; i++){
string name = sFileBase;
if (i < 10){
name = name + ".00" + to_string(i);
}
else if (i < 100) {
name = name + ".0" + to_string(i);
}
else {
name = name + '.' + to_string(i);
}
aFiles[i-1] = name;
}
//----------------Open each file in aFiles----------------------
for (int i = 0; i < iFilesSize; i++){
// There are two important lines of code here. The first gets sFileName from
// aFiles. The second gets sFileName from user input using cin (this is commented out).
// Obviously, none of the last section of code is needed for the second line to work.
// The first line does not work for me. The second does.
string sFileName;
//First
sFileName = aFiles[i];
//Second
//cin >> sFileName
string sFullPath = sPathName + "/" + sFileName;
cout << "Searching ... " << sFullPath << endl << endl;
//Open file
ifstream inputFile(sFullPath);
//Check that the file opened
if (! inputFile.is_open()) {
cout << "Error reading" << sFullPath << endl;
perror("Error is: ");
return 0;
}
else {
cout << "File opened successfully..." << aFiles[i] << endl << endl;
}
}
cout << "All files opened..." << endl << endl;
return 0;
}
Also here's a link to a zip of one of the directories for any tests someone might want to run. Thanks for any and all help!
It looks like you start filling aFiles from index iFloor, while you start reading aFiles from index 0.
How about changing aFiles[i-1] = name; to aFiles[i-iFloor] = name;
"TL;DR File names stored as strings in array (using new)"
Don't do this. Use a dynamic container like std::vector<std::string> instead.
"- ifstream won't open them (perror returns "No such file or directory")."
Use the debugger to check what's actually passed to the
ifstream inputFile(sFullPath);
with sFullPath.
"Swap out array variable with a call to the user to name the file (using cin) - ifstream opens the file. Why? How do I get the array to work?"
You cannot replace the behaviors of a stream getting values as you're trying with the array.
The best way to make the input stream source transparent, is to simply use a std::istream reference, and don't care if it's std::cin or e.g. a std::istringstream reference.
The std::string instance needed to initialize the mentioned std::istringstream can be build e.g. using a std::ostringstream and pass the str() property to the std::istringstream constructor.

Xcode: Where to put input file?

I'm trying to learn C++ and I'm using Xcode. I have the following main method:
int main()
{
const int SIZE = 256;
Expression* expression;
char paren, comma, line[SIZE];
ifstream fin("input.txt");
while (true)
{
symbolTable.init();
fin.getline(line, SIZE);
if (!fin)
break;
stringstream in(line, ios_base::in);
in >> paren;
cout << line << " ";
expression = SubExpression::parse(in);
in >> comma;
parseAssignments(in);
double result = expression->evaluate();
cout << "Value = " << result << endl;
// catch the exceptions
return 0;
}
}
Where do I put the file "input.txt" so the program can read it?
The filename parameter of ifstream is usually taken as a relative path to the working directory so that's where you should put the file.
If you launch the executable from a file manager, the working directory of the process will most likely be set to the directory the executable is in. In that case the text file should be in the same directory.
All relative paths (on OS X, any path that doesn't start with a slash, "/"), are interpreted relative to a process' working directory.
If you're running from the terminal, it should be in the terminal's current directory (i.e. ls should list it).
If you're running from inside XCode, there is a project setting for which directory should be the working directory.
You set that to wherever your file is, or move the file to wherever that directory is.

Segfault during file read

The program is supposed to prompt the user for their username. Upon receiving the username it concatenates it with '.history' to create username.history. Then it opens that file (username.history) and reads the input from it. I am running into a segfault here though. Whenever it opens the file, which is empty because the file doesn't exist, it reads multiple lines and then throws the segfault. I think the problem might stem from how I'm trying to open the file, but I'm not sure. Here is the portion that is causing problems:
// File input and output
ifstream f_in;
ofstream f_out;
// Prompt user for their username.
char username[80];
cout << "Please input your username: " << endl;
cin >> username;
cout << endl;
cout << "Loading history file if it exists." << endl;
// Create file naem and initialize the file line counter to 0.
strcat(username, ".history");
int fcount = 0;
// Open file and read in lines if there are any.
// Place read lines into the command string for use later.
char tmp[50];
f_in.open(username);
while(!f_in.eof()){
f_in >> tmp;
cmd[fcount] = tmp;
fcount++;
}
f_in.close();
Other pertinent info:
cmd is declared as a global variable (char cmd[200][50])
Any help will be greatly appreaciated.
Not sure if it is the only issue, but cmd[fcount] = tmp is wrong. You should use strcpy().
while(f_in.good())
{
f_in >> tmp;
cmd[fcount] = tmp;
fcount++;
}