Чтение байтов произвольной длины из файла в строку C ++ - PullRequest
1 голос
/ 13 апреля 2011

Теперь, когда я довольно хорошо знаком с Python, решил изучать C ++, поэтому я очень n00b, но уверен, что готов учиться.Я сделал скрипт для чтения из очень строго заданного формата файла (.EDF, для медицинских сигналов), с заголовком ascii, определяемым размерами полей в байтах.Итак, я прочитал 8 байтов для первого поля, 80 байтов для второго поля и т. Д.

Мой рабочий скрипт на Python выглядит следующим образом:

## HEADER FIELD NAMES AND SIZES FROM EDF SPEC:
header_fields = (
('version',     8),    ('patinfo',    80),    ('recinfo',      80),
('start date',  8),    ('start time',  8),    ('header bytes',  8),
('reserved',   44),   ('nrecs',        8),    ('recduration',   8),
('nchannels', 4))

## TELL WHICH FILE TO OPEN
folder = os.path.expanduser('~/Dropbox/01MIOTEC/06APNÉIA/Samples')
f = open(folder + '/Osas2002plusQRS.rec', 'rb')

# READ FILE CONTENT TO DICTIONARY OF LABELLED FIELD CONTENTS,
# ALREADY STRIPPED FROM BLANK SPACES
header = {}
for key, value in header_fields:
    header[key] = f.read(value).strip()

Конечный результат равен 'header ', словарь, в котором каждая пара является «помеченной» строкой.

Мой текущий неуклюжий код на C ++, который почти работает для печати без разметки строк, выглядит так:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

static int header_bytes[] = {8,80,80,80,80,8,8,8,44,8,8,4};
static int header_bytes_len = sizeof(header_bytes)/sizeof(int);
static string header_fields[] =
{
    "version",     
    "patinfo",     
    "recinfo",     
    "patinfo",     
    "recifo",      
    "start date",  
    "start time",  
    "header bytes",
    "reserved",    
    "nrecs",       
    "rec duration",
    "nchannels"
};

int main()
{
    ifstream edfreader;
    edfreader.open("/home/helton/Dropbox/01MIOTEC/06APNÉIA/Samples/Osas2002plusQRS.rec", ios::binary);

    char * buffer = new char [80];
    for (int n = 0; n<header_bytes_len; n++)
    {
        edfreader.read(buffer, header_bytes[n]);
        buffer[header_bytes[n]] = '\0';
        cout<<"'"<<buffer<<"'"<<endl;
    }
    return 0;
}

На самом делеЯ скопировал и вставил последнюю часть main () из записи форума cplusplus.com, просто для того, чтобы получить какой-то вывод, но на самом деле я хотел сохранить поля как массив строковых объектов или, что еще лучше, массивуказателей на строковые объекты.Я читаю "C ++ Primer", но все еще на 200+ страницах, но я очень хочу немного поиграться с кодом на C ++, поэтому, если кто-нибудь сможет указать мне на некоторые методы, концепции или чтения, я буду очень счастлив.

Спасибо за чтение

Ответы [ 3 ]

2 голосов
/ 13 апреля 2011
  • Откройте файл в двоичном режиме или у вас могут возникнуть проблемы.
  • Существует проблема в способе вывода результата чтения: предполагается, что '\0' завершенные строки, которые выне уверены, что получите (или, возможно, не получите, если ваши поля заполнены пробелами).Увеличьте буфер и добавьте '\0' после прочтения:

    buffer[header_bytes[n]] = '\0';
    
1 голос
/ 13 апреля 2011

Предполагая, что в полях нет пробелов, кроме отступа, вы можете прочитать их в строки C ++, используя:

/* Read field of n bytes */
std::string read_field(std::istream &edfreader, size_t n)
{
    // there's no need for new;
    // in fact, new may lead to a memory leak if you forget to delete
    std::vector<char> buf(n);

    // read as a sequence of bytes
    edfreader.read(&buf.front(), n);

    // find the first space or end of buffer
    size_t end = 0;
    while (end < n && buf[end] != ' ')
        end++;

    // make a string object from the buffer
    return std::string(buf, end);
}

std::string выполняет выделение памяти для вас;вы можете использовать его почти как строку Python, за исключением того, что он может быть изменен.

Единственные допущения, которые здесь сделаны, заключаются в том, что набор символов вашей ОС (расширенный набор) ASCII и что обработка исключений включена для edfreader.

1 голос
/ 13 апреля 2011

создайте класс / структуру, описывающую формат файла, аналогично тому, что вы делали в python

   struct Header {
    char version[8];
    char patinfo[80];
    ..., 
    };

, затем откройте файл в двоичном режиме и прочитайте записи, используя приведенную выше структуру

ifstream file( "filename", ios::binary );
Header H;
file.read( reinterpret_cast<char*>(&H), sizeof(H) );

это читает запись заголовка, теперь вы можете получить доступ к содержимому структуры, но вы должны быть осторожны, не относиться к элементам как к строкам, так как они могут иметь или не иметь окончание \ 0

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...