【发布时间】:2012-04-26 14:39:29
【问题描述】:
好的,请耐心等待,因为我将在下面介绍两次单独的尝试。
我首先开始阅读这里的指南 (http://www.cplusplus.com/doc/tutorial/files/)。然而,虽然它包含了如何使用 read() 的一个很好的示例,但它没有包含如何使用 write() 的示例。
我首先尝试使用 write() 以二进制形式存储一个简单的 char 数组。我最初的想法(和希望)是我可以使用 ios::app 将新条目附加到这个文件中。最初这似乎可行,但我也得到了垃圾输出。另一个论坛上的帖子寻求帮助表明我的 char 数组末尾缺少空终止符。我应用了这个(或至少尝试基于我的显示方式),如下面的示例所示。不幸的是,这意味着 read() 不再正常运行,因为它不会读取空终止符。
我还被告知,char *memoryBlock 是对 C++ 标准或其他东西的“滥用”,而且是不安全的,我应该改为定义一个精确大小的数组,即char memoryBlock[5],但是如果我想怎么办将字符数据写入可以是任何大小的文件?那我该如何进行呢?下面的代码包括各种注释掉的代码行,表明我所做的各种尝试和不同的变体,包括我上面提到的一些建议。我确实希望尝试使用良好实践的代码,所以如果 char *memoryBlock 不安全,或者任何其他代码行,我希望修改它。
我还想澄清一下,我在这里写字符只是为了测试目的,所以请不要建议我应该用文本模式而不是二进制模式来写。我将在下面的代码下的这个问题的第二部分进一步阐述。
第一个代码:
#include <cstdlib>
#include <iostream>
#include <fstream>
//#include <string>
int main()
{
//char memoryBlock[5];
char *memoryBlock;
char *memoryBlockTwo;
std::ifstream::pos_type size;// The number of characters to be read or written from/to the memory block.
std::ofstream myFile;
myFile.open("Example", std::ios::out | /*std::ios::app |*/ std::ios::binary);
if(myFile.is_open() && myFile.good())
{
//myFile.seekp(0,std::ios::end);
std::cout<<"File opening successfully completed."<<std::endl;
memoryBlock = "THEN";
//myFile.write(memoryBlock, (sizeof(char)*4));
//memoryBlock = "NOW THIS";
//strcpy_s(memoryBlock, (sizeof(char)*5),"THIS");
//memoryBlock = "THEN";
//strcpy(memoryBlock, "THIS");
//memoryBlock[5] = NULL;
myFile.write(memoryBlock, (sizeof(char)*5));
}
else
{
std::cout<<"File opening NOT successfully completed."<<std::endl;
}
myFile.close();
std::ifstream myFileInput;
myFileInput.open("Example", std::ios::in | std::ios::binary | std::ios::ate);
if(myFileInput.is_open() && myFileInput.good())
{
std::cout<<"File opening successfully completed. Again."<<std::endl;
std::cout<<"READ:"<<std::endl;
size = myFileInput.tellg();
memoryBlockTwo = new char[size];
myFileInput.seekg(0, std::ios::beg);// Get a pointer to the beginning of the file.
myFileInput.read(memoryBlockTwo, size);
std::cout<<memoryBlockTwo<<std::endl;
delete[] memoryBlockTwo;
std::cout<<std::endl<<"END."<<std::endl;
}
else
{
std::cout<<"Something has gone disasterously wrong."<<std::endl;
}
myFileInput.close();
return 0;
}
我的下一次尝试是基于尝试将 ios::app 与 ios::binary 一起使用根本行不通,并且要修改文件,我必须阅读整个内容,进行更改,然后回写并替换文件的全部内容,尽管这看起来效率不高。
但是我没有在下面的代码中阅读和修改内容。我实际上想要做的是将自定义类的对象写入文件,然后将其完整地再次读取。
这似乎可行(尽管如果我在这里的代码方面做得不好,请指出),但是,我似乎无法存储 std::string 和 std::vector 类型的变量,因为我遇到了访问冲突当我到达 myFileInput.close() 时。将这些成员变量注释掉后,不会发生访问冲突。对于为什么会发生这种情况,我最好的猜测是他们使用指向其他内存的指针来存储他们的文件,我不是将数据本身写入我的文件,而是指向它的指针,当我阅读我的文件时,它碰巧仍然有效数据输出。
是否有可能将这些更复杂的数据类型的内容存储在一个文件中?还是我必须将所有内容分解为更基本的变量,例如字符、整数和浮点数?
第二个代码:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class testClass
{
public:
testClass()
{
testInt = 5;
testChar = 't';
//testString = "Test string.";
//testVector.push_back(3.142f);
//testVector.push_back(0.001f);
}
testClass(int intInput, char charInput, std::string stringInput, float floatInput01, float floatInput02)
{
testInt = intInput;
testChar = charInput;
testArray[0] = 't';
testArray[1] = 'e';
testArray[2] = 's';
testArray[3] = 't';
testArray[4] = '\0';
//testString = stringInput;
//testVector = vectorInput;
//testVector.push_back(floatInput01);
//testVector.push_back(floatInput02);
}
~testClass()
{}
private:
int testInt;
char testChar;
char testArray[5];
//std::string testString;
//std::vector<float> testVector;
};
int main()
{
testClass testObject(3, 'x', "Hello there!", 9.14f, 6.662f);
testClass testReceivedObject;
//char memoryBlock[5];
//char *memoryBlock;
//char *memoryBlockTwo;
std::ifstream::pos_type size;// The number of characters to be read or written from/to the memory block.
std::ofstream myFile;
myFile.open("Example", std::ios::out | /*std::ios::app |*/ std::ios::binary);
if(myFile.is_open() && myFile.good())
{
//myFile.seekp(0,std::ios::end);
std::cout<<"File opening successfully completed."<<std::endl;
//memoryBlock = "THEN";
//myFile.write(memoryBlock, (sizeof(char)*4));
//memoryBlock = "NOW THIS";
//strcpy_s(memoryBlock, (sizeof(char)*5),"THIS");
//memoryBlock = "THEN AND NOW";
//strcpy(memoryBlock, "THIS");
//memoryBlock[5] = NULL;
myFile.write(reinterpret_cast<char*>(&testObject), (sizeof(testClass)));//(sizeof(char)*5));
}
else
{
std::cout<<"File opening NOT successfully completed."<<std::endl;
}
myFile.close();
std::ifstream myFileInput;
myFileInput.open("Example", std::ios::in | std::ios::binary | std::ios::ate);
if(myFileInput.is_open() && myFileInput.good())
{
std::cout<<"File opening successfully completed. Again."<<std::endl;
std::cout<<"READ:"<<std::endl;
size = myFileInput.tellg();
//memoryBlockTwo = new char[size];
myFileInput.seekg(0, std::ios::beg);// Get a pointer to the beginning of the file.
myFileInput.read(reinterpret_cast<char *>(&testReceivedObject), size);
//std::cout<<memoryBlockTwo<<std::endl;
//delete[] memoryBlockTwo;
std::cout<<std::endl<<"END."<<std::endl;
}
else
{
std::cout<<"Something has gone disasterously wrong."<<std::endl;
}
myFileInput.close();
return 0;
}
对于这个问题的冗长,我深表歉意,但我希望我在提供尽可能多的关于我的问题的信息方面的彻底性将加快答案的出现,即使对于这个问题(甚至可能是一个简单的问题修复虽然我已经搜索了几个小时试图找到解决方案),因为时间是一个因素。我将全天监控这个问题,以便在回答的帮助下提供澄清。
【问题讨论】:
-
有点难以理解 恐怕我无法找出问题所在,因为您已将代码注释掉,请尝试提供能够重现该错误的最少代码。作为初学者,您看起来有一些内存分配问题。还有什么错误,你得到一个核心转储,还是你在文件中得到废话?
-
当前提供的代码会产生我所描述的问题。不包括带有向量和字符串的第二个示例,但我已经解释了围绕那些请求答案的问题。您需要做的就是取消注释类中引用向量和字符串的代码。
-
在第一个示例中,由于未定义 memoryBlock,因此无法编译。如果您取消注释任何一个定义,您就会遇到问题,因为您没有分配任何或足够的空间。
-
抱歉,我取消了相应行的注释。
-
read将读取文件中的NULL终止符。std::cout只是不会打印过去。