2009-08-31 83 views
3

我有一个数据结构定义为自定义数据的iostream

struct myDataStruct 
{ 
    int32_t header; 
    int16_t data[8]; 
} 

,我想借此字符流,并把它变成一个MYDATA的流。我应该扩展什么类的流?我想创建一个自定义流类,这样我可以做这样的事情

myDataStruct myData; 
myDataStruct myDataArray[10]; 

myDataStream(ifstream("mydatafile.dat")); 
myDataStream.get(myData); 
myDataStream.read(myDataArray, 10); 
+0

您想要格式化输入(文本格式)还是从数据的二进制表示中读取(字段名称看起来像是消息) – 2009-08-31 22:51:16

+0

表示的数据是二进制的。每个数据包以标题序列开始并包含8个数据样本。我想将其转换成8个样本流。那些可以在另一个进程中使用或写入二进制文件。 – HazyBlueDot 2009-08-31 23:26:37

回答

5

相反的myDataStream.get(myData),你要做的就是超载operator>>为您的数据类型:

std::istream& operator>>(std::istream& is, myDataStruct& obj) 
{ 
    // read from is into obj 
    return is; 
} 

如果你想读到一个数组,只写一个循环:

for(std::size_t idx=0; idx<10; ++idx) 
{ 
    myDataStruct tmp; 
    if(is >> tmp) 
    myDataArray[idx] = tmp; 
    else 
    throw "input stream broken!"; 
} 

使用函数模板,你也应该能够重载运算符的右手SI阵列德(但我从来没有尝试过):

template< std::size_t N > 
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N]) 
{ 
    // use loop as above, using N instead of the 10 
} 

但我不能决定这是否华丽或卑鄙。

+1

或重载运算符>>(std :: istream&is,std :: vector &obj)用于数组并隐藏循环(对C数组来说不会那么容易) – Eugene 2009-08-31 23:17:47

+0

@Eugene:感谢评论,我扩展了我的帖子,提出了评论给我的想法。 – sbi 2009-08-31 23:27:58

+0

由于我们正在添加创意(即使我相信问题涉及二进制表示和未格式化的输入/输出),如果您相信输入的正确性,则可以尝试使用std :: copy/std :: copy_n算法。 – 2009-09-01 09:35:05

0

如果您使用的是未格式化的输入,则应该直接以二进制形式读取。通常你会使用一些编译器特定的指令来创建没有填充的数据结构,然后从文件中读/写。

// Gcc 
#pragma pack(1) // option 1: pragmas 
struct frame { 
    std::uint32_t header; 
    std::uint16_t data[8]; 
} __attribute((packed)); // option 2: packed attribute 
#pragma pack(0) 

bool operator==(data const & lhs, data const & rhs) 
{ 
    bool result = lhs.header == rhs.header; 
    for (int i = 0; i < 8; ++i) 
    { 
     result &= lhs.data[i] == rhs.data[i]; 
    } 
    return result; 
} 

int main() 
{ 
    frame data = { 10, 1, 2, 3, 4, 5, 6, 7, 8 }; 

    std::ofstream out("data.bin", ofstream::binary); 
    out.write(reinterpret_cast<char*>(&data), sizeof(data)); 
    out.close(); 

    std::ifstream in("data.bin", ifstream::binary); 
    frame readed; 
    in.read(reinterpret_cast<char*>(&readed), sizeof(readed)); 
    in.close(); 

    std::cout << (readed == data) << std::endl; // 1 
} 

的编译器指令禁用填充为VS可能是不同的(我相信编译指令都在GCC和VS的作品,但我一直使用的属性)。