从文件到字符串C ++读取任意长度的字节

时间:2011-04-13 14:14:41

标签: c++ string file-io

现在我对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;
}

实际上,我从cplusplus.com论坛条目中复制粘贴了main()的最后一部分,只是为了获得某种输出,但实际上我想要的是将字段保存为字符串对象数组,或者更好的是指向字符串对象的指针数组。 我正在阅读“C ++ Primer”,但仍然在200多页,但我想要摆弄一些c ++代码摆弄,所以如果有人能指出我的方法或概念或读数,我会非常高兴。

感谢您阅读

3 个答案:

答案 0 :(得分:2)

  • 以二进制模式打开文件,否则可能会出现问题。
  • 输出读取结果的方式有一个问题:它假设'\0'终止了你不确定得到的字符串(如果你的字段被填充,或者肯定不会得到它们带空格)。放大缓冲区并在阅读后添加'\0'

    buffer[header_bytes[n]] = '\0';
    

答案 1 :(得分:1)

创建一个描述文件格式的类/结构,类似于你在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

你可以比上面更高级,但这只是对现有代码的快速更改,而不是创建更精细的类/文件处理

答案 2 :(得分:1)

假设除了填充之外的字段中没有空格,您可以使用以下命令将它们读入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的{​​{3}}。