John Ruiz wrote:
Hello everyone. I find it amazing how in C++ that reading in files still
more or less requries usage of char * type. I know there's getline to use
std::string, but the basic_stream::get methods don't work with std::string.
I would like to create a function perhaps something like:
void read(std::string &s, int numBytes);
where the user passes in s to have numBytes of data read from a file into s.
Well, this would require me to do a thing like allocate memory of char bytes
and then do a copy over to the string.
How else would such a function work, even if it were part of the
standard library? Even with a bit of memcpy magic, how would you get
around copying the text out of the I/O system's buffer? Would it be
more efficient to use unbuffered input?
So, for this reason, I find myself
sticking to doing the C thing and using FILE pointers and all because to me,
What does that accomplish? Aren't you still working with C-style
strings? What problem have you solved or avoided?
it seems like a waste to read into a char array, then copy over to
std::string, so to avoid that copy, I just do the C thing.
You didn't have to do that copy when you were using std::istream,
either. You just chose to do so because you liked std::string. How has
that changed? Does mixing the standard library with the core language
make you feel bad?
So, am I unaware of a way around this problem? Thanks in advance.
Why not write your own implementation of "read" to use std::string if
you don't like null-terminated character arrays? You could append one
character at a time, as needed. If you're willing to spare a bit of
space, you could buffer the input yourself to get more characters with
each call to std::istream::read. The buffer even could be automatic, so
it wouldn't take up space unless your custom "read" function actually
were used. Wait a minute, let me go try something.
Ok, here you go. This isn't production code, it's just something I
whipped up; so, don't berate me if you see something you like. Do feel
free to point it out, though.
#include <cstddef>
#include <istream>
#include <string>
namespace IO
{
typedef std::istream Istream;
typedef std::string String;
typedef std::size_t Size;
/* Read as many chars as possible (up to given maximum) from an
* input stream and append them to a string. Return the number of
* characters successfully read.
*/
Size read( Istream&, String&, Size maximum_quantity_of_chars_to_read );
}
#include <iostream>
int main( )
{
std::string s;
IO::read( std::cin, s, 10 );
std::cout << s << '\n';
}
namespace IO
{
Size const buffer_size = 1024;
typedef char Buffer[ buffer_size ];
}
IO::Size IO::read( Istream& input, String& s, Size max_chars )
{
Size num_chars_read = 0; // To be returned.
Buffer buffer;
for( Size full_buffers_to_read = max_chars / buffer_size;
input and full_buffers_to_read;
--full_buffers_to_read )
{
input.read( buffer, buffer_size );
s.append( buffer, input.gcount( ) );
num_chars_read += input.gcount( );
}
Size chars_still_wanted = max_chars % buffer_size;
if( input and chars_still_wanted )
{
input.read( buffer, chars_still_wanted );
s.append( buffer, input.gcount( ) );
num_chars_read += input.gcount( );
}
return num_chars_read;
}