文本文件与二进制文件的读写
【https://wenku.baidu.com/view/d7dfd688680203d8ce2f243c.html】
以什么模式打开文件根本不重要,只要关心这个文件里的数据内容本身是二进制格式还是文本格式就好了!如果内容是文本格式的,你就调用文本格式那一套函数,比如puts,gets,fscanf,fprintf,<<,>>等,如果内容是二进制格式的,你就调用二进制格式那一套函数,比如fread,fwrite,ifstream.read(),ofstream.write()等。 保持文件内容与处理函数相对应。
【http://blog.csdn.net/songjinshi/article/details/7789584】
有数据要存储的时候.首先得考虑你要存储的数据是字符数据还是非字符数据,再来判断选择用二进制文件还是文本文件来进行存储。(字符数据放在文本/二进制文件中,都和内存中的数据形式没有区别)
【http://www.cnblogs.com/pengwangguoyh/articles/3223072.html】
C的文本方读写与二进制读写的差别仅仅体现在回车换行符的处理上.文本方式写时,每遇到一个''\n''(0AH换行符),它将其换成''\r\n''(0D0AH,回车换行),然后再写入文件;当文本读取时,它每遇到一个''\r\n''将其反变化为''\n'',然后送到读缓冲区.正因为文本方式有''\n''--''\r\n''之间的转换,其存在转换耗时.二进制读写时,其不存在任何转换,直接将写缓冲区中数据写入文件.
文本文件中的每个字节的最高位都是0,使用了一个字节中的七位来表示所有的信息,而二进制文件则是将字节中的8位。不管是二进制文件也好,还是文本文件也好,都是一连串的0和1,但是打开方式不同,对于这些0和1的处理也就不同。如果按照文本方式打开,就会将每个字节转换成ASCII码,而以按照二进制方式打开的话,则不会进行任何的translate;最后就是文本文件和二进制文件在编辑的时候,使用的方式也是不同的。譬如,你在记事本中进行文本编辑的时候,你进行编辑的最小单位是字节(byte);而对二进制文件进行编辑的话,最小单位则是位(bit),当然我们都不会直接通过手工的方式对二进制文件进行编辑了
数据存储在二进制文件中是二进制编码形式。
文本文件
1. 读入文本文件txt
①打开文件(关联一个文件流,使用open或直接打开,可选择各种打开方式)
ifstream infile;
infile.open("1.txt");// the same as:infile.open("1.txt",ios::in|ios::out,0);
//ifstream infile("1.txt", ios::in);
②判断打开是否成功
assert(infile.is_open());
//if (infile.good()) { } or if (infile) { }
③按要求读取数据
//按行读取——getline
string s;
while (getline(infile,s))
{
cout<< s<< endl;
}
//按字符读取【用>>写入;get读入,其中get可以控制格式,如while(fin.get(c,80,'/0')!=NULL)】
char c;
//infile >> noskipws;//加上此句则读入空格与回车
while (!infile.eof())
{
infile>> c;// while ((c = infile.get()) != EOF)
cout<<c<< endl;
}
system("pause");
④关闭文件
infile.close();
2. 写入文本文件txt(用<<写入)
ofstream f1("111.txt");
if (!f1)return;
f1 <<"姓名:"<<"xxx"<< endl;
f1.close();
二进制文件
用fstream类或者CFile类都可以,需注意相关函数的差别。二进制写入,任何类型都要转换成char*,读取时相应解码。字符串处理时要注意,二进制形式没有结束符,读取一般都读入char数组中。
①用fstream类:
1. 读取
ifstream fin("a.dat",ios::binary);//要以二进制打开
fin.read(char*,sizeof);
//如果是整形需转成(char*)//int nNum1;fin.read((char*)&nNum1, sizeof(int));
//如果是字符串//char szBuf[256] = { 0 };fin.read(szBuf,sizeof(char) * 256);
【事先不知道要读入的文件的类型和大小??】
fin.close();
用FILE打开【fseek确定文件的大小】 //只能正确显示字符串,int ,double都不行
FILE * f = fopen("a.dat","rb");
if (f)
{
fseek(f,0, SEEK_END);
int size = ftell(f);
char * buf =newchar[size];
fseek(f,0, SEEK_SET);
memset(buf,0, size);
int nRead = fread(buf,sizeof(char), size, f);
fclose(f);
if (nRead > 0)
{
for (unsignedint i = 0; i <nRead;i++)
{
cout<< buf[i];
}
}
}
2. 写入:
ofstream fout("a.dat",ios::binary);
fout.write(char*,sizeof);
//int nNum = 20; fout.write((char*)&nNum, sizeof(int));
//string str("Hello, world"); fout.write(str.c_str(), sizeof(char) *(str.size()));
fout.close();
写入换行符
string s0 ="\n\r";
fout.write(s0.c_str(),sizeof(char) * (s0.size()));
【文本文件:换行符\n 二进制文件:换行符\r\n】
3. 判断是否成功打开
if(!fin.is_open()) //或者
{
cout << "Error InOpen..." << endl;
return -1;
}
判断是否到达文件尾:
if(in.eof()) ShowMessage("已经到达文件尾!");
随机读写操作:
file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节
file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节
【seekp(绝对位置);seekp(相对位置,参照位置);seekg类似】
tellg();//返回当前指针位置 tellp();//返回当前指针位置
参照位置:ios::beg= 0 //相对于文件头
ios::cur= 1 //相对于当前位置
ios::end= 2 //相对于文件尾
4. 拷贝二进制文件【read+write】
ifstream fin("1.txt",ios::binary);
if (!fin) {
cout<<"File open error!/n";
return;
}
ofstream fout("2.txt",ios::binary);
char c[1024];
while (!fin.eof())
{
fin.read(c,1024);//read()从文件中读取 *字符到指向的缓存
fout.write(c,fin.gcount());// 从缓存写字符到文件中,gcount统计真正的个数
}
fin.close();
fout.close();
cout <<"Copy over!/n";
②用CFile类:(类似,操作函数不太一样)
提速:利用指针和结构体读取数据块
例子:如图示,100个一组,自定义结构体
#include <string>
#define NUM 1000
typedef struct _STL_BIN_DATA_
{
floatx;
intn;
} STL_BIN_DATA;
typedef struct _STL_BIN_DATA0_
{
chara[12];
STL_BIN_DATAb[100];
} STL_BIN_DATA0;
int main()
{
/write(一个个写入)
ofstreamfout("a.dat", ios::binary);
floatx1;
intn1;
intnum = NUM;
fout.write((char*)&num,sizeof(int));
stringstr("Hello,world!");
//ints_size = strlen(str.c_str());
fout.write(str.c_str(), sizeof(char) *(str.size()));
for(int i = 0;i < NUM;i++) {
if(i!=0&& i%100==0){
fout.write(str.c_str(),sizeof(char) * (str.size()));
}
x1 = i+0.1;
fout.write((char*)&x1,sizeof(float));
n1= i;
fout.write((char*)&n1,sizeof(int));//可以利用结构体写
}
fout.close();
/read
CFiletfile;
CStringfName = { "E:\\project\\my_test\\test\\test\\test\\a.dat" };
//tfile.Open(fName,CFile::typeBinary);
if(!tfile.Open(fName, CFile::typeBinary))
{
return-1;
}
clock_tcend, cstart;
cstart= clock();
//1.利用指针,一次性读入(pbt),再按结构体强制转换(pbd)(4619ms)
STL_BIN_DATA0z[NUM/100];
tfile.Read((char*)&num,sizeof(int));
//cout<< num<<endl;
intp = tfile.GetPosition();
inttsize = (int)tfile.GetLength();
tsize-= p;
STL_BIN_DATA0*pbd;
byte*pbt;
pbt = (byte *)malloc(tsize);
tfile.Read(pbt,tsize);//一次性读入
for(int i = 0; i < NUM/100; i++)
{
pbd= (STL_BIN_DATA0 *)(pbt+i*812);//每个结构体的长度是多少
for(int k = 0;k < 12;k++) {
z[i].a[k]= pbd->a[k];
//cout<< z[i].a[k];
}
//cout<< endl;
for(int j = 0;j < 100;j++) {
z[i].b[j]= pbd->b[j];
//cout<< z[i].b[j].x <<" "<< z[i].b[j].n << endl;
}
}
///2. 按结构体读入(4659ms)
STL_BIN_DATA0 z[NUM / 100];
tfile.Read((char*)&num, sizeof(int));
// cout << num << endl;
for (int i = 0; i < NUM/100; i++)
{
tfile.Read((char*)&(z[i]),sizeof(STL_BIN_DATA0));
//char cc[13];
//cc[12]= '\0';
//for(int k=0;k<12;k++)
//cc[k] = z[i].a[k];
//cout << cc<< endl; //注意要加结束符,否则输出的内容有些错误,但a的内容正确
//for(int j=0;j<100;j++)
//cout << z[i].b[j].x <<" " << z[i].b[j].n << endl;
}
3.分别转换读入 (4456ms)
char szBuf[13] = { 0 };
szBuf[12] ='\0';
tfile.Read((char*)&num, sizeof(int));
cout << num<<endl;
for (int i = 0; i < NUM; i++)
{
if ( i % 100 == 0) {
tfile.Read(szBuf, 12);
string s(szBuf);
cout << s<< endl;
}
tfile.Read((char*)&(x1),sizeof(float));
tfile.Read((char*)&(n1),sizeof(int));
cout <<x1 << " "<<n1 << endl;
}
cend = clock();
cout << cend - cstart;
system("pause");
tfile.Close();
return 0;
}
参考:http://blog.csdn.net/hlylivy123/article/details/4458130
https://baike.so.com/doc/5444731-5683090.html
补充:别人的快速读取的代码,我也自己试过啦
【ImportPart.h】
#define AFX_IMPORTEXPORT_H__BAA02E6B_A948_11D1_8DA6_0800369C8A03__INCLUDED_
#pragma once
#endif // _MSC_VER >= 1000
#include <list>
typedef struct _STL_BINFILE_HEAD_
{
byte head[80];
UINT DataCount;
} STL_BINFILE_HEAD;
{
float Normalvector[3];
float Vertex1[3];
float Vertex2[3];
float Vertex3[3];
//WORD Attributebytecountend;
} STL_BIN_DATA;
{
};
{
float nx1, ny1, nz1, nx2, ny2, nz2, nx3, ny3, nz3;
};
class CImportPart
{
public:
CImportPart(void);
virtual ~CImportPart(void);
bool nBuffer;
int nTr[100];
int nCount;
std::vector<Normal> Nor3[100];
};
#include "StdAfx.h"
#include "ImportPart.h"
{
nCount = 0;
IsImport = false;
nBuffer = false;
}
CImportPart::~CImportPart(void)
{
}
{
CFile tfile;
char tbuf[100];
Normal nV;
Vec3[nCount].clear();
Nor3[nCount].clear();
{
//AfxMessageBox(L"Fail to open the stl file!");
return false;
}
{
tfile.Close();
return false;
}
tbuf[99] = 0;
int tsize = (int)tfile.GetLength();
if (strstr(_strupr(tbuf), "FACET") != NULL) //is acsii
{
char* lpBuf = new char[tsize];
tfile.Read(lpBuf,tsize);
istringstream fin(lpBuf);
{
if( strTmp1 == "facet")
{
fin >> strTmp2 >> nV.nx1 >> nV.ny1 >> nV.nz1;
nV.nx3 = nV.nx2 = nV.nx1;
nV.ny3 = nV.ny2 = nV.ny1;
nV.nz3 = nV.nz2 = nV.nz1;
fin >> strTmp1 >> strTmp2;
fin >> strTmp3 >> tV.x2 >> tV.y2 >> tV.z2;
fin >> strTmp3 >> tV.x3 >> tV.y3 >> tV.z3;
Vec3[nCount].push_back(tV);
}
}
nTr[nCount] = Nor3[nCount].size();
free(lpBuf);
tfile.Close();
}
else
{
STL_BINFILE_HEAD tstlhd;
STL_BIN_DATA *pbd;
byte *pbt;
UINT tReadLen;
tfile.Read(&tstlhd, sizeof(STL_BINFILE_HEAD));
nTr[nCount] = tstlhd.DataCount;
Vec3[nCount].reserve(tstlhd.DataCount);
Nor3[nCount].reserve(tstlhd.DataCount);
{
pbt = (byte *)malloc(tReadLen);
tfile.Read(pbt, tReadLen);
{
pbd = (STL_BIN_DATA *)(pbt + i*50);
// read normal coordinates
nV.nx1 = nV.nx2 = nV.nx3 = pbd->Normalvector[0];
nV.ny1 = nV.ny2 = nV.ny3 = pbd->Normalvector[1];
nV.nz1 = nV.nz2 = nV.nz3 = pbd->Normalvector[2];
tV.x1 = pbd->Vertex1[0];
tV.y1 = pbd->Vertex1[1];
tV.z1 = pbd->Vertex1[2];
tV.x2 = pbd->Vertex2[0];
tV.y2 = pbd->Vertex2[1] ;
tV.z2 = pbd->Vertex2[2];
tV.x3 = pbd->Vertex3[0];
tV.y3 = pbd->Vertex3[1];
tV.z3 = pbd->Vertex3[2];
Nor3[nCount].push_back(nV);
}
else
{
// AfxMessageBox(L"WARNNING!!!\nThe size of this file is more than 400M, Please choose a small one!");
}
free(pbt);
tfile.Close();
}
}