Tomek
Tomek

Reputation:

using fstream to read every character including spaces and newline

I wanted to use fstream to read a txt file.

I am using inFile >> characterToConvert, but the problem is that this omits any spaces and newline.

I am writing an encryption program so I need to include the spaces and newlines.

What would be the proper way to go about accomplishing this?

Upvotes: 34

Views: 78973

Answers (13)

jdhao
jdhao

Reputation: 28507

I also find that the get() method of ifstream object can also read all the characters of the file, which do not require unset std::ios_base::skipws. Quote from C++ Primer:

Several of the unformatted operations deal with a stream one byte at a time. These operations, which are described in Table 17.19, read rather ignore whitespaces.

These operations are list as below: is.get(), os.put(), is.putback(), is.unget() and is.peek().

Below is a minimum working code

#include <iostream>
#include <fstream>
#include <string>

int main(){
    std::ifstream in_file("input.txt");

    char s;

    if (in_file.is_open()){
        int count = 0;
        while (in_file.get(s)){

            std::cout << count << ": "<< (int)s <<'\n';
            count++;
        }

    }
    else{
        std::cout << "Unable to open input.txt.\n";
    }
    in_file.close();

    return 0;
 }

The content of the input file (cat input.txt) is

ab cd
ef gh

The output of the program is:

0: 97
1: 98
2: 32
3: 99
4: 100
5: 10
6: 101
7: 102
8: 32
9: 103
10: 104
11: 32
12: 10

10 and 32 are decimal representation of newline and space character. Obviously, all characters have been read.

Upvotes: 0

Jason Etheridge
Jason Etheridge

Reputation: 6917

Probably the best way is to read the entire file's contents into a string, which can be done very easily using ifstream's rdbuf() method:

std::ifstream in("myfile");

std::stringstream buffer;
buffer << in.rdbuf();

std::string contents(buffer.str());

You can then use regular string manipulation now that you've got everything from the file.

While Tomek was asking about reading a text file, the same approach will work for reading binary data, though the std::ios::binary flag needs to be provided when creating the input file stream.

Upvotes: 52

user1621518
user1621518

Reputation: 21

Another better way is to use istreambuf_iterator, and the sample code is as below:

ifstream inputFile("test.data");

string fileData(istreambuf_iterator<char>(inputFile), istreambuf_iterator<char>());

Upvotes: 2

MCA
MCA

Reputation: 59

ifstream ifile(path);
std::string contents((std::istreambuf_iterator<char>(ifile)), std::istreambuf_iterator<char>());
ifile.close();

Upvotes: 0

Iakov Minochkin
Iakov Minochkin

Reputation: 432

std::ifstream ifs( "filename.txt" );

std::string str( ( std::istreambuf_iterator<char>( ifs ) ), 
                 std::istreambuf_iterator<char>()
               );

Upvotes: 4

luke
luke

Reputation: 37493

For encryption, you're better off opening your file in binary mode. Use something like this to put the bytes of a file into a vector:

std::ifstream ifs("foobar.txt", std::ios::binary);

ifs.seekg(0, std::ios::end);
std::ifstream::pos_type filesize = ifs.tellg();
ifs.seekg(0, std::ios::beg);

std::vector<char> bytes(filesize);

ifs.read(&bytes[0], filesize);

Edit: fixed a subtle bug as per the comments.

Upvotes: 22

Flame
Flame

Reputation: 2207

Simple

#include <fstream>
#include <iomanip>


ifstream ifs ("file");
ifs >> noskipws

that's all.

Upvotes: 0

Constantin
Constantin

Reputation: 28204

As Charles Bailey correctly pointed out, you don't need fstream's services just to read bytes. So forget this iostream silliness, use fopen/fread and be done with it. C stdio is part of C++, you know ;)

Upvotes: -5

CB Bailey
CB Bailey

Reputation: 793249

A lot of the benefit of the istream layer is providing basic formatting and parsing for simple types ro and from a stream. For the purposes that you describe, none of this is really important and you are just interested in the file as a stream of bytes.

For these purpose you may be better of just using the basic_streambuf interface provided by a filebuf. The 'skip whitespace' behaviour is part of the istream interface functionality that you just don't need.

filebuf underlies an ifstream, but it is perfectly valid to use it directly.

std::filebuf myfile;
myfile.open( "myfile.dat", std::ios_base::in | std::ios_base::binary );

// gets next char, then moves 'get' pointer to next char in the file
int ch = myfile.sbumpc();

// get (up to) the next n chars from the stream
std::streamsize getcount = myfile.sgetn( char_array, n );

Also have a look at the functions snextc (moves the 'get' pointer forward and then returns the current char), sgetc (gets the current char but doesn't move the 'get' pointer) and sungetc (backs up the 'get' pointer by one position if possible).

When you don't need any of the insertion and extraction operators provided by an istream class and just need a basic byte interface, often the streambuf interface (filebuf, stringbuf) is more appropriate than an istream interface (ifstream, istringstream).

Upvotes: 3

jdmichal
jdmichal

Reputation: 11162

You can call int fstream::get(), which will read a single character from the stream. You can also use istream& fstream::read(char*, streamsize), which does the same operation as get(), just over multiple characters. The given links include examples of using each method.

I also recommend reading and writing in binary mode. This allows ASCII control characters to be properly read from and written to files. Otherwise, an encrypt/decrypt operation pair might result in non-identical files. To do this, you open the filestream with the ios::binary flag. With a binary file, you want to use the read() method.

Upvotes: 2

user3458
user3458

Reputation:

For encryption, you should probably use read(). Encryption algorithms usually deal with fixed-size blocks. Oh, and to open in binary mode (no translation frmo \n\r to \n), pass ios_base::binary as the second parameter to constructor or open() call.

Upvotes: 1

Adam Holmberg
Adam Holmberg

Reputation: 7365

I haven't tested this, but I believe you need to clear the "skip whitespace" flag:

inFile.unsetf(ios_base::skipws);

I use the following reference for C++ streams: IOstream Library

Upvotes: 16

mmattax
mmattax

Reputation: 27710

The following c++ code will read an entire file...


#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () 
{
  string line;
  ifstream myfile ("foo.txt");

  if (myfile.is_open()){

    while (!myfile.eof()){
      getline (myfile,line);
      cout << line << endl;
    }
    myfile.close();
  }
  return 0;
}

post your code and I can give you more specific help to your problem...

Upvotes: 3

Related Questions