从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。
ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式为:
ASC码: 00110101 00110110 00110111 00111000
↓ ↓ ↓ ↓
十进制码: 5 6 7 8 共占用4个字节。ASCII码文件可在屏幕上按字符显示, 例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。 由于是按字符显示,因此能读懂文件内容。
二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678的存储形式为: 00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示,但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。
因此,文件的打开方式也分为以文本方式和二进制方式打开:
举个例子,一个32位数字0x0000200十进制数512,可以以两种方式存在文件中。第一种是人易读的方式"512",存储3个 字符,每个字符按ASCII码存放,这样用一个文本编辑器打开,人可以容易的读到这个数是512。 第二种方式是以机器易读的方式直接存储4个字节一个32位的00 00 02 00,这样机器容易读取这个数是512,直接内存拷贝就可以。 否则机器就要首先将"512"读每一个字符, 然后将"5"这个字符的ASCII码转换成5, 最后执行一个5*100+1*10+2才能得到512这个数。fwrite和fread都是机器易读的方式。 从文件中将00 00 02 00读入一个int类型变量,用fread写就是
fread(&a, sizeof(int), 1, fp);
即从文件中读取一个大小为sizeof(int)的内容到内存地址&a。
相应的fwrite形式是
fwrite(&a, sizeof(int), 1, fp);
若文件中存储的是人易读的形式比如 “512 ”,那么要处理就最好使用fscanf和fprintf。
对于fgetc函数的使用有以下几点说明:
1. 在fgetc函数调用中,读取的文件必须是以读或读写方式打开的。
2. 读取字符的结果也可以不向字符变量赋值,例如:fgetc(fp);但是读出的字符不能保存。
3. 在文件内部有一个位置指针。用来指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc 函数后,该位置指针将向后移动一个字节。 因此可连续多次使用fgetc函数,读取多个字符。应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统自动设置的。
用fopen打开一个文本文件,fopen的第一个参数为文件路和文件名,第二个参数定义的是打开文件的方式,执行完fopen后,需要判断一下,此文件是否确实被打开了。
if(NULL == fd)printf("文件未被打开");
接下来就可以进行文件的操作了。
读文件的函数有好几个,fread,fscanf,fgets。它们之间是有区别的:
fread是以块的方式来读取数据,按照指定的长度和指定的次数来读,读完后的数据是按照地址的方式来存储的,所以,比较适合用它来读二进制数,因为程序员比较清楚的知道自己要读多少的数据。
fgets是以串的方式来读取数据,从数据文件中读取不超过N-1个字符的数,读入的数据在最后一个字符后会加上一个截止符'\n',如果中间出现了回车,就会截止了。所以可以用fgets来读入一行的文本数据,应该是相当好用的。
fscanf与fgets类似,不过它是按照格式来读的,跟scanf一样。比如说,指定一个%d,那么它就读入一个整型的值;如果指定一个%s,那么它遇到一个空格也会停止的。
以下是一个实际的代码,用三种方式来完成文件的读取。
#include <stdio.h>
int main()
{
FILE *fd;
char buf[64];
fd = fopen("txtfile.txt","rb");
if(NULL == fd)
{
printf("read file error!");
return 0;
}
printf("read file success!\n");
while(!feof(fd))
{
/*method 1
fgets(buf,64,fd);
printf("%s\n",buf);
*/
/*method 2
fread(buf,64,1,fd);
printf("the %dth time: %s \n ",count,buf);
*/
fscanf(fd,"%s",buf);
printf("%s\n",buf);
}
fclose(fd);
return 1;
}
<span style="font-size:18px;">标准C++ 读文件内容</span>
<pre name="code" class="cpp">//标准C++ 读文件内容 ( 仿PHP ) 2012-8-12 by Dewei
//用法:string s = file_get_contents("C:\\LICENSE.txt");
string file_get_contents(const string &filename)
{
string contents = "";
fstream in;
in.open(filename.c_str(), fstream::in|fstream::binary|fstream::ate);
if (in.good()) {
fstream::pos_type end_pos = in.tellg();
long num_size = end_pos;
++num_size;
in.seekg (0, fstream::beg);
char *buffer = new char[num_size];
memset(buffer, 0, num_size);
in.read(buffer, end_pos);
in.close();
contents = buffer;
if (buffer != NULL)
delete[] buffer;
}
return contents;
}
//标准C++ 写入文件内容 ( 仿PHP ) 2012-8-12 by Dewei
//用法:file_put_contents("C:\\LICENSE.txt", "写入内容");
bool file_put_contents(const string &filename, const string contents)
{
fstream out;
out.open(filename.c_str(), fstream::out|fstream::binary);
if (out.good()) {
out.write(contents.c_str(), contents.length());
out.close();
}
return true;
}
C 语言实现 读取文件内容
<pre name="code" class="cpp">//C 语言实现 读取文件内容 ( 仿PHP ) 2012-6-25 by Dewei
//用法:string s = file_get_contents("C:\\LICENSE.txt");
string file_get_contents(const string &filename)
{
string contents;
FILE *fp;
fp = fopen(filename.c_str() , "rb");
if (fp == NULL) {
return "";
}
fseek(fp, 0, SEEK_END);
int file_size = ftell(fp);
char *tmp;
fseek(fp, 0, SEEK_SET);
tmp = (char *)malloc(file_size+1);
memset(tmp, 0, file_size+1);
fread(tmp, sizeof(char), file_size, fp);
if (ferror(fp)) {
/* now, it is an error on fp */
}
fclose(fp);
contents = tmp;
free(tmp);
return contents;
}
//C 语言实现 写入文件内容 ( 仿PHP ) 2012-6-25 by Dewei
//用法:file_put_contents("C:\\LICENSE.txt", "写入内容");
bool file_put_contents(const string &filename, const string contents)
{
FILE *fp;
fp = fopen(filename.c_str() , "wb");
if (fp == NULL) {
return false;
}
fwrite(contents.c_str(), contents.length(), 1, fp);
fclose(fp);
return true;
}
c_str函数讲解
c_str函数的返回值是const char*的,不能直接赋值给char*,所以就需要我们进行相应的操作转化,下面就是这一转化过程。
c++语言提供了两种字符串实现,其中较原始的一种只是字符串的c语言实现。与C语言的其他部分一样,它在c++的所有实现中可用,我们将这种实现提供的字符串对象,归为c-串,每个c-串char*类型的。
标准头文件<cstring>包含操作c-串的函数库。这些库函数表达了我们希望使用的几乎每种字符串操作。 当调用库函数,客户程序提供的是string类型参数,而库函数内部实现用的是c-串,因此需要将string对象,转化为char*对象,而c_str()提供了这样一种方法,它返回const char*类型(可读不可改)的指向字符数组的指针。 例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string add_to = "hello!";
const string add_on = "baby";
const char *cfirst = add_to.c_str();
const char *csecond = add_on.c_str();
char *copy = new char[strlen(cfirst) + strlen(csecond) + 1];
strcpy(copy, cfirst);
strcat(copy, csecond);
add_to = copy;
cout << "copy: " << copy << endl;
delete [] copy;
cout << "add_to: " << add_to << endl;
//我强烈建议,以及我的老师也强烈建议我
//一定要用return 0; 来告诉系统:程序正常结束.
//return -1;是用来告诉系统:程序异常结束
// 亲们 ,做开发要认真~共勉~
//一定要用 int main()
return 0;
}
//以上程序过编译
//VC 6.0, win7, - -!兼容性差
——————
简单的例子:
函数声明:const char *c_str();
c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同.
这是为了与c语言兼容,在c语言中没有string类型,故必须通过 string 类对象 的 成员函数 c_str()把string 对象转换成c中的字符串样式。
注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针
比如:最好不要这样:
char* c;
string s="1234";
c = s.c_str();
//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理(纠正:s对象的析构是在对指针c完成赋值操作之后进行的,故此处并没有错误)
在vc++2010中提示的错误原因:
应该这样用:
char c[20];
string s="1234";
strcpy(c,s.c_str());
这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作
———再举个例子———
c_str() 以const char* 类型返回 string 内含的字符串
如果一个函数要求char*参数,可以使用c_str()方法:
string s = "Hello World!";
printf("%s", s.c_str()); //输出 "Hello World!"
——————
c_str在打开文件时的用处:
当需要打开一个由用户自己输入文件名的文件时,可以这样写:ifstream in(st.c_str());。其中st是string类型,存放的即为用户输入的文件名。