using fstream to read every character including spaces and newline

…衆ロ難τιáo~ 提交于 2019-11-28 04:22:34
Jason Etheridge

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.

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.

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

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

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

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

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

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.

user1621518

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

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.

Simple

#include <fstream>
#include <iomanip>


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

that's all.

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

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!