读取/写入我自己的Vector实现文件以进行作业 - ifstream.read(),是否有必要将char *转换为int,若然,如何?

时间:2017-04-28 10:53:44

标签: c++ binary fstream

我在那里提供了一个内容丰富的标题,对不起,如果它太长了。

我正在使用C ++为OOP上的CIS类工作。对于这个类,我们通常需要实现提供的头而不修改它或#include任何其他库。当前的赋值是将void Read(std::ifstream&)void Write(std::ofstream&)函数添加到我们为之前的赋值实现的Vector类中。

要求是:

  • 必须以二进制模式打开所有文件。
  • write函数必须将类型为T的内部数组写入文件
  • 读取函数必须将文件读入类型为T的数组。

没有指定从输入文件中读取的数组要做什么。我的假设是返回引用,但read()的返回类型在赋值中指定为void。我最好的猜测是,我的教授只是想让我们展示读入数组的能力,这就是我正在拍摄的内容。我还考虑将输入文件的数组连接到任何向量对象调用read()的末尾,但我认为这不重要,所以我离题了。

我相信我已经写好了()。这就是我现在正在处理的事情: Write()被破坏了,我会在代码后解释:

306 template <class T> void Vector<T>::Write (std::ofstream& ofile) const                                                                                                                                                                    
307 {                                                                                                                                                                                                                                    
308   if (!ofile.is_open()) ofile.open("vector.bin", std::ios::trunc | std::ios::binary);                                                                                                                                                    
309                                                                                                                                                                                                                                          
310   if (ofile.is_open())                                                                                                                                                                                                                   
311   {                                                                                                                                                                                                                                      
312     ofile.write((char*)&m_array, sizeof(m_array));                                                                                                                                                                                       
313   } else throw -6;                                                                                                                                                                                                                       
314                                                                                                                                                                                                                                          
315   ofile.close();                                                                                                                                                                                                                         
316 }     

当write()运行时,它会毫无错误地执行此操作,但它会将一些非常不正确的内容写入输出文件中。假设m_array包含{2,8,16,4}。输出文件将包含:

01000000 00010000 00001000 00100000

什么时候应该包含(假设sizeof(int)是4,我知道我不应该假设,但你明白了):

01000000 00000000 00000000 00000000
00010000 00000000 00000000 00000000
00001000 00000000 00000000 00000000
00100000 00000000 00000000 00000000

似乎当我将m_array转换为char *时,我的计算机是一个聪明的裤子并且意识到由数字4表示的字符不会占用4个字节。

我的工作方式有点像:

void* temp = m_array;
char* buffer = (char*)temp;

这似乎有助于编译器忘记m_array中的4个字节实际上代表一个元素。它只是感觉很难看,我觉得必须有一个合乎逻辑的方法来做到这一点,或者它不会是一个介绍性的C ++类中的任务。

无论如何,我遇到的问题是读取功能。如果我是正确的,那么根据此分配实现的向量对象将只能从该特定对象写入的文件中读取。如果写入读取的算法尝试从Vector写入的文件中读取,那么它只会变得垃圾,对吧?这是我遇到的一个重大挑战,编写一个能够从文件读取到T类数组的算法,而不管表达T所需的实际字节数。

我现在所处的轨道是做以下事情:

T temp;
char* buffer = new char[sizeof(T)];
// Loop the following for the entire file
ifile.read(buffer, sizeof(T));
temp = T(*buffer); // I know this won't work, this is what I'm trying to get at

如果我理解正确,这将允许我将正确数量的字节读入char数组。例如,如果将int的arrray写入文件,它将读取两个字节并将其存储在char两个长的数组中。然后,我的缓冲区变量将包含我想要的数据。

我如何将这些数据转化为临时数据??!?

我在这里疯了,特别是因为我知道atoi会很好地工作,或者至少值得一些调查。我认为这不会解决我为任何原始数据类型工作的问题,但它至少是一个开始。我把头发拉出来因为我有一个两个字节的数组,如果我把它们放在一起我就会得到我想要的int,但是我无法弄清楚如何将它们放在一起。我是怎么回事呢?这是一种尝试从二进制文件中读取的荒谬方式吗?

我可以像temp = *(int*(buffer))这样做吗?这对我来说似乎很难看,而且我更愿意理解正确的做事情的方式,而不是尝试每一个疯狂的想法,直到有些事情发生。

非常感谢您阅读我的沙拉。

1 个答案:

答案 0 :(得分:1)

在处理二进制数据时,我倾向于使用memcpy / memmove。回答你的问题:

T temp;
char* buffer = new char[sizeof(T)];

// Loop the following for the entire file
ifile.read(buffer, sizeof(T));
//Put binary data into temp var
std::memcpy(&temp, buffer, sizeof(T));

对于更优雅的解决方案,我会使用一种C结构,您可以在一次操作中直接从文件中写入/读取:

typedef struct vector_s {
    uint32_t   bytesPerElement;
    uint32_t   numberOfElements;
    char       data[1]; //Structure hack works because its the last element. 
}   vector_t;

然后玩C结构hack:Is the "struct hack" technically undefined behavior?