文件访问
变量、数组都是存储在内存(RAM)中的,这些数据所占用的内存在程序结束以后会被操作系统回收,其中的数据也就丢失了。因此我们需要将数据保存到外部存储器上(通常为硬盘),便于下次使用。
在一些较为底层的语言里,你可以直接访问硬盘的某个扇区并进行数据读写,但这种方式一般不被推荐,因为这种方式除了效率比较低下外还存在较大的危险性,不恰当的磁盘访问可能会引起严重的故障(例如操作系统崩溃或数据丢失)。
因此我们通常是通过文件来访问磁盘上的数据,文件系统由操作系统管理,程序员通过操作系统间接地访问磁盘上的数据,不恰当的文件访问会被操作系统阻止(例如文件被其他程序占用、或程序没有访问这个文件的权限),这样一来就安全得多,同时操作系统也会采取一些机制来提高文件访问的效率。
使用fopen函数打开或创建文件
要将数据保存到磁盘文件,首先需要创建文件;一个文件如果之前已经创建,则需要打开它(有时是直接覆盖它,取决于你打开它的方式)。在C语言中创建和打开文件都使用一个函数———fopen函数,fopen函数的原型是:
FILE* fopen(const char* filename, const char* mode);
可以看到———fopen函数使用了两个参数,第一个参数是filename,它是一个字符串常量。第二个参数也是一个字符串,它的作用是决定打开这个文件的方式。
以下是fopen函数使用的一个例子:
FILE* fp = fopen("D:\\Data\\Test.txt", "W");
"D:\Data\Test.txt"表示D盘Data目录下的Test.txt文件,之所以是两个斜杠而不是一个,是因为斜杠在字符串中有特殊作用———与其他一些字符组成转义符,例如'\n'表示换行符,'\t'表示制表符,因此单个斜杠在字符串中需要使用斜杠的转义符\来表示。
fopen函数的打开方式
fopen函数的第二个参数用于表示打开文件的方式,可以根据程序的需求决定使用哪种方式;例如,只想读取文件中的数据的话,“只读”权限就够了;既想读取又想写入数据的话,“读写”权限就是必须的了。另外,文件也有不同的类型,按照数据的存储方式可以分为二进制文件和文本文件,它们的操作细节是不同的。在调用 fopen() 函数时,这些信息都必须提供,称为“文件打开方式”。最基本的文件打开方式有以下几种:
调用 fopen() 函数时必须指明读写权限,但是可以不指明读写方式(此时默认为"t")。
读写权限和读写方式可以组合使用,但是必须将读写方式放在读写权限的中间或者尾部(换句话说,不能将读写方式放在读写权限的开头)。例如:
将读写方式放在读写权限的末尾:"rb"、"wt"、"ab"、"r+b"、"w+t"、"a+t"
将读写方式放在读写权限的中间:"rb+"、"wt+"、"ab+"
整体来说,文件打开方式由 r、w、a、t、b、+ 六个字符拼成,各字符的含义是:
r(read):读
w(write):写
a(append):追加
t(text):文本文件
b(banary):二进制文件
+:读和写
关闭文件
文件一旦使用完毕,应该用fclose()函数把文件关闭,以释放相关资源,避免数据丢失。fclose()的用法为:
int fclose(FILE *fp);
fp 为文件指针。例如:
fclose(fp);
文件正常关闭时,fclose()的返回值为0,如果返回非零值则表示有错误发生。
实例
最后,我们通过一段完整的代码来演示 fopen 函数的用法,这个例子会一行一行地读取文本文件的所有内容:
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main() {
FILE *fp;
char str[N + 1];
//判断文件是否打开失败
if ( (fp = fopen("E:\\DATA\\demo.txt", "rt")) == NULL ) {
puts("Fail to open file!");
exit(0);
}
//循环读取文件的每一行数据
while( fgets(str, N, fp) != NULL ) {
printf("%s", str);
}
//操作结束后关闭文件
fclose(fp);
return 0;
}
图片处理
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
typedef struct BitMapHeader
{
long Size;//文件大小
short Reserved1;//保留字,不考虑
short Reserved2;//保留字,同上
long OffBits;//实际位图数据的偏移字节数,即前三个部分长度之和
}BIT_MAP_HEADER;
//信息头BITMAPHEADER,也是一个结构体,其定义如下:
typedef struct BitMapInfo
{
long Size; //指定此结构体的长度,为40
long Width; //位图宽
long Height; //位图高
short Planes; //平面数,为1
short BitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
long Compression; //压缩方式,可以是0,1,2,其中0表示不压缩
long SizeImage; //实际位图数据占用的字节数
long XPelsPerMeter; //X方向分辨率
long YPelsPerMeter; //Y方向分辨率
long ClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
long ClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的
} BIT_MAP_INFO;
int main()
{
FILE* fp = fopen("E:\\DATA\\tx.bmp", "rb");
char tag[2];
fread(tag,2, 1, fp);
if (tag[0] != 'B' || tag[1] != 'M')
{
printf("图片读取错误,这不是一个BMP文件");
return -1;
}
BIT_MAP_HEADER bmpHrader;
fread(&bmpHrader, sizeof(bmpHrader), 1, fp);
BIT_MAP_INFO bmpInfo;
fread(&bmpInfo, sizeof(bmpInfo), 1, fp);
printf("这个图片的宽度是:%d\n", bmpInfo.Width);
printf("这个图片的高度是:%d\n", bmpInfo.Height);
initgraph(bmpInfo.Width, bmpInfo.Height);
unsigned char data[3];
for (int y = bmpInfo.Height - 1; y >= 0; y--)
{
for (int x = bmpInfo.Width - 1; x >= 0; x--)
{
fread(data, 3, 1, fp);
int b = data[0];
int g = data[1];
int r = data[2];
putpixel(x, y, RGB(r,g,b));
}
}
getch();
closegraph();
return 0;
}
版权属于:KrisWi
本文链接:http://7k.cx:83/index.php/archives/66/
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。