我很难理解程序的行为。test.txt文件有16个字节,其中由于结构的指针p所指向的文本大小超过16个字节(字符串文本),因此还有其他int值。如何将额外的数据存储在只有16个字节的测试文件中。该文件由另一个结构"b"读取,但它提供了正确的值,如"a"。
int main()
{
string text("C:\Users\Chitra\Desktop\Capture.JPG");
string filepath("C:\Users\Chitra\Desktop\New folder\Project1\Project1\test.txt");
fstream fout(filepath,ios::out|ios::binary);
fstream fin(filepath,ios::in|ios::binary);
struct block
{
int value;
int size;
const char* p;
int some;
};
block a;
a.value = 1457745;
a.size = text.length();
a.p = text.c_str();
a.some = 97877;
fout.write((char*)&a, sizeof(a));
fout.close();
block b;
fin.read((char*)&b, sizeof(b));
fin.seekg(0, ios::end);
cout << "file size " << fin.tellg();
fin.close();
cout << "nsize a " << sizeof(a) << " size b " << sizeof(b);
cout << "n"<<b.value << " " << b.size << " " << b.p << " " << b.some;
getchar();
return 0;
}
文件只有16个字节,因为当您向文件写入a.p时,您正在写入一个指向内存中字符串的四字节指针值,而不是写入字符串数据本身。
它之所以有效,是因为在同一进程中,您立即将相同的指针值读回另一个指针变量,因此当您读取b.p指向的内存时,它与a.p指向的存储器相同,即以NUL结尾的字符串文本。
如果您创建的第二个程序只是读取文件,而没有声明字符串文本,那么您应该会遇到错误,或者至少看不到文本。
int main()
{
string filepath("C:\Users\Chitra\Desktop\New folder\Project1\Project1\test.txt");
fstream fin(filepath,ios::in|ios::binary);
struct block
{
int value;
int size;
const char* p;
int some;
};
block b;
fin.read((char*)&b, sizeof(b));
fin.seekg(0, ios::end);
cout << "file size " << fin.tellg();
fin.close();
cout << "n size b " << sizeof(b);
cout << "n"<<b.value << " " << b.size << " " << b.p << " " << b.some;
getchar();
return 0;
}
正如Sam Mikes所说的块。p是指针,你只保存它的值(指针的值是它指向的内存的地址),因为a.p在内存中仍然指向它,所以内存不会改变。添加下面的delete a;
代码,并查看不同的
*注意:a、b和块的大小相同,可以使用sizeof(a) or sizeof(b) or sizeof(block)
代替
#include <string>
#include<iostream>
#include <fstream>
using namespace std;
int main(){
string text("C:\Users\Chitra\Desktop\Capture.JPG");
string filepath("C:\Users\Chitra\Desktop\New folder\Project1\Project1\test.txt");
fstream fout(filepath,ios::out|ios::binary);
fstream fin(filepath,ios::in|ios::binary);
struct block {
int value;
int size;
const char* p;
int some;
};
block a;
a.value =1457745;
a.size=text.length();
a.p=text.c_str();
a. some=97877;
fout.write((char*)&a,sizeof(a));
fout.close();
delete a.p;
block b;
fin.read((char*)&b,sizeof(b));
fin.seekg(0,ios::end);
cout<<"file size "<<fin.tellg();
fin.close();
cout<<"nsize a "<<sizeof(a)<<" size b "<<sizeof(b)<<" size block "<<sizeof (block);
cout<<"n"<<b.value<<" "<<b.size<<" "<<b.p<<" "<<b.some;
getchar();
return 0;
}
你不能只做…
fout.write(pointer, bytes);
对于pointer
和byte
的任何值,因为数据不存在于连续内存中。必须分别写入不带指针的block
中嵌入的数据和指向字符串的数据。如果你把指针移到结构的末尾,然后写:,这是最简单的
struct block
{
int value;
int some;
int size;
const char* p;
};
fout.write((char*)&a, sizeof a - sizeof a.p);
// could also "offsetof(block, p)" for size - possibly more fragile
fout.write(a.p, a.size);
然后,要读回数据:
block b;
fin.read((char*)&b, sizeof b - sizeof b.p);
b.p = new char[b.size + 1];
fin.read(b.p, b.size);
b.p[b.size + 1] = ' '; // guarantee NUL termination
稍后,您将需要delete[] b.p;
来解除分配new[]
返回的内存。或者,您可以使用另一个string
:
block b;
fin.read((char*)&b, sizeof b - sizeof b.p);
std::string b_string(b.size, ' '); // initially b.size spaces
fin.read(&b_string[0], b.size); // overwrite with data from the file...
使用std::string
,在调用析构函数时会自动进行解除分配。
(实际上,最好使用带有std::fstream
s的C++串行化库,就像这里的boost一样。)