using fstream to read every character including sp

2019-01-16 12:30发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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



回答4:

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



回答5:

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



回答6:

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

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


回答7:

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.



回答8:

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>());


回答9:

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.



回答10:

Simple

#include <fstream>
#include <iomanip>


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

that's all.



回答11:

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


回答12:

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.



回答13:

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