Я программист, пытающийся начать новую фазу своей жизни на c ++ (я знаю, что все еще использую printf ниже, но это потому, что форматирование так просто). Я ищу распечатать первый байт файла данных из функции-члена объекта. Я думаю, что мой потоковый буфер разрушается, прежде чем я могу прочитать его данные, но я теряюсь в том, что делать.
Мой класс выглядит следующим образом
class MyParser {
MyParser(string filepath);
void readHeader();
streambuf *pbuf;
long size;
}
Мой конструктор открывает файл, выводит буфер, выводит первый байт и возвращает. (Я думаю pbuf
умирает в конце этого кода). Этот код выводит First Byte (in constructor): 0x8C
MyParser::MyParser(string filepath) {
ifstream file(filepath.c_str(), ios::in | ios::binary)
pbuf = file.rdbuf();
size = pbuf->pubseekoff(0,ios::end,ios::in);
pbuf->pubseekpos(0,ios::in);
unsigned char byte = pbuf->sgetc();
printf("First Byte (in constructor): 0x%02X\n", byte);
return;
}
Мой заголовок чтения выводит первый байт, но в зависимости от вывода все видно First Byte (in readHeader): 0xFF
void MyParser::readHeader() {
unsigned char byte = pbuf->sgetc();
printf("First Byte (in readHeader): 0x%02X\n", byte);
}
Мой главный просто создает парсер и пытается прочитать заголовок
void main() {
MyParser parser("../data/data.bin");
parser.readHeader();
}
Я думаю, что решение моей проблемы заключается в создании new
потоковый буфер, но new streambuf(file.rdbuf())
не работает для меня Любой совет?
Ваша программа имеет неопределенное поведение: буфер потока, который вы храните, принадлежит std::ifstream
Вы открываете в теле своего конструктора. Когда этот объект умирает, буфер потока также освобождается. Самый простой способ избежать этой проблемы — это иметь std::ifstream
быть членом вашего класса: это связывает время жизни потока с вашим объектом. Также может быть проще использовать std::istream
интерфейс для вашего разбора, а не несколько неловко std::streambuf
интерфейс.
Если вы действительно хотите просто использовать буфер потока, вы можете выделить std::filebuf
с помощью new filebuf
и open()
поток файлов напрямую. Чтобы сохранить указатель на него, вы, вероятно, использовали бы std::unique_ptr<std::filebuf>
(или же std::auto_ptr<std::filebuf>
если вы не используете C ++ 2011). Использование класса указателя обеспечивает автоматическое освобождение объекта. Конечно, указатели по-прежнему будут членами вашего класса, чтобы правильно определить время жизни.
Ваша попытка скопировать потоковый буфер не сработала, потому что потоковые буферы не могут быть скопированы. Вам нужно создать буфер файлов напрямую:
MyParser::MyParser(std::string const& filename)
: pbuf(new std::filebuf)
{
this-pbuf->open("whatever", std::ios_base::in);
...
}
Вам нужен новый учебный материал по C ++, потому что (извините), но это так неправильно. Вы должны объявить файловый поток как член, в этом нет необходимости new
где-нибудь в этой программе, и почти никто никогда не должен иметь дело с streambuf
,
class MyParser {
std::ifstream file;
public:
MyParser(string filepath) {
file.open(filepath, std::ios::in | std::ios::binary );
char byte;
file.read(sizeof(byte), &byte);
printf("First Byte (in constructor): 0x%02X\n", byte);
}
void readHeader() {
char byte;
file.read(sizeof(byte), &byte);
printf("First Byte (in readHeader): 0x%02X\n", byte);
}
};