C/C++ 二进制文件读写

一个短整型数字(例如 1297)既可以用一个字符串表示 "1297",如图 1 所示:



图 1 以字符串表示的数字


也可以用一个二进制数字表示,如图 2 所示:

图 2 以二进制表示的数字


这两种表示都可以看作是字节序列。字符串表示取决于用于表示单个字符的编码类型,使用 ASCII 编码时长度为 4 个字节。二进制数字表示中的字节数取决于数字的类型,当数字是短整型时,长度为 2 个字节。从字符串表示到数字的转换称为解析,而从数字到字符串的逆转换称为格式化。

c++二进制文件读写样例

写操作。 
ofstream write(char *buffer, int length) 
buffer是变量指针,一般需要强制转化成char *类型,然后加取地址符,因为任何内容都可以表现成字符的形式,而后面的length则是变量类型的字节长,一般用sizeof进行计算防止不必要的错误,下面看实例。

 

    double pos[200];
    int a = 110;
	for(int i = 0; i < 200; i ++ )
		pos[i] = i ;
	//写出数据
	ofstream f("binary.dat",ios::binary);
	if(!f)
	{
		cout << "创建文件失败" <<endl;
		return;
	}
	f.write((char*)pos, 200*sizeof(double));      //fwrite以char *的方式进行写出,做一个转化
    f.write((char*)&a,sizeof(int));
	f.close();

	double pos[200];
    int a1;
	ifstream f("binary.dat", ios::binary);
	if(!f)
	{
		cout << "读取文件失败" <<endl;
		return;
	}
	f.read((char*)pos,200*sizeof(double));
    f.read((char*)&a1,sizeof(int));
	for(int i = 0; i < 200; i++)
		cout << pos[i] <<endl;
	f.close();

	f.open("xx.txt",ios::in);	
	//文件打开方式选项:
	// ios::in    = 0x01, //供读,文件不存在则创建(ifstream默认的打开方式)
	// ios::out    = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式)
	// ios::ate    = 0x04, //文件打开时,指针在文件最后。可改变指针的位置,常和in、out联合使用
	// ios::app    = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后
	// ios::trunc   = 0x10, //在读写前先将文件长度截断为0(默认)
	// ios::nocreate = 0x20, //文件不存在时产生错误,常和in或app联合使用
	// ios::noreplace = 0x40, //文件存在时产生错误,常和out联合使用
//复杂数据类型 二进制读写
#include<fstream>
#include<iostream>
#include<cstring>
struct A
{
    int a;
    double b;
};
int main()
{
    using namespace std;
    A aa={1127,3.1415};
    ofstream ofs("test.txt",ios::binary);
    ofs.write((char*)&aa,sizeof(A));
    ofs.close();
    A bb;
    ifstream ifs("test.txt",ios::binary);
    ifs.read((char*)&bb,sizeof(A));
    cout<<bb.a<<endl;
    cout<<bb.b<<endl;
    return 0;
}

----------------------------------分割线-------------------------

信息可按纯粹的二进制格式存储在文件中。存储的第一步是以二进制模式打开文件,其方法是使用 ios::binary 标志。示例如下:

file.open("stuff.dat", ios::out | ios::binary);

请注意,ios::out 和 ios::binary 标志使用|运算符联合加入到语句中,这导致文件以输出和二进制模式打开。

注意,默认情况下,文件以文本模式打开。

ostream 和 ofstream 类的 write 成员函数可用于将二进制数据写入文件或其他输出流。要调用该函数,需指定一个缓冲区的地址,该缓冲区包含一个要写入的字节数组和一个指示要写入多少字节的整数:

write(addressOfBuffer, numberOfBytes);

write 成员函数不会区分缓冲区中的整数、浮点数或其他类型;它只是将缓冲区视为一个字节数组。由于 C++ 不支持指向字节的指针,因此 write 函数原型将指定缓冲区的地址是指向 char 的指针:

write(char *addressOfBuffer, int numberOfBytes);

这意味着当调用 write 时,需要告诉编译器将缓冲区的地址解释为指向 diar 的指针。要做到这一点,可以使用称为 reinterpret_cast 的特殊形式的类型转换。简单地说,reinterpret_cast 可用于强制编译器解释一个类型的位,就好像它们定义了一个不同类型的值。

以下示例即是使用 reinterpet_cast 将指向 double 的指针转换为指向 char 的指针:

double d = 45.9;
double *pd = &d;
char *pChar;
//将指向double的指针转换为指向char的指针
pChar = reinterpret_cast<char *>(pd);

一般来说,将某个值转换为某些目标类型,可以使用以下表达式:

reinterpret_cast<TargetType>(value);

以下是使用 write 将一个 double 类型数字和一个包含 3 个 double 类型数字的数组写入文件的示例:

double dl = 45.9;
double dArray[3] = { 12.3, 45.8, 19.0 };
ofstream outFile("stuff.dat", ios::binary);
outFile.write(reinterpret_cast<char *>(&dl), sizeof(dl));
outFile.write(reinterpret_cast<char *>(dArray),sizeOf(dArray));

请注意,在写入单个变量(如以上示例中的 dl)时,可以将变量本身视为缓冲区并传递它的地址(在这种情况下该地址是 &dl)。但是,在使用数组作为缓冲区时,只要传递数组就可以了,因为数组已经是一个地址。

如果正在写入的数据恰好是字符数据,则不需要使用这种转换。以下是一些写入字符数据的示例:

char ch = 'X';
char charArray[5] = "Hello";
outFile.write(&ch, sizeof(ch));
outFile.write(charArray, sizeof(charArray));

在 istream 和 ifstream 类中有一个read成员函数,它可以用来读取使用 write 写入的二进制数据。它釆用了两个形参,一个是字节读取后将要存储的缓冲区的地址,另外一个是要读取的字节数:

read(addressOfBuffer, numberOfBytes)

必须使用 reinterpret_cast 将缓冲区的地址解释为指向 char 的指针。可以通过调用输入流上的 fail() 成员函数来发现指定的字节数是否成功读取。

//This program uses the write and read functions.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    //File object used to access file
    fstream file("nums.dat", ios::out | ios::binary);
    if (!file)
    {
        cout << "Error opening file.";
        return 0;
    }
    //Integer data to write to binary file
    int buffer[ ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int size = sizeof(buffer) / sizeof(buffer[0]);
    // Write the data and close the file
    cout << "Now writing the data to the file.\n";
    file.write(reinterpret_cast<char *>(buffer), sizeof(buffer));
    file.close ();
    // Open the file and use a binary read to read contents of the file into an array
    file.open("nums.dat", ios::in);
    if (!file)
    {
        cout << "Error opening file.";
        return 0;
    }
    cout << "Now reading the data back into memory.\n";
    file.read(reinterpret_cast<char *>(buffer), sizeof (buffer));
    // Write out the array entries
    for (int count = 0; count < size; count++)
        cout << buffer[count] << " ";
    // Close the file
    file.close ();
    return 0;
}

http://c.biancheng.net/view/1538.html

https://blog.csdn.net/nichengwuxiao/article/details/78789225 

https://blog.csdn.net/wjw8128/article/details/53367018

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值