Ifstream Read Useless Data - c++

I'm using C++ to read a file in chunks.
The file contains integers, two per line.
First of all, I'm using this to find the file's length :
input.seekg (0, input.end);
int length = input.tellg();
input.seekg (0, input.beg);
After that, i check if length is bigger than chunksize, and if this is true, I allocate memory for the chunk...
char * buffer = new char [chunksize];
Ok, so here goes the reading function...
while (true)
{
input.read (buffer,chunksize);
cout<<buffer;
if(input.eof()) break;
}
Immediately after that I delete [] buffer;
However, I'm facing a problem with this code. For example, when the input file is like that :
2 5
4 5
6 8
7 5
4 2
1 2
The program will not output the expected characters, but something like :
2 5
4 5
6 8
7 5
4 2
1 2 2
1 2
Do you know the reason for these extra characters? If the file's size is less than chunksize, I input.read using its length and it works just fine. Maybe if using read with a length larger than the size of the file makes it not work correctly?
Thanks a lot

Your string is not NULL-terminated. The read() function will not put a '\0' at the end of what it reads for you, so when you go to print it, you're printing essentially garbage data beyond the end of what you read, because the print code is expecting a NULL terminator to mark the end of the string.

Related

C++ Reading from file incorrectly

There is a certain problem that I would like to have help with. Here is how it goes:
I'm using the following code to read a certain amount of characters into a char array to process later:
char str[15]; // first 16 characters that i need to get from file
std::ifstream fin("example.txt");
if(fin.is_open()){
std::cout<<"File opened successfully \n";
for(int i = 0; i<=15; i++)
{
fin.get(str[i]); //reading one character from file to array
}
}
else{
std::cout<<"Failed to open file";
}
std::cout<<str;
It works fine for the first 4 or even 5 characters, but when it reaches to 8 it starts to print out garbage characters.
Contents of the example.txt file, from which i read text.
The Quick Brown Fox Jumped Over The Lazy Dog The Quick Brown Fox Jumped Over The Lazy Dog
Output when I read 8 characters:
The Quic�j�
Output when I read 16 characters:
The Quick Brown ASCII
Why is this happening and where did the 'ASCII' come from when I try to read certain length from a file?
And lastly, what kind of code should I utilize if I want to get specific lengths from a file? For example if I want to read the first 4 or 8 or 16 or even 20 characters? It doesn't necessarily have to be into a char array, it can be saved into a string.
Thank you in advance.
Your char array is only 15 chars long. So this line goes out of bounds:
for(int i = 0; i<=15; i++)
If i is equal to 15 that's one too many because your array counts from 0 to 14.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <= count them!
There are 15 places starting at 0 ending at 14
Also when strings are stored in memory they have to be terminated by a null character '\0'. Otherwise the function that prints them doesn't know when to stop, which is probably where your garbage is coming from.
So, because the null terminator takes one of your 15 spaces, that only leaves you with 14 to read from the file.
So:
for(int i = 0; i < 14; i++)
{
fin.get(str[i]); //reading 14 characters (0-13)
}
str[14] = '\0'; // add the string terminator at the end of the array.
See if that works.

Two 2D Arrays, Two Matrices, One File

I am trying to figure out how to read two matrices from one file and then assign them to two different 2D arrays. The matrices are separated by a new line in the text file. I managed to get the first one to read successfully but now I cant figure out how to read the second one. The way I see it, the the line that separates the two matrices must be considered and checked for. How do I get the program to read and assign the second matrix to an array?
Both matrices and arrays are 4x4.
This is what the text file looks like:
3 4 5 7
5 16 7 12
11 12 3 9
9 8 1 12
15 4 3 6
1 12 3 12
7 8 19 9
11 12 8 5
Here is my code for the first array which works fine.
for (int y = 0; y < 4; ++y )
{
for (int x = 0; x < 4; ++x )
{
infile >> array1[x][y];
}
}
And here is my code for the array I can't figure out.
for (int y = 0; y < 4; ++y )
{
for (int x = 0; x < 4; ++x )
{
if(x == '\n' && y == '\n') //My attempt.
{
infile >> array2[x][y];
}
}
}
Here is the output:
This will check to make sure numbers in file are written to the first array.
3 4 5 7
5 16 7 12
11 12 3 9
9 8 1 12
This will check to make sure numbers in file are written to the second array.
9.21742e-314 1.0572e-307 7.29112e-304 3.87184e-306
1.06498e-307 1.65425e-317 6.79039e-313 4.22748e+266
5.92879e-323 1.06196e-307 6.95089e-308 9.88799e-315
1.79648e-313 8.48798e-314 6.95224e-308 1.06193e-307
Press any key to continue . . .
Any help is appreciated!
When you are reading your file using the "formatted input" operator >>, the kind and amount whitespace (spaces, tabs, newlines) between the items (numbers in your case) is insignificant. This means you do not get to see the empty line at all. If you need to parse a file based on its lines, consider using getline instead and parsing the single lines using a istringstream.
If on the other hand you know the size of both arrays, you can simply read the second array just as you read the first array. The extra empty line just gets ignored.
The reason your code for reading the second array does not work is that you compare the index variables to '\n', which happens to be 10 on most systems. As your index ranges from 0 to 3, the if condition is never true, so nothing gets read at all, so you are seeing a dump of uninitialized memory.
You can read the second array exactly as you read the first. The reason is that, when you start reading from a stream, at first it discards whitespaces till it encounters something that is not whitespace. Then it gets the numbers/character one by one till it encounters whitespace again. So, there is no problem with the newline and you can read the remaining array without problems.

Issue reading a file

i am creating a program to read the .dxf file of autodesk.
i am encountering a problem while reading strings.
when i use :
string acad;
fstream f;
f.open(name);
f >> acad
if the string is "chamfer" it works perfect.
but if the string is "a & b" it is able to read only upto a.
since the file format follows a pattern i am using while loop.
example from a file:
9 //loop 1
$DWGCODEPAGE //loop 1
3 //looop 1
ANSI_1252 //looop 1
9 //loop 2
$LASTSAVEDBY //loop 2
1 //loop 2
sam & tom //loop 2
9 //loop 3
$INSBASE //loop 3
10 //loop 3
0.0 //loop 3
as you can see sometimes there may not be any space as in "ANSI_1252" & sometimes there may be spaces as in "sam & tom".
how can i generalise the code so that the whole string in a line is stored along with the spaces, if any.
please forget about the spaces in the beginning of each line, i am using ws for that.
thank you!
>> operator reads words delimited by space, when used with a string parameter. If you want to read lines of characters, you should use getline() instead.

sorting through a file/returning info

Just need general project help.
Basically I need to do this for 8 players. The numbers come from a file im supposed to call in. The first 5 numbers for for the first 5 games, the next for rebounds, and then for blocks. Im assuming I need to call in a loop to read the first name, last name, points, rebounds and blocks, process that info and then output the information.Any tips/ suggestions?
ex from the text file:
Thomas Robinson 17 28 10 16 10 11 12 13 8 9 1 1 1 0 1
ex from what I'm supposed to return that information to
Game Log
-----------------------------------------------------------------------------
Player Name : Thomas Robinson
-----------------------------------------------------------------------------
Game # Points Rebounds Blocks
-----------------------------------------------------------------------------
1 17 11 1
2 28 12 1
3 10 13 1
4 16 8 0
5 10 9 1
-----------------------------------------------------------------------------
I think this is homework, but since I don't know which functions can be used, and which functions can't, my answers may be can't fit the request.
At a first look, I got three ideas.
1) using ifstream::get()
ifstream in_file;
in_file.open("your_file_name.txt");
char ch;
string str = "";
while(in_file.get() != '\n')
{
str = "";
while((ch = in_file.get()) != ' ')
{
// add ch to str.
str += string(&ch, 1);
}
// push str into an array, vector, stack, etc.
/*...*/
}
in_file.close();
2) read the line into a string, and then use a split function, you can find how to implement a split function everywhere.
3) use the ifstream::getline() function, it provides a delemiter parameter.
you can find the usage of ifstream::get() and ifstream::getline() here and here
The code I provide in 1) is probably not a good practice, you should check the 'EOF' stream error, in_file.open()'s exceptions etc.
btw, the code I first wrote was an error code, you can't use str += string(ch), you should either write str += string(&ch, 1) or str += string(1, ch) or str += ch you can find string's constructors here. Sorry for the error code again.
You can parse the file with the ">>" operator pretty nicely if everything is separated by spaces and newlines. Which is how the ">>" operator works. So, yes, you need a loop. Basically you want the loop to work like this:
(I never knew you could do this in Comp Sci 1. It would've saved me so much trouble...I used to do things like what the other answer is doing.)
(I'm also assuming you know how to open a txt file as an ifstream. If not, see http://www.cplusplus.com/reference/iostream/ifstream/open/.)
int temp;
int n = 0;
int x = 1;
while(textfile >> temp) // Each time through the loop, this will make temp
// the next value in the file. It will stop when
// there's nothing more to read.
{
/* Now it's going to go from left to right through the file, so you
need some logic to put it in the right place. you know that every
five numbers start a new column, so:*/
array[x][n] = temp; //Start x at 1 because you're skipping the first column
n++;
if (n == 5) {
n = 0;
x++; //Every five values, move on to the next column
}
Now your array will have the stuff where it needs to be. Just output it according to plan.

problem in reading binary file (mix of ascii and binary)

My code for reading binary file is:
dataFile.open(fileName.c_str());
ifstream binData("Trafficlog_Data.txt", ios::in | ios::binary); //binary data file
if(!binData) {
cout << "Cannot open file.\n";
return -1;
}
char *memblock;int nBytes =12;
memblock = new char [nBytes+1];
binData.read(memblock,nBytes);
memblock[nBytes+1]='\0';
std::string message;message.assign(memblock,nBytes);
printf("%s\n",message.c_str());
Now i have given a file as input which contain binary and ascii data
RFB 003.003
RFB 003.003
--some binary data--
When I am reading first 12 bytes of file which is "RFB 003.003\n" but it prints "RFB 003.003=". Can anyone tell where i m getting it wrong please.
promblem is not with '\0'. problem is it is not reading "RFB 003.003\n" . IS it because this file is mix of binary and ascii data
You didn't allocate memory for memblock:
char *memblock = new char[nBytes+1];
Change:
memblock[nBytes+1]='\0';
to:
memblock[nBytes]='\0';
Let's say you read in six bytes to memblock, that goes into positions 0 through 5 inclusive:
0 1 2 3 4 5 6 7
+---+---+---+---+---+----+---+---+
| H | E | L | L | O | \n | ? | ? |
+---+---+---+---+---+----+---+---+
(the ? areas still contain whatever rubbish was there before).
You then need to put the null terminator at position 6 rather than position 7 as your code is doing.
By placing the null terminator too far to the "right", you're including that first ? position, which could be holding anything.
That's what's causing your specific problem. You also have an issue that you're not allocating space to hold the data you're reading in. You just have a char * but you're not actually initialising it to point to usable memory. That's almost certainly going to cause problems.
Probably the simplest solution is to define it as:
char memblock[nBytes+1];
Although I see you've fixed that in your question now so it's of little consequence. The actual problem (putting the null byte at the wrong location) is covered above.
You're off-by-one: just do memblock[nBytes]='\0'; The index starts at 0, so if nBytes is 0 you're writing at the first position, if nBytes is 1 you're writing at the second position and so on. By doing nBytes + 1 you actually jumped ahead one position and left one garbage byte at the end of the string.