используя fstream для чтения каждого символа, включая пробелы и перевод строки - PullRequest
30 голосов
/ 22 сентября 2008

Я хотел использовать fstream для чтения текстового файла.

Я использую inFile >> characterToConvert, но проблема в том, что при этом пропускаются пробелы и перевод строки.

Я пишу программу шифрования, поэтому мне нужно включить пробелы и переводы строк.

Каков будет правильный путь для достижения этой цели?

Ответы [ 13 ]

48 голосов
/ 23 сентября 2008

Вероятно, лучший способ - это прочитать все содержимое файла в строку, что очень легко сделать, используя метод ifstream * rdbuf():

std::ifstream in("myfile");

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

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

Теперь вы можете использовать обычные операции со строками, когда у вас есть все из файла.

Пока Tomek спрашивал о чтении текстового файла, тот же подход будет работать для чтения двоичных данных, хотя при создании потока входного файла должен быть указан флаг std :: ios :: binary.

22 голосов
/ 22 сентября 2008

Для шифрования лучше открыть файл в двоичном режиме. Используйте что-то вроде этого, чтобы поместить байты файла в вектор:

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

Редактировать: исправлена ​​небольшая ошибка в комментариях.

14 голосов
/ 22 сентября 2008

Я не проверял это, но я считаю, что вам нужно снять флажок «пропустить пробел»:

inFile.unsetf(ios_base::skipws);

Я использую следующую ссылку для потоков C ++: Библиотека IOstream

3 голосов
/ 13 апреля 2011
std::ifstream ifs( "filename.txt" );

std::string str( ( std::istreambuf_iterator<char>( ifs ) ), 
                 std::istreambuf_iterator<char>()
               );
3 голосов
/ 23 сентября 2008

Большим преимуществом слоя istream является обеспечение базового форматирования и анализа для простых типов ro и из потока. Для целей, которые вы описываете, ничего из этого не является действительно важным, и вы просто интересуетесь файлом как поток байтов.

Для этих целей вам лучше всего использовать интерфейс basic_streambuf, предоставляемый filebuf. Поведение «пропуска пробелов» является частью функциональности интерфейса istream, которая вам просто не нужна.

filebuf лежит в основе ifstream, но вполне допустимо использовать его напрямую.

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

Также обратите внимание на функции snextc (перемещает указатель 'get' вперед и затем возвращает текущий символ), sgetc (получает текущий символ, но не перемещает указатель 'get') и sungetc (выполняет резервное копирование указатель 'get' на одну позицию, если это возможно).

Когда вам не нужны какие-либо операторы вставки и извлечения, предоставляемые классом istream, и вам просто нужен базовый байтовый интерфейс, часто интерфейс streambuf (filebuf, stringbuf) более подходит, чем интерфейс istream (ifstream, istringstream) .

3 голосов
/ 22 сентября 2008

Следующий код C ++ прочитает весь файл ...


#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;
}

опубликуйте свой код, и я могу оказать вам более конкретную помощь в решении вашей проблемы ...

2 голосов
/ 24 августа 2012

Другой лучший способ - использовать istreambuf_iterator, а пример кода такой:

ifstream inputFile("test.data");

string fileData(istreambuf_iterator<char>(inputFile), istreambuf_iterator<char>());
2 голосов
/ 22 сентября 2008

Вы можете позвонить int fstream::get(), который будет читать один символ из потока. Вы также можете использовать istream& fstream::read(char*, streamsize), который выполняет ту же операцию, что и get(), только над несколькими символами. Указанные ссылки включают примеры использования каждого метода.

Я также рекомендую читать и писать в двоичном режиме. Это позволяет правильно читать и записывать управляющие символы ASCII в файлы. В противном случае пара операций шифрования / дешифрования может привести к появлению неидентичных файлов. Для этого вы открываете файловый поток с флагом ios::binary. С двоичным файлом вы хотите использовать метод read().

1 голос
/ 22 сентября 2008

Для шифрования вам, вероятно, следует использовать read () . Алгоритмы шифрования обычно работают с блоками фиксированного размера. Да, и чтобы открыть в двоичном режиме (без перевода frmo \ n \ r в \ n), передайте ios_base :: binary в качестве второго параметра в конструктор или вызов open ().

0 голосов
/ 15 июня 2017

Я также обнаружил, что метод get () объекта ifstream также может читать все символы файла, для которых не требуется сбрасывать std::ios_base::skipws. Цитата из C ++ Primer :

Некоторые из неотформатированных операций имеют дело с потоком по одному байту за раз. Эти операции, которые описаны в Таблице 17.19, читают, а игнорируют пробелы.

Эти операции перечислены ниже: is.get () , os.put () , is.putback () , is.unget () и is.peek () . * +1022 *

Ниже приведен минимальный рабочий код

#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;
 }

Содержимое входного файла (cat input.txt) равно

ab cd
ef gh

Вывод программы:

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 и 32 - десятичное представление символа новой строки и пробела. Очевидно, все символы были прочитаны.

...