Reading multiple files in directory in C++ - c++

Hi I am new to c++ and was wondering if we could read from multiple files all saved in a single directory. Basically I have a folder consisting of a number of text files and I want my program to read the files. The thing is the folder can be updated (new files added or existing files deleted) so cannot specify in the program the number of and name of files to read (I want to read all the files). So is there a way to do this?

#include <iostream>
#include <fstream>
#include <string>
void run_with(const char* filename) {
std::ifstream fi(filename);
std::string s;
fi >> s;
std::cout << filename << " : " << s << std::endl;
}
int main(int argc, char** argv) {
for (int i = 1; i < argc; ++i) {
run_with(argv[i]);
}
Here you go. Its bassically opening one file but you open it multiple times.

Related

How to open a text file

I am trying to open a text file, and the code below is my attempt:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
std::ifstream file;
file.open("InputFile.txt");
std::string fileOutput;
if (file.is_open())
{
while (!file.eof())
{
file >> fileOutput;
std::cout << fileOutput << std::endl;
}
}
else
{
std::cout << "File failed to open" << std::endl;
}
file.close();
return 0;
}
The text file is located on my desktop, and it only contain two integers.
Whenever I run the code above, it will show me the "file failed to open" message. I am completely new to c++, so I really don’t have any idea why my code is not working. So any comments would be appreciated.
The text file is located on my desktop
So where is your C++ source file, is it located in my desktop as well?
Note this code file.open("InputFile.txt"); tries to open the InputFile.txt in the current folder, that means it only works if both C++ source file and your text file are in the same folder. That seems to be your problem.
Like #ShadowRanger's this comment, the existing answers are both inaccurate. The argument for file.open() needs to either 1. reflect the relative location of the text file in relation to the current working directory (where you are calling the executable from), or 2. give the absolute location of the text file on the disc.
I suggest the following solution:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "incorrect number of inputs" << "\n";
std::cout << "correct usage: this_executable.exe file_location" << "\n";
return -1;
}
std::ifstream file;
file.open(argv[1]);
std::string fileOutput;
if (file.is_open())
{
while (file >> fileOutput)
{
std::cout << fileOutput << std::endl;
}
}
else
{
std::cout << "File "<< argv[1] <<" failed to open" << std::endl;
}
file.close();
return 0;
}
This solution takes the file's address info out of the code. With this solution, when you call your executable, the file's address(directory path + file name) is given to the executable at run-time rather than compile-time. Now, you'd run the executable like:
C:\path_to_your_exe>my_executable.exe C:\path_of_your_txt_file\InputFile.txt
The benefits of this approach are:
You can change the file's name / path without having to recompile the code;
On the commandline, it is easier to check that the target file's address is correct by tab completion
Also note:
As #ShadowRanger also pointed out the Why is “while ( !feof (file) )” always wrong? issue which I was not aware of.
If you are wondering what argv[1] means, see this guide for more information on commandline arguments for C++. You also want to make sure to catch situations when the user did not specify an input (meaning argv[1] is invalid, thus the argc != 2)
Unless the file you are opening and your executable are in the same directory, the same message will be printed since it will search for the file in the current working directory. You can specify the absolute path to the file on your desktop using %USERPROFILE%\\Desktop\\InputFile.txt or any other environmental variable that maps the absolute path of a disk, from which your file can be found.

Recieve 3 files by terminal and concatenate the content of file2 and file3 to file1 using fstream

I'm begginer in C++, so may be parts of my code doesn't have sense, sorry.
What I have to do is (C++, Linux, by fstream):
· Receive 3 or more files passed by terminal by:
./executable file1.txt file2.txt file3.txt
· programm a function that read the files file2.txt and file3.txt and copy it to file1.txt (concatenate, don't overwrite)
I don't know how to do it, I don't know anything about fstream, I'm just learning now by myself, so I really need help. Maybe there are similar questions solved in SO, but I don't know how to solve my problem by them.
I attach the code I have. I don't know how to code the function, so it's empty.
Thank you so much.
I try doing:
void concat(char *argv[], int numberoffilesreceived){
char c;
towritethefiles.open(argv[0], ios::app);
for(int i=1; i<numberoffilesreceived; i++){
toreadthefiles.open(argv[i], ios::in);
while(!toreadthefiles.eof()){
toreadthefiles >> c;
towritethefiles<< c;
}
}
}
It compiles but doesn't work, the program freezes when you run it.
and I also try using std::copy by I don't understand how it works.
ifstream toreadthefiles;
ofstream towritethefiles;
void concat(char *argv[], int numberoffilesreceived);
int main(int argc, char *argv[]){
/* 1/2 The code from below to 2/2 it's only to prevent path errors when receiving the files (it works fine) */
const char directory[SIZE]="./";
int count_files=0;
char files[SIZE][SIZE];
for(int i=1; i<argc; i++){
strcpy(files[i], directory);
strcat(files[i], argv[i]);
count_files++;
}
/*2/2 to add ./ to the name files when passed by terminal: ./executable ./file1.txt ./file2.txt ./file3.txt */
/*check if received almost 3 files like required */
if(argc<3){
cout<< "Error, to few files entered" << endl;
getchar();
exit(1);
}
/*pass the files to the concat function*/
for(int i=1; i<argc; i++){
concat(&argv[i], count_files);
}
toreadthefiles.close();
towritethefiles.close();
return 0;
}
void concat(char *argv[], int count_files){
}
I think I see an issue with your concat() function. You are calling concat() for each of the files passed in. Then in the function, you are using count_files to run that loop again for the number of files passed in.
I would consider rewriting concat() function so that it looks like this:
void concat(std::ofstream& outputStream, char* fileToAppend)
{
std::ifstream in(fileToAppend);
if (!in) {
cout << "Error, cannot open file: " << fileToAppend;
return;
}
// Use std::getline to read each line in the input stream,
// then write it to the output stream!
string line;
while (std::getline(in, line)) {
outputStream << line;
}
}
The benefit being that you can reuse the function for appending a single input file to an existing output stream, and you wrap up the check to ensure the file exists (you may want something more sophisticated like returning true/false on the file being appended, or throwing an error, etc.).
In main(), you would replace the code after the check for at least three files with something like:
// Create an output stream with the first file
// ios::out- output flag
// ios::app- append flag
std::ofstream out(argv[1], ios::out | ios::app);
// Make sure the file exists!
if (!out) {
cout << "Error, cannot open file: " << argv[1];
exit(1);
}
// For all other arguments, concat with the first.
for (int i = 2; i < argc; i++) {
concat(out, argv[i]);
}
You can use std::copy with stream iterators, and I've revised my previous suspicion that it would be slow, so here's one way using doing just that with comments in the code.
#include <iostream>
#include <fstream>
#include <vector>
#include <ios>
#include <stdexcept>
void concat(const std::string& destination, const std::vector<std::string>& sources) {
// open the destination file and keep it open until all is done
std::ofstream dest_fs(destination, std::ios_base::binary);
if(!dest_fs)
throw std::runtime_error("Could not write to \"" + destination + "\".");
// loop over the source files
for(const auto& source_file : sources) {
// open the current source file
std::ifstream source_fs(source_file, std::ios_base::binary);
if(!source_fs)
throw std::runtime_error("Could not read from \"" + source_file + "\".");
// copy from source to destination
std::copy(std::istreambuf_iterator<char>(source_fs),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(dest_fs));
}
}
int cppmain(std::string program, std::vector<std::string> args) {
if(args.size() < 2) {
std::cout << "USAGE: " << program << " destination_file input_file(s)\n";
return 1;
}
// extract the first argument which is the destination file
std::string destination_file = std::move(args.front());
args.erase(args.begin()); // erase first argument from the vector
try {
// do the concatenation
concat(destination_file, args);
return 0;
} catch(const std::exception& ex) {
std::cerr << program << ": ERROR: " << ex.what() << "\n";
return 1;
}
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], {argv + 1, argv + argc});
}

Why doesn't this open the file in the directory of the program?

I have this short program:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char * argv[]) {
std::string homedir = std::getenv("HOME");
std::string filename = argc > 1 ? argv[1] : (homedir + "/" + "file");
std::cout << homedir << std::endl;
std::cout << filename << std::endl;
std::fstream file;
file.open(filename, std::ios::out);
file << "Yo yo waddup" << std::endl;
file.close();
return 0;
}
When I supply no arguments, it opens a file in the users home directory. That of course makes sense. But when I run it from a different directory like this:
$ ./folder/hometest examplefile
The program creates "examplefile" in my current directory instead of the directory where the program is.
Why exactly is this happening?
Why exactly is this happening?
The program is behaving just as expected.
The file is opened relative to the current work directory, not where the executable is located.
If it didn't work that way,
All your programs will have to work with absolute paths, or
The location of the program will be flooded with files. First, that might not be possible because of permissions issue. Second, in a multi-user system, users will end up trying to create the same file names/directories.
Neither of the above is desirable.

no such file or directory, killed in fstream c++

I am new to C++.
I was trying to read a file using fstream.
here is the code,
I put the file inside the a.out directory but still cannot read it, where is my mistake?
#include<iostream>
#include<fstream>
int main()
{
std::ifstream myfile("my.txt");
int a, b;
while(myfile>>a>>b)
std::cout<<a<<b;
return 0;
}
Try:
#include <iostream>
#include <fstream>
#include <unistd.h>
int main()
{
char* name = get_current_dir_name();
std::cout << "Current Working Dir: " << name << "\n";
free(name);
std::ifstream myfile("my.txt");
if (!myfile))
{
std::cout << "Failed to open file\n";
exit(1);
}
int a, b;
while(myfile>>a>>b)
{
std::cout<<a<<b;
}
return 0;
}
Make sure that the file is located in the current directory of the .exe. This is usually the same directory as where the .exe is located on your harddrive.
If you don't know what the current directory is, I recommended you use the full path.

C++ Trouble Reading a Text File

I'm trying to read a text file but nothing is coming out. I feel like maybe It's not linking correctly in my Visual Studio Resources folder but if I double click it - it opens fine in visual studio and it doesn't run into any problems if I test to see if it opens or if it is good. The program compiles fine right now but there's not output. Nothing prints to my command prompt. Any suggestions?
Code
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
char str[100];
ifstream test;
test.open("test.txt");
while(test.getline(str, 100, '#'))
{
cout << str << endl;
}
test.close();
return 0;
}
Text File
This is a test Textfile#Read more lines here#and here
You try to open file by name without path, this means the file shall be in current working directory of your program.
The problem is with current directory when you run your program from VS IDE. VS by default sets current working directory for runnning program to project directory $(ProjectDir). But your test file resides in resources directory. So open() function could not find it and getline() immediately fails.
Solution is simple - copy your test file to project directory. Or copy it to target directory (where your program .exe file is created, typically $(ProjectDir)\Debug or $(ProjectDir)\Release) and change working directory setting in VS IDE: Project->Properties->Debugging->Working Directory, set to $(TargetDir). In this case it will work both from IDE and command line/Windows Explorer.
Another possible solution - set correct path to file in your open() call. For testing/education purposes you could hardcode it, but actually this is not good style of software development.
Not sure if this will help but I wanted to simply open a text file for output and then read it back in. Visual Studio (2012) seems to make this difficult. My solution is demonstrated below:
#include <iostream>
#include <fstream>
using namespace std;
string getFilePath(const string& fileName) {
string path = __FILE__; //gets source code path, include file name
path = path.substr(0, 1 + path.find_last_of('\\')); //removes file name
path += fileName; //adds input file to path
path = "\\" + path;
return path;
}
void writeFile(const string& path) {
ofstream os{ path };
if (!os) cout << "file create error" << endl;
for (int i = 0; i < 15; ++i) {
os << i << endl;
}
os.close();
}
void readFile(const string& path) {
ifstream is{ path };
if (!is) cout << "file open error" << endl;
int val = -1;
while (is >> val) {
cout << val << endl;
}
is.close();
}
int main(int argc, char* argv[]) {
string path = getFilePath("file.txt");
cout << "Writing file..." << endl;
writeFile(path);
cout << "Reading file..." << endl;
readFile(path);
return 0;
}