использование fstream для чтения каждого символа включая пробелы и новую строку

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

30
задан Toby Speight 11 May 2016 в 11:42
поделиться

9 ответов

Вероятно, лучший способ состоит в том, чтобы считать содержание всего файла в строку, которая может быть сделана очень легко с помощью ifstream's rdbuf() метод:

std::ifstream in("myfile");

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

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

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

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

48
ответ дан 27 November 2019 в 23:10
поделиться

Как Charles Bailey правильно указал, Вам не нужны сервисы fstream только для чтения байтов. Поэтому забудьте эту iostream глупость, используйте fopen/fread и будьте сделаны с ним. C stdio является частью C++, Вы знаете ;)

-5
ответ дан 27 November 2019 в 23:10
поделиться

Простой

#include <fstream>
#include <iomanip>


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

это - все.

0
ответ дан 27 November 2019 в 23:10
поделиться

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

1
ответ дан 27 November 2019 в 23:10
поделиться

Следующий код 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;
}

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

3
ответ дан 27 November 2019 в 23:10
поделиться

Большое преимущество 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 (перемещает 'получить' указатель вперед и затем возвращает текущий символ), sgetc (получает текущий символ, но не перемещает 'получить' указатель), и sungetc (создает резервную копию 'получить' указателя одним положением если возможный).

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

3
ответ дан 27 November 2019 в 23:10
поделиться

Я не протестировал это, но я полагаю, что необходимо очистить "пробельный флаг" пропуска:

inFile.unsetf(ios_base::skipws);

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

14
ответ дан 27 November 2019 в 23:10
поделиться

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

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

2
ответ дан 27 November 2019 в 23:10
поделиться

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

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

Редактирование: исправленный тонкая ошибка согласно комментариям.

22
ответ дан 27 November 2019 в 23:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: