Reputation: 19
I have a problem and I dont know how to solve it. The issue is:
char * ary = new Char[];
ifstream fle;
fle.open(1.txt, ios_base::binary);
fle.seekg(fle.end);
long count = fle.tellg();
fle.seek(fle.beg);
here is the problem: File 1.txt contains: Hello world!.
when I execute:
ary = new char(count);
fle.read(ary, count);
the ary filled like this: Hello world! @T#^@$@FF(garbage)
The file is ookay nothing inside it only what is above.
Platform: Win 7, VS 2012
Any idea how to solve this issue. (Solved)
(Problem 2) Now I am facing another problem, the fle.read sometimes read more than the size i gave. For Example if i passed like fle.read(buffer, 1000) it ends in some cases (strlen(buffer) = 1500. How can i solve this?
Regards,
Upvotes: 0
Views: 3724
Reputation: 1774
Try this
ary = new char[count + 1];
fle.read(ary,count);
ary[count] = '\0';
The terminating null character was missing - its not in the file, you have to add it afterwards
Upvotes: 0
Reputation: 18821
I think your problem is not that your array contains garbage, but that you forgot to put the null-terminator character at the end and your print statement doesn't know when to stop.
Also, you wrote new char(count)
instead of new char[count]
. In the first case, you only instantiate one char
with value count
while in the second case you create a buffer of count
characters.
Try this:
ary = new char[count+1];
fle.read(ary, count);
ary[count] = '\0';
Upvotes: 3
Reputation: 153899
Well, the most obvious problem is that you are allocating using
new char(count)
, which allocates a single char
, initialized
with count
. What you were probably trying to do would be new
char[count]
. What you really need is:
std::vector<char> arr( count );
fle.read( &arr[0], count );
Or maybe count + 1
in the allocation, if you want a trailing
'\0'
in the buffer.
EDIT:
Since you're still having problems: fle.read
will never read
more than requested. What does fle.gcount()
return after the
read?
If you do:
std::vector<char> arr( count );
fle.read( &arr[0], count );
arr.resize( fle.gcount() );
you should have a vector with exactly the number of char
that
you have read. If you want them as a string, you can construct
one from arr.begin(), arr.end()
, or even use std::string
instead of std::vector<char>
to begin with.
If you need a '\0'
terminated string (for interface with
legacy software), then just create your vector with a size of
count + 1
, instead of count
, and &arr[0]
will be your
'\0'
string.
Do not try to use new char[count]
here. It's very difficult
to do so correctly. (For example, it will require a try block
and a catch.)
Upvotes: 2
Reputation: 585
Most of the other answers miss a very important point:
When you do ary = new char(count);
you allocate A SINGLE CHARACTER initialized with a symbol with ASCII code count
.
You should write this: ary = new char[count + 1];
Upvotes: 2
Reputation: 2965
You're reading count
characters for a file, you have to allocate one extra character to provide for the string terminator (\0
).
ary = new char[count + 1];
ary[count] = '\0';
Upvotes: 0
Reputation: 69663
char[]-strings in C are usually null-terminated. They are one byte longer than necessary, and the last byte is set to 0x00
. That's necessary because C has no way to tell the length of an array.
When you read binary data from a file, no terminating null-character is read into the string. That means a function like printf which operates on char-arrays of unknown length will output the array and any data which happens to come after it in memory until it encounters a null-character.
Solution: allocate the char[]-buffer one byte longer than the length of the data and set the last byte to 0
manually.
Better solution: Don't use C-style char-arrays. Do it the object-oriented way and use the class std::string to represent strings.
Upvotes: 5
Reputation: 612794
We have to guess a little here, but most likely this comes down to an issue with your debugging. The buffer is filled correctly, but you inspect its contents incorrectly.
Now, ary
is declared as char*
and I suspect that when you attempt to inspect the contents of ary
you use some printing method that expects a null-terminated array. But you did not null-terminate the array. And so you have a buffer overrun.
If you had only printed count
characters, then you would not have overrun. Nor would you if you had null-terminated the array, not forgetting to allocate an extra character for the null terminator.
Instead of using raw arrays and new
, it would make much more sense to read the buffer into std::string
. You should be trying to avoid null-terminated strings as much as possible. You use those when performing interop with non-C++ libraries.
Upvotes: 1