0

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,

6
  • it isnt in the file, that is part of your allocated memory. try nulling the array before you do anything. ie ary = new char(count); memset(ary, 0, count); fle.read(ary,count);, for memset, you will also need #include <string.h> if you dont already have it. Commented Oct 8, 2013 at 12:19
  • 2
    Why are you opening the file in binary? Commented Oct 8, 2013 at 12:20
  • And count has an o in it. Commented Oct 8, 2013 at 12:20
  • @bizzehdee - memset requires <string.h> or <cstring> Commented Oct 8, 2013 at 12:22
  • new char(..) creates a single char not an array! and new char[] is pointless! (didn't even know it would compile). Commented Oct 8, 2013 at 14:37

7 Answers 7

5

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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'; 

6 Comments

Thanks That did what I want, for me instead of increasing the buffer I just made ary[count -1] = '\0' otherwise I will have to change the receiver buffer size, if am not wrong.
If you do ary[count-1] = '\0', you will lose the last byte.
Yea, but I changed the read size to -1 so I can keep that byte empty. 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(destination, 1000) it ends in some cases 1500. How can i solve this?
@JamesKanze Is it better now?
Yes, but... why use new char[], when std::vector<char> is so much better. (Consider what happens if fle.read throws an exception.)
|
2

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];

3 Comments

Two nits (because you do have the right answer, unlike all of the others): there's no ASCII involved here. A char is just another type of small integer, and you initialize it with the integral value of count (converted to a char, of course). And what he should write is more along the lines of std::vector<char> ary( count + 1);.
@James Why no ASCII involved? When you write char(32) you will get a space inside because 32 is the ASCII code for the space, won't you?
What you get on output depends on the output device. How you interpret it internally is up to you; if you interpret it as a character, and 32 is the code point for space in the encoding you're using (which is probably the case, even if ASCII itself is pretty much dead, and not used anywhere), then you will interpret it as a space. But in the end, char is an integral data type, which holds integral values. And in an expression like new char(count), there's nothing to say that count should be interpreted as a code point, rather than an ordinary integral value.
2

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.)

Comments

1

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.

Comments

0

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'; 

1 Comment

This still only allocates a single char. (What he really needs, of course, is std::vector<char> ary( count + 1 );.)
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.