C++ what's happening with my ifstream.get() function? - c++

I'm trying to read in a picture file.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream read("C://Users/Ben/Desktop/1.jpg");
while (1){
cout << read.get();
cin.get();
}
return 0;
}
When I do this, I get a series of numbers ranging from 0 ~ 255. So I'm assuming it's reading in the byte values correctly, except for the fact that I hit -1 (eof) prematurely. After about 30 to 40 values, the -1 appears. It's a 3MB file. I don't expect the -1 to appear until way later. What's going on?

As #melpomene mentioned in their comment there may be a difference for the results of std::ifstream::get() regarding the file was opened using the std::ios::binary mode or not (at least for the Windows OS it seems).
There's no evidence that a value of -1 as result of std::ifstream::get() indicates that the read stream is in std::ifstream::eof() state. You may read up in the std::ifstream::get() reference documentation, for more information.

Try this:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
// Add the mode ios::binary to make the file load in binary format.
ifstream read("C://Users/Ben/Desktop/1.jpg", ios::binary);
// Declare data variable
int data = 0;
// Reading loop
while (read.read((char*)&data, 4) && read.gcount() != 0) {
// Output data
cout << data << endl;
}
// Wait for user input before closing program
cin.get();
return 0;
}

Related

I am trying to take the contents of fa plain txt file and put it into a char array, then I would like to print it out of the array

#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
int arraySize = 100;
char file[arraySize];
fstream myfile;
//open file
myfile.open("SamplePlainText.txt", ios::binary);
myfile.read(file, sizeof(file));
myfile.write(file, sizeof(file));
for(int i=0; i< arraySize; i++) {
cout << file[i] << endl;
}
}
I am trying to copy the contents of a plain txt file that says "This is a test." into a char array so I can read the information back out of the array using a for loop. Whenever I compile/run the program I am getting a bunch of random numbers and can't figure out where my error is. Any suggestions? (Its only my second semester programming so forgive me if this is not good. This is exactly what I ran on xcode )
Problems:
The file was not opened for reading or writing and cannot be read or written.
The read was not tested for success before actions were taken on the data read.
The entire buffer was printed regardless of how much, or little, data was read. Writing more data than was read results in printing whatever already existed in the buffer. This often looks like garbage.
Modified and annotated code:
//#include <stdio.h> not required
#include <fstream>
//#include <string> not required
#include <iostream>
//#include <cstdlib> not required
using namespace std;
int main() {
const int arraySize = 100; // must use constant values to size arrays
char file[arraySize];
ifstream myfile; // file opened for input.
// currently cannot write to file. reading from and writing to the same file
// stream is exceptionally hard to get right. For now don't even try.
// If you must read and write the same file:
// Read the file into buffer
// Modify data in buffer
// Close the stream.
// Open the file for writing.
// Write the buffer to the file.
// Close the stream.
// In this case writing exactly what was read back to the file is pointless,
// so I left it out.
//open file
myfile.open("SamplePlainText.txt",
ios::binary); // ifstream implies opened for reading
if (myfile.read(file, sizeof(file)))
{ // printing the data read is only meaningful if data was read
for(int i=0;
i< myfile.gcount(); // only print up to number of bytes read
i++) {
cout << file[i] << endl;
}
}
else
{
cout << "File was not read" << endl;
}
// myfile.write(file, sizeof(file));
// left out for now
}

File Handling and if else

I am trying to make a program for my University project and I needed some help.
I am trying to make a program which creates a file using ofstream and stores 1 or 0 in it (I've already found a way to store 0 or 1 in the file using random) and tells if the file contains 0 or 1 using if-else statements.
I'm having issue in reading the file, I can't find a way to make my program read that created file and tell whether it had 1 or 0 in it.
Here's my code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main () {
int randu;
srand((int) time(0));
ofstream room;
room.open("room0");
room << rand() % 2;
room.close();
if (room.open("room0") == 1 ) {
cout << "the room is occupied";
}
else {
cout << "the room is free";
}
room.close();
return 0;
}
I'm having issue in reading the file ?
You are not reading anything in the code you shown.
Once the file is open and you want to check whether it's 0 or 1, for that first you need to read from file and if you want to read something, then room should be object of ifstream class, not ofstream class.
You can use getline() or get() or read() for reading purpose.
For example: char ch = room.get();
Whether the file is open or not you can check using fail():
if(room.fail()) {
cout << "the room is occupied";
}
else {
cout << "the room is free";
}

In C++ why is ifstream getline returning every other number in my .txt file, rather than all of them?

When I run this code it doesn't print the contents of the .txt file which is numbers 1 to 100, it prints all of the even numbers up to 100 (e.g. 2 4 6 8 so on.) And I don't know why, it didn't before and I don't think I changed anything. I'm using xcode. Anybody got any ideas?
#include <stdio.h>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
int main () {
string line;
int Points[100];
ifstream myfile("StatNum.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
getline(myfile,line);
stringstream(line) >> Points[100]; //uses stringstream to convert Myline (which is a string) into a number and put it into an index of Points
cout << Points[100] << endl;
}
myfile.close();
}
else cout << "Unable to open file" << endl;
return 0;
}
This happens because you call getline twice per iteration:
First, you call it in the while header
Then you call it inside the loop.
One invocation (the one in the while header) is sufficient, because the result is saved in the line variable, which the loop body is free to examine.
Removing the second invocation will fix the problem.
As #dasblinkenlight pointed out, you are calling std::getline() twice and that's the problem that you see.
The problem that you can't see is that you are writing data to Points[100] which is an invalid location, outside of the array's bounds. The 100 valid locations in your array are indexes 0 to 99, that is Points[0], Points[1], ..., Points[99] (because counting in C++ starts from 0, not 1).
Writing to Points[100] is Undefined Behavior which means that your program may crash, or worse: may not crash while corrupting its own data.
Since you're using C++ you have std::vector and other containers at your disposal, where you can easily store the numbers you read:
#include <vector>
// ...
vector<int> points;
while (getline(myfile, line))
{
int temp;
stringstream(line) >> temp;
points.push_back(temp);
cout << temp << endl;
}

ifstream tellg() not returning the correct position

read.cpp
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
int id;
char name[50];
ifstream myfile("savingaccount.txt"); //open the file
myfile >> id;
cout << myfile.tellg(); //return 16? but not 7 or 8
cout << id ;
return 0;
}
savingaccount.txt
1800567
Ho Rui Jang
21
Female
Malaysian
012-4998192
20 , Lorong 13 , Taman Patani Janam
Melaka
Sungai Dulong
The Problem
I expect the tellg() to either return 7 or 8 since the first line 1800567 which is 7 digits so the stream pointer should be placed after this number and before the string "Ho Rui Jang", but tellg() returns 16. Why is it so?
had the same issue. try to read the filestream binary:
ifstream myfile("savingaccount.txt",ios::binary);
it helped for me
This seems more like a compiler bug (probably gcc)
With the following Code:-
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
int id;
char name[50];
ifstream myfile("savingaccount.txt"); //open the file
cout << myfile.tellg()<<endl;
myfile >> id;
streamoff pos=myfile.tellg();
cout <<"pos= "<<pos<<'\n';
cout <<"id= " << id<<'\n' ;
return 0;
}
Following is the output:-
In the image inpstr.exe was generated from Visual studio's cl while inp.exe from g++(gcc version 4.6.1 (tdm-1))
It is not a compiler bug. tellg() is not guaranteed to return an offset from the start of the file. There are a minimal set of guarantees such as, if the return value from tellg() is passed to seekg(), the file pointer will position at the corresponding point in the file.
In practice, under unix, tellg() does return an offset from the start of the file. Under windows, it returns an offset from the beginning of the file but only if the file is opened in binary mode.
But the only real guarantee is that different values returned from tellg() will correspond to different positions in the file.

How can I convert a text file with numbers in it into a binary file?

So I have made a program that opens up a text file using ifstream. Now I want to make it so it outputs this file in binary. I have tried ofstream and using .write() but when I do the program crashes. I set it up correctly when using .write() as I have seen online but I haven't seen anyone do it with what I was working with. Anybody have a solution to this? Also, I do not know why 'InputFile' and 'OutputFile' are both highlighted blue like that.
#include <iostream>
#include <fstream>
#include <string>
#include <bitset>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Error 1";
return 0;
}
else
{
int WIDTH, HEIGHT;
ifstream InputFile;
InputFile.open(argv[1], ios::in);
ofstream OutputFile;
OutputFile.open("OUTPUT.raw", ios::binary | ios::app);
cout << "Enter Width" << endl;
WIDTH = cin.get();
HEIGHT = WIDTH;
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
}
}
}
//cout << bitset<8>(txt[i]);
return 0;
};
OutputFile.write((char*)InputFile.get(), sizeof(InputFile));
First, istream::get() extracts one characters from the stream and returns its value casted to an integer. The result is a temporary, which you cast to a pointer to char! It compiles, because the C-style cast basically tells the compiler "shoosh, I know what I'm doing!", but it will certainly do weird things at run-time. You need to get an adress of some object where the value you want to write is stored in, and cast that adress.
The second thing, sizeof(InputFile) returns size of ifstream class that manages the file stream. It's not in any way related to how many data is in the stream's buffer.
If you open a stream in text mode, then the correct way to extract data from it is to use extraction operator (>>). Then it's pretty simple:
std::ifstream in_file("numbers.txt");
std::ofstream out_file("numbers.bin", std::ios::binary);
int i;
while (in_file >> i)
out_file.write(reinterpret_cast<char*>(&i), sizeof(int));
The above snippet will work with an input text file like this: -4 21 1990 5425342 -3432 0 100.
You will have to parse your text file to get int for every string in file and just create a new file and write your binary data with fputc() or fwrite() functions.