I have written a program which opens a file then displays line by line its contents (text file)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main (int argc, char* argv[])
{
string STRING;
ifstream infile;
infile.open(argv[1]);
if (argc != 2)
{
cout << "ERROR.\n";
return 1;
}
if(infile.fail())
{
cout << "ERROR.\n";
return 1;
}
else
{
while(!infile.eof())
{
getline(infile,STRING);
cout<<STRING + "\n";
}
infile.close();
return 0;
}
}
What do I need to add to make the file be read only ?
(infile.open(argv[1]) is where am guessing something goes)
The class ifstream is for reading only so, problem solved. Also, did you really mean to check argc after using argv[1] ?
On the other hand, when you use fstream you need to specify how you want to open the file:
fstream f;
f.open("file", fstream::in | fstream::out); /* Read-write. */
The default mode parameter of open for ifstream class is ios::in. That is
infile.open(argv[1]);
is same as:
infile.open(argv[1], ios::in);
So you are opening the file in read-only mode.
You already open the file for read-only. Your can't write to it if you use ifstream. Even:
infile.rdbuf()->sputc('a');
is guaranteed to fail.
You don't need to do anything as the default value for the openmode is already ios_base::in. So you're already good to go :)
See here for more details: http://en.cppreference.com/w/cpp/io/basic_ifstream/open
Related
I would like to access a file through fstream with the following requirements:
If the files does not exists, it create it
The file can be read (from pos 0)
The file can be (over)written (from pos 0)
Without closing and re-opening the file
ios_base::in seems to disable file creation
ios_base::out seems to disable file reading
Is this possible? How?
#include <iostream>
#include <sstream>
#include <fstream>
#include <cassert>
using namespace std;
int main()
{
auto mode = ios_base::in|ios_base::out;
std::string filePath = "./test.txt";
std::string content1 = "Any content 1";
std::string content2 = "Any content 2";
{
std::remove(filePath.c_str());
}
{// Test creation
// make sure test.txt is missing / does not exists
fstream file(filePath, mode);
assert(file.is_open() && file.good());
file << content1;
}
{ // Test reading & writing
fstream file(filePath, mode);
// read
file.seekg(0);
std::stringstream buffer1;
buffer1 << file.rdbuf();
cout << buffer1.str() << endl;
assert(buffer1.str()==content1);
// write
file.seekp(0);
file << content2;
assert(file.is_open() && file.good());
// read
file.seekg(0);
std::stringstream buffer2;
buffer2 << file.rdbuf();
cout << buffer2.str() << endl;
assert(buffer2.str()==content2);
}
return 0;
}
Run it
Only with fstream I'd say no.
You might want to have something similar with the trunc mode but you'll lose everything if the file exists (which might be a problem, if not go for trunc + out)
The other way is to check if the file exists, if not you create it (whichever way). Then you open with In and Out and do your stuff.
It kind of doesn't make sense to be able to read inside an empty file you just created from the cpp point of view
I just started working with binary files in C++, and i have successfully written and read a (.bin) file. Here is the code:
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
int main()
{
char input[100];
strcpy(input, "This is a string");
fstream file("example.bin", ios::binary | ios::in | ios::out |
ios::trunc);
if(!file.is_open())
{
cerr << "Error opening file.\n";
} else {
for(int i = 0; i<= strlen(input); i++)
{
file.put(input[i]);
}
}
file.seekg(0);
char ch;
while(file.good())
{
file.get(ch);
cout<<ch;
}
}
And this worked. After that, i tried to redesign the code to just read a binary file. The major changes were: changed fstream to be an ifstream(to read), deleted the part with writing into a file. Once the code was ready, i found a file i want to read (eof0.bin). When i used the code, the only thing i got was an empty string. I noticed that the initial size of the file was 37 kilobytes, while after using my program it became 0. I want to know, how my program cleared the data in the binary file?
This is the code that i used to read the file.
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
int main()
{
ifstream file("eof0.bin", ios::binary | ios::in | ios::out | ios::trunc);
if(!file.is_open())
{
cerr << "Error opening file.\n";
} else {
// Nothing.
}
file.seekg(0);
char ch;
while(file.good())
{
file.get(ch);
cout<<ch;
}
}
Everything compiles, but using it on a file 37 kilobytes in size gives me a 0 kilobyte file.
You open with an openmode std::ios_base::trunc. From http://en.cppreference.com/w/cpp/io/ios_base/openmode we can see that it
discard[s] the contents of the stream when opening
So just use:
// also dropped ios::out since you only want to read, not write
ifstream file("eof0.bin", ios::binary | ios::in);
Further, this
char ch;
while(file.good())
{
file.get(ch);
cout<<ch;
}
is not an appropriate way to read the file. Think about what happens with an empty file: After opening it, it's "good" (remember, the eofbit is only set when some input operation encounters eof). Then the get fails, leaving ch as it is, thus invoking undefined behavior. Better test on the stream state directly after the input operation:
char ch;
while (file.get(ch)) {
// use ch
}
// optionally distinguish eof and fail cases
For more background on reading files, see Why is iostream::eof inside a loop condition considered wrong?
I'am having a rather difficult time with this program (see code below). It is supposed to :
Create an array of 26 components to do the letter count for the 26 letters in the alphabet and a variable for the line count.
Create an ASCII (or text) file that contains text and will be used as input to my program.
Call that file "textinput" and then, have the output stored in a file called "textoutput".
Can anyone tell me what I'am doing wrong? I keep getting "File not found" errors.
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <cstdlib>
#include <fstream>
using namespace std;
int main()
{
int lineCount = 0;
int letterCount[26];
for(int i = 0; i < 26; i++)
letterCount[i] = 0;
ifstream infile;
infile.open("textinput.txt", ios::in);
if(!infile)
{
cerr<<"File does not exist."<<endl;
exit(1);
}
ofstream outfile;
outfile.open("textoutput.txt", ios::out|ios::binary);
if(!outfile)
{
cerr<<"File cannot be opened."<<endl;
exit(1);
}
char data[100];
outfile<<data;
while(infile>>data)
{
outfile<<data<<endl;
}
while(infile)
{
char ch1 = infile.get();
if(ch1 == '\n')
{
lineCount++;
continue;
}
int asciiNum = (int)ch1;
if(asciiNum > 96)
{
asciiNum = asciiNum - 97;
}
else
{
asciiNum = asciiNum - 65;
}
letterCount[asciiNum]++;
}
infile.close();
outfile.close();
system("PAUSE");
return 0;
}
The funny thing is, "File not found" errors are not possible with your program.1 So, I'm going out on a limb and suggest that you need to qualify the path to your executable!
Say, you compiled with something like
gcc program1.cpp -o program1
To execute, you must use
./program1
Because program1 won't work. The reason is that with 99% certainty, your current working directory is not in the search PATH for executables (and you want to keep it that way).
Beyond this, yes, do make sure that the textinput.txt exists in the same directory.
1(There's no such error message in the program. You should know: you programmed it!)
ifstream class is used to read from files and to read from files you must need to create it first which you haven't done, so first create the file .
By doing like this :
ifstream infile;
infile.open("textinput.txt", ios::in);
you are trying to read from a file which has not been created yet OR may be as described in other answer or the comments that your file doesn't exist in the same directory.
You better use ofstream to first write on the file and then use ifstream.
Does your code work if you have the file? If it does try removing the ios::out.If i'm not mistaken ios::out is used when you do not want to truncate your old content in the file,but that implies you already have it.
When I debug this I can see it opens datafile1 , it reads the firstline and
in the logfile I get roma-3-4.log
It change to c:/temp/roma-3-4.log but when I want to open it , it fails. I have check that the _Mystate = 2 .
What is the meaning of that
Thanks
in the transfersubs.cfg there is this
roma-3-4.log
** In the directory c:/temp/ I have the following file
roma-3-4.log
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string input;
string logfile;
string errorfile;
short logfilesize1;
fstream dataFile1("c:/temp/transfersubs.cfg", ios::in);
if (dataFile1)
{
getline(dataFile1, input, '$');
logfile=input;
logfilesize1=input.size();
errorfile=input;
errorfile[logfilesize1-4]='e';
errorfile[logfilesize1-3]='r';
errorfile[logfilesize1-2]='r';
logfile="C:/Temp/"+logfile;
fstream dataFile2( logfile, ios::in);
if (dataFile2)
{
dataFile2.close();
}
else
{
cout << "ERROR: Cannot open logfile.\n";
}
dataFile1.close();
}
else
{
cout << "ERROR: Cannot open file.\n";
}
system("Pause");
return 0;
}
I believe your getline doesn't bother looking the newline but only for a $. You didn't post the file you are reading from, but check to ensure it has a $ at the end of the file name otherwise it will fetch the entire file.
It appears that unless you put a \n or endl after writing to the file using ofstream, ifstream won't be able to read anything from the file. In fact, adding a space after whatever you've written into file won't help either.
So always add a newline right after whatever it is that you've written to file using ofstream.
I'm trying to open a binary file for writing without erasing the content. But I do not want to write to eof. I want to write to a specific position in file.
Here is a litte example:
ofstream out("test.txt", ios::binary | ios::app);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
out.close();
ofstream out2("test.txt", ios::binary | ios::app);
out2.seekp(10);
out2.write("Welt", 4);
out2.close();
If using app, seek doesn't work. If not using app opening file erases data. Does anybody know an answer?
try the second overload of seekp, which allows you to provide an offset and a direction, this could be begining of file in your case (i.e. ios_base::beg). This of course assumes you know what you are doing and all you want to do is overwrite an existing number of characters.
EDIT: here is fully working example:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
{
ofstream out("test.txt", ios::binary);
for(int i = 0; i < 100; i++)
out.put('_');
out.write("Hallo", 5);
}
{
fstream out2("test.txt", ios::binary | ios::out | ios::in);
out2.seekp(10, ios::beg);
out2.write("Welt", 4);
}
}
When opening with ios::app, it is as if you open a new file that just happened to be attached to an existing file: you can not access the existing file. I'm not sure, because I would do as in Kerrek's answer, but if you really want to try, you probably have to open with "ios::in | ios::out", similar to fopen("test.txt", "rw").
Or as crashmstr points out: ios::out might be enough.
You cannot magically extend the file from the middle. Perhaps easiest to write to a new file: First copy the initial segment, then write your new data, then copy the remaining segment. When all is done, you can overwrite the original file.
According to the specification of fstream here
fstream::open
the ios::app "Sets the stream's position indicator to the end of the stream before EACH output operation." So ios::app doesn't work for replacing, seeks of any sort fail, at least for me.
Just using ios::out does wipe out the file contents preserving only the size, basically turning the file into trash.
ios::in|ios::out turned out as the only working thing for me.
Working Code: This code searches for a string (OLD-STRING) in cout.exe and replaces with a new string (NEW-STRING).
`#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
fstream ifs;
ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out);
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
size_t pos = str.find("OLD-STRING");
if (pos != string::npos)
{
cout << "string found at position: " << int(pos) << endl;
ifs.seekp(pos);
ifs.write("NEW-STRING", 10);
}
else
{
cout << "could not find string" << endl;
}
if (ifs.is_open())
ifs.close();
return 0;
}`