How do you do the following operations in C++?
Opening Files
Closing Files
Reading Files
Writing Files
Reading
#include <fstream>
int main()
{
std::ifstream inputFile("MyFileName") // Opens a File.
int x;
inputFile >> x; // Reads an integer from a file.
std::string word;
inputFile >> word; // Reads a space separated word from a file.
double y;
inputFile >> y; // Reads a floating point number from the file.
// etc..
} // File AutoMagically closed by going out of scope.
Writing
#include <fstream>
int main()
{
std::ofstream inputFile("MyFileName") // Opens a File.
int x = 5;
inputFile << x << " "; // Writes an integer to a file then a space.
inputFile << 5 << " "; // Same Again.
std::string word("This is a line");
inputFile << word << "\n"; // Writes a string to a file followed by a newline
// Notice the difference between reading and
// writing a string.
inputFile << "Write a string constant to a file\n";
double y = 15.4;
inputFile << y << ":"; // Writes a floating point number
// to the file followed by ":".
// etc..
} // File AutoMagically closed by going out of scope.
All at once
{
std::ifstream in("foo.txt"); /* opens for reading */
std::ofstream out("bar.txt"); /* opens for writing */
out << in.rdbuf(); /* streams in into out. writing and reading */
} /* closes automatically */
http://www.cplusplus.com/doc/tutorial/files.html
I personally still use the C style fopen, fread, fwrite, etc, but that is more of preference than actually "correct".
With C++ you've got lots of choices for how to interact with files, especially if you are using one of the many frameworks around, like Qt, wxWidgets, or GLib. To summarize, the standard C++ library uses a streams based model of file access, via std::ifstream and std::ofstream. This is similar to what you see when using std::cout and is what #Martin's post exemplifies. You also have available the standard C library functions for reading and writing files, namely open(), close(), read() and write(). The f*() variants take a FILE pointer rather than a file descriptor. The C variants are more useful when you want to treat a file as a raw stream of bytes, which unfortunately happens more often than it should. While both of these are "portable", constructing paths and handling directories/special files usually isn't, which is why you get things like boost::filesystem.
Related
i am new to this site , and this my first question !
i have a question about fstream function .
fstream f("new.dat",ios::out|ios::in);
fstream is for both input and output , so when we use it like this , and there is a new.dat file before it will output and input both . but it is strange , when i do that , it will output data correctly , but it is unable to input .
i found out if you close it , and reopen it , it will input . why it is like that??
int main()
{
fstream writeFile("newFile.dat", ios::out|ios::in);
char i[3];
char u[3]="HI";
if (!writeFile)
{
cerr << "error" << endl;
}
writeFile << u <<endl;
writeFile >> i;
cout << i << endl;
}
this is my full code , and result is an empty line.
The fstream object has a position in its output file, and since you opened it just for output and input without any position or writing modifiers, that position is at the end of the file. When you output i to the file, writeFile writes i to the file, and then moves its position past i so when you ask it to write more, you don't overwrite i.
You can reset the position to the start of the file with a call to writeFile.seekg(0), which places that internal position at the 0 position in the file (at the start).
If you're curious about stream manipulation, I'd suggest a look at cppreference.com and specifically its documentation on c++'s input and output libraries here.
Couple things going on here:
You can't open a file for reading if it doesn't exist, this includes a file you want to read and write. No file, no open.
Once you manage to open a file, the stream keeps track of where it is in the file. As you read or write, obviously the location moves.
There is only one location marker in the stream, so you can read to where you want to write, then write. Unfortunately this means any further reading will pick up after the write. If that's not what you want, get and store the current location (with tellg) before writing, and seek (with seekg) to the stored location after writing.
This has some problems such as what if the block of data you wish to insert is longer or shorter than the block of data you want to overwrite? The simple solution to this problem is read into buffer, edit buffer, write buffer back to file.
When you open a file and start writing into it, you overwrite whatever was in the file. If you want to add to a file, open with ios::app. This sets the stream's location to the end of the file. I am unaware of any sort of insert that pushes existing data along as you write in new data.
Some simple file handling example code
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
fstream f1("filename", ios::out);
if (f1.is_open())
{
if (f1 << "Hi")
{
cout << "wrote"<<endl;
}
f1.close();
}
fstream f2("filename", ios::out|ios::app);
if (f2.is_open())
{
if (f2 << " there!")
{
cout << "appended"<<endl;
}
f2.close();
}
fstream f3("filename", ios::in);
if (f3.is_open())
{
cout << f3.rdbuf()<< endl;
f3.close();
}
fstream f4("filename", ios::in|ios::out);
if (f4.is_open())
{
f4.seekg(3);
if (f4 << "Fred!")
{
cout << "overwrote"<<endl;
}
f4.close();
}
fstream f5("filename", ios::in);
if (f5.is_open())
{
cout << f5.rdbuf()<< endl;
f5.close();
}
// note the extra ! on the end left over from Hi there! I do not know how
// to get rid of this. I have always just done stuff like this to get around it.
fstream f6("filename", ios::in);
stringstream s1;
string token;
f6 >> token;
s1 << token << " Tim!";
f6.close();
fstream f7("filename", ios::out);
f7 << s1.rdbuf();
f7.close();
// and then moved temp over filename.
fstream f8("filename", ios::in);
cout << f8.rdbuf()<< endl;
f8.close();
}
I want to access specific lines in of text file to display or modify that one. My text file contains lines of different lengths and i heard cannot use seekg or seekp for such files. I got a code but it doesn't works. Can someone please tell me its fault of some other helpful idea?
#include <fstream>
#include <limits>
#include <string>
#include <iostream>
std::fstream& GotoLine(std::fstream& file, unsigned int num)
{
file.seekg(std::ios::beg);
for(unsigned int i=0; i < num - 1; ++i)
{
file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
return file;
}
int main()
{
using namespace std;
std::fstream& GotoLine(std::fstream& file, unsigned int num);
cout << "Starting..." << endl;
fstream file("bla.txt");
GotoLine(file, 8);
string line8;
file >> line8;
cout << "[" << line8 << "]" << endl;
// cin.get();
cout << "Finished..." << endl;
return 0;
}
string line8;
file >> line8;
will only extract until the first whitespace character is hit.
you could use something like:
string line8;
getline(file, line8);
This at least worked for me with the rest of your code on Windows 7 with VS2012
Standard C++11 (and earlier versions of the standard) dont have notion of lines contained inside files. Also POSIX (and even Windows or MacOSX) don't have it. Textual files usually contain lines of variable length (and only the line terminator is relevant, either \n or \r\n or \n\r, depending upon the operating system and perhaps the file read mode -binary or textual-).
In the 1960s or 1970s IBM mainframe OS/360 operating systems had "file" systems which did have files made of fixed-length lines, mimicking punched cards.
So, you have to read your file line by line and remember where are the line limits (or use std::istream::ignore to skip till \n).
Alternatively, read every line of your file into a std::vector<std::string> using std::getline on std::ifstream-s.
For /etc/fstab (or /proc/mounts) reading all the lines in a vector is a good idea, since it is always a tiny file. It usually have less than an few dozens of lines, often less than about a hundred char each. The pathological case could be a file with many thousand lines of comments, but that don't really happen in practice.
I'm making a C++ program to be able to open a .bmp image and then being able to put it in a 2D array. Right now i have the code like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "Image.h"
using namespace std;
struct colour{
int red;
int green;
int blue;
};
Image::Image(string location){
fstream stream;
string tempStr;
stringstream strstr;
stream.open(location);
string completeStr;
while(!stream.eof()){
getline(stream, tempStr);
completeStr.append(tempStr);
}
cout << endl << completeStr;
Image::length = completeStr[0x13]*256 + completeStr[0x12];
Image::width = completeStr[0x17]*256 + completeStr[0x16];
cout << Image::length;
cout << Image::width;
cout << completeStr.length();
int hexInt;
int x = 0x36;
while(x < completeStr.length()){
strstr << noskipws << completeStr[x];
cout << x << ": ";
hexInt = strstr.get();
cout << hex << hexInt << " ";
if((x + 1)%3 == 0){
cout << endl;
}
x++;
}
}
Now if i run this on my test file of 256x256 it will print fine, until it reaches 0x36E where it gives an error / doesn't go further. This happens because the completeStr string doesn't recieve all the data that is in the bmp file. Why isn't able to read all the lines in the bmp file?
There are a number of problems with your code. The principal
one (and probably the reason for your problem) is that you are
opening the file in text mode. Technically, this means that if
the file contains anything but printable characters and a few
specific control characters (like '\t'), you have undefined
behavior. In practice, under Windows, this means that sequences
of 0x0D, 0x0A will be converted into a single '\n', and that
a 0x1A will be interpreted as the end of the file. Not really
what one wants when reading binary data. You should open the
stream in binary mode (std::ios_base::binary).
Not a serious error, but you shouldn't really use an fstream
if you are only going to read the file. In fact, using an
fstream should be very rare: you should use either ifstream
or ofstream. The same thing holds for stringstream (but
I don't see any role for stringstream when reading a binary
file).
Also (and this is a real error), you are using the results of
getline without checking whether is succeeded. The usual
idiom for reading lines would be:
while ( std::getline( source, ling ) ) ...
But like stringstream, you don't want to use getline on
a binary stream; it will remove all of the '\n' (which have
already been mapped from CRLF).
If you want all of the data in memory, the simplest solution is
something like:
std::ifstream source( location.c_str(), std::ios_base::binary );
if ( !source.is_open() ) {
// error handling...
}
std::vector<char> image( (std::istreambuf_iterator<char>( source ) ),
(std::istreambuf_iterator<char>()) );
std::getline reads in a line of text.
It's not useful for a binary file.
Open the file in binary mode and use unformatted input operations (like read).
I was writing a program which could read inputs directly from a text
file into a C++ file. However, the contents of the file come in
different formats, for example time. The input file looks like this:
Time(1) Price(1)
8:56:18 1250.00
9:00:25 1250.25
9:21:36 1250.50
9:23:32 1249.75
Time(2)
8:55:28
9:02:14
9:20:23
9:21:37
Price(2)
1680.50
1681.00
1680.50
1681.50
My program to read the file is as follows:
int main()
{
string file;
cout << "Enter a file name to read input: ";
cin >> file;
ifstream file_name(file.c_str());
while(!file_name.eof())
{
double input;
file_name >> input;
cout << input << endl;
}
}
But when I executed the program, I get stuck in an infinite loop and
all I see are 0s written on the screen. Is this being caused due the
formatting of the time?
The default behavior of file_name >> input is type safe therefore file_name byte offset pointer never increments for inputs like Time(1) or 8:56:18. You may use string input; instead of double input; to retrieve the values, then later you may check their types by using following standard c library.
#include <cstdlib>
.
.
.
atof()
atoi()
.
Here is the documentation.
I'm working on some legacy code that uses win32 WriteFile() to write to a random location in a binary file. The offset of the write can be past the end of the file in which case WriteFile() seems to automatically extend the file size to the offset and then write the data to the file.
I'd like to use std::fstream to do the same, but when I try to seekp() to the appropriate location, past the end of the file, the seekp() fails and the subsequent write() fails as well.
So it seems to me that I have to 'manually' fill in the space between the current EOF and the location I want to write to.
The code looks like this:
void Save(size_t offset, const Element& element)
{
m_File.seekp(offset, std::ios_base::beg);
m_File.write(reinterpret_cast<const char*>(&element), sizeof(Element));
if (m_File.fail()) {
// ... error handling
}
}
So is my only option to 'manually' write 0s from the current EOF up to offset?
Here is an example I picked up verbatim from MSDN:
// basic_ostream_seekp.cpp
// compile with: /EHsc
#include <fstream>
#include <iostream>
int main()
{
using namespace std;
ofstream x("basic_ostream_seekp.txt");
streamoff i = x.tellp();
cout << i << endl;
x << "testing";
i = x.tellp();
cout << i << endl;
x.seekp(2); // Put char in third char position in file
x << " ";
x.seekp(2, ios::end); // Put char two after end of file
x << "z";
}
The file "basic_ostream_seekp.txt" has te ting\0\0z at the end of the program, i.e., you are allowed to seek past the end of the file.
In any case, if write does fail for you, you could check and see if seekp does too. If it does, you can detect the failure earlier.