常见硬件设备所对应的文件
文件 | 硬件设备 |
---|
stdin | 标准输入文件,一般指键盘;scanf()、getchar() 等函数默认从 stdin 获取输入。 | stdout | 标准输出文件,一般指显示器;printf()、putchar() 等函数默认向 stdout 输出数据。 | stderr | 标准错误文件,一般指显示器;perror() 等函数默认向 stderr 输出数据(后续会讲到)。 | stdprn | 标准打印文件,一般指打印机。 |
- 文件是数据源的一种,除了文件,还有数据库、网络、键盘等;数据传递到内存也就是保存到C语言的变量(例如整数、字符串、数组、缓冲区等)。我们把数据在数据源和程序(内存)之间传递的过程叫做数据流(Data Stream)。相应的,数据从数据源到程序(内存)的过程叫做输入流(Input Stream),从程序(内存)到数据源的过程叫做输出流(Output Stream)。
- 输入输出(Input output,IO)是指程序(内存)与外部设备(键盘、显示器、磁盘、其他计算机等)进行交互的操作。几乎所有的程序都有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等。通过输入和输出操作可以从外界接收信息,或者是把信息传递给外界。
- 我们可以说,打开文件就是打开了一个流。
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main() {
FILE *fp;
char str[N + 1];
if ( (fp = fopen("d:\\demo.txt", "rt")) == NULL ) {
puts("Fail to open file!");
exit(0);
}
while( fgets(str, N, fp) != NULL ) {
printf("%s", str);
}
fclose(fp);
return 0;
}
文本文件和二进制文件的区别
根据我们以往的经验,文本文件通常用来保存肉眼可见的字符,比如.txt文件、.c文件、.dat文件等,用文本编辑器打开这些文件,我们能够顺利看懂文件的内容。 二进制文件通常用来保存视频、图片、程序等不可阅读的内容,用文本编辑器打开这些文件,会看到一堆乱码,根本看不懂。 但是从物理上讲,二进制文件和字符文件并没有什么区别,它们都是以二进制的形式保存在磁盘上的数据。 我们之所以能看懂文本文件的内容,是因为文本文件中采用的是 ASCII、UTF-8、GBK 等字符编码,文本编辑器可以识别出这些编码格式,并将编码值转换成字符展示出来。 而二进制文件使用的是 mp4、gif、exe 等特殊编码格式,文本编辑器并不认识这些编码格式,只能按照字符编码格式胡乱解析,所以就成了一堆乱七八糟的字符,有的甚至都没见过。
fopen() 中的文本方式和二进制方式
在C语言中,二进制方式很简单,读取文件时,会原封不动的读出文件的全部內容,写入数据时,也是把缓冲区中的內容原封不动的写到文件中。文本方式和二进制方式并没有本质上的区别,只是对于换行符的处理不同。 总起来说,对于 Windows 平台,为了保险起见,我们最好用"t" 来打开文本文件,用"b" 来打开二进制文件。对于 Linux 平台,使用"r" 还是"b" 都无所谓,既然默认是"r" ,那我们什么都不写就行了。
字符形式
#include<stdio.h>
int main(){
FILE *fp;
char ch;
if( (fp=fopen("D:\\demo.txt","rt")) == NULL ){
puts("Fail to open file!");
exit(0);
}
while( (ch=fgetc(fp)) != EOF ){
putchar(ch);
}
putchar('\n');
if(ferror(fp)){
puts("读取出错");
}else{
puts("读取成功");
}
fclose(fp);
return 0;
}
#include<stdio.h>
int main(){
FILE *fp;
char ch;
if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){
puts("Fail to open file!");
exit(0);
}
printf("Input a string:\n");
while ( (ch=getchar()) != '\n' ){
fputc(ch,fp);
}
fclose(fp);
return 0;
}
字符串形式
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main(){
FILE *fp;
char str[N+1];
if( (fp=fopen("d:\\demo.txt","rt")) == NULL ){
puts("Fail to open file!");
exit(0);
}
while(fgets(str, N, fp) != NULL){
printf("%s", str);
}
fclose(fp);
return 0;
}
将下面的内容复制到 D:\\demo.txt:
C语言中文网
http:
一个学习编程的好网站!
#include<stdio.h>
int main(){
FILE *fp;
char str[102] = {0}, strTemp[100];
if( (fp=fopen("D:\\demo.txt", "at+")) == NULL ){
puts("Fail to open file!");
exit(0);
}
printf("Input a string:");
gets(strTemp);
strcat(str, "\n");
strcat(str, strTemp);
fputs(str, fp);
fclose(fp);
return 0;
}
运行程序,输入C C++ Java Linux Shell,打开 D:\\demo.txt,文件内容为:
C语言中文网
http:
一个学习编程的好网站!
C C++ Java Linux Shell
数据块形式
#include<stdio.h>
#define N 5
int main(){
int a[N], b[N];
int i, size = sizeof(int);
FILE *fp;
if( (fp=fopen("D:\\demo.txt", "rb+")) == NULL ){
puts("Fail to open file!");
exit(0);
}
for(i=0; i<N; i++){
scanf("%d", &a[i]);
}
fwrite(a, size, N, fp);
rewind(fp);
fread(b, size, N, fp);
for(i=0; i<N; i++){
printf("%d ", b[i]);
}
printf("\n");
fclose(fp);
return 0;
}
运行结果:
23 409 500 100 222↙
23 409 500 100 222
#include<stdio.h>
#define N 2
struct stu{
char name[10];
int num;
int age;
float score;
}boya[N], boyb[N], *pa, *pb;
int main(){
FILE *fp;
int i;
pa = boya;
pb = boyb;
if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
puts("Fail to open file!");
exit(0);
}
printf("Input data:\n");
for(i=0; i<N; i++,pa++){
scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);
}
fwrite(boya, sizeof(struct stu), N, fp);
rewind(fp);
fread(boyb, sizeof(struct stu), N, fp);
for(i=0; i<N; i++,pb++){
printf("%s %d %d %f\n", pb->name, pb->num, pb->age, pb->score);
}
fclose(fp);
return 0;
}
运行结果:
Input data:
Tom 2 15 90.5↙
Hua 1 14 99↙
Tom 2 15 90.500000
Hua 1 14 99.000000
C语言fscanf和fprintf函数的用法
#include<stdio.h>
#define N 2
struct stu{
char name[10];
int num;
int age;
float score;
} boya[N], boyb[N], *pa, *pb;
int main(){
FILE *fp;
int i;
pa=boya;
pb=boyb;
if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){
puts("Fail to open file!");
exit(0);
}
printf("Input data:\n");
for(i=0; i<N; i++,pa++){
scanf("%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score);
}
pa = boya;
for(i=0; i<N; i++,pa++){
fprintf(fp,"%s %d %d %f\n", pa->name, pa->num, pa->age, pa->score);
}
rewind(fp);
for(i=0; i<N; i++,pb++){
fscanf(fp, "%s %d %d %f\n", pb->name, &pb->num, &pb->age, &pb->score);
}
pb=boyb;
for(i=0; i<N; i++,pb++){
printf("%s %d %d %f\n", pb->name, pb->num, pb->age, pb->score);
}
fclose(fp);
return 0;
}
运行结果:
Input data:
Tom 2 15 90.5↙
Hua 1 14 99↙
Tom 2 15 90.500000
Hua 1 14 99.000000
- 如果将 fp 设置为 stdin,那么 fscanf() 函数将会从键盘读取数据,与 scanf 的作用相同;设置为 stdout,那么 fprintf() 函数将会向显示器输出内容,与 printf 的作用相同。
#include<stdio.h>
int main(){
int a, b, sum;
fprintf(stdout, "Input two numbers: ");
fscanf(stdin, "%d %d", &a, &b);
sum = a + b;
fprintf(stdout, "sum=%d\n", sum);
return 0;
}
运行结果:
Input two numbers: 10 20↙
sum=30
C语言rewind和fseek函数
#include<stdio.h>
#define N 3
struct stu{
char name[10];
int num;
int age;
float score;
}boys[N], boy, *pboys;
int main(){
FILE *fp;
int i;
pboys = boys;
if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
printf("Cannot open file, press any key to exit!\n");
getch();
exit(1);
}
printf("Input data:\n");
for(i=0; i<N; i++,pboys++){
scanf("%s %d %d %f", pboys->name, &pboys->num, &pboys->age, &pboys->score);
}
fwrite(boys, sizeof(struct stu), N, fp);
fseek(fp, sizeof(struct stu), SEEK_SET);
fread(&boy, sizeof(struct stu), 1, fp);
printf("%s %d %d %f\n", boy.name, boy.num, boy.age, boy.score);
fclose(fp);
return 0;
}
运行结果:
Input data:
Tom 2 15 90.5↙
Hua 1 14 99↙
Zhao 10 16 95.5↙
Hua 1 14 99.000000
C语言实现文件复制功能
#include <stdio.h>
#include <stdlib.h>
int copyFile(char *fileRead, char *fileWrite);
int main(){
char fileRead[100];
char fileWrite[100];
printf("要复制的文件:");
scanf("%s", fileRead);
printf("将文件复制到:");
scanf("%s", fileWrite);
if( copyFile(fileRead, fileWrite) ){
printf("恭喜你,文件复制成功!\n");
}else{
printf("文件复制失败!\n");
}
return 0;
}
int copyFile(char *fileRead, char *fileWrite){
FILE *fpRead;
FILE *fpWrite;
int bufferLen = 1024*4;
char *buffer = (char*)malloc(bufferLen);
int readCount;
if( (fpRead=fopen(fileRead, "rb")) == NULL || (fpWrite=fopen(fileWrite, "wb")) == NULL ){
printf("Cannot open file, press any key to exit!\n");
getch();
exit(1);
}
while( (readCount=fread(buffer, 1, bufferLen, fpRead)) > 0 ){
fwrite(buffer, readCount, 1, fpWrite);
}
free(buffer);
fclose(fpRead);
fclose(fpWrite);
return 1;
}
运行结果:
要复制的文件:d:
将文件复制到:d:
恭喜你,文件复制成功!
C语言获取文件大小(长度)
long fsize(FILE *fp){
long n;
fpos_t fpos;
fgetpos(fp, &fpos);
fseek(fp, 0, SEEK_END);
n = ftell(fp);
fsetpos(fp,&fpos);
return n;
}
在windows平台下
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
long fsize(FILE *fp);
int main(){
long size = 0;
FILE *fp = NULL;
char filename[30] = "D:\\1.mp4";
if( (fp = fopen(filename, "rb")) == NULL ){
printf("Failed to open %s...", filename);
getch();
exit(EXIT_SUCCESS);
}
printf("%ld\n", fsize(fp));
return 0;
}
long fsize(FILE *fp){
long n;
fpos_t fpos;
fgetpos(fp, &fpos);
fseek(fp, 0, SEEK_END);
n = ftell(fp);
fsetpos(fp,&fpos);
return n;
}
C语言插入、删除、更改文件内容
文件复制函数
long fcopy(FILE *fSource, long offsetSource, long len, FILE *fTarget, long offsetTarget){
int bufferLen = 1024*4;
char *buffer = (char*)malloc(bufferLen);
int readCount;
long nBytes = 0;
int n = 0;
int i;
fseek(fSource, offsetSource, SEEK_SET);
fseek(fTarget, offsetTarget, SEEK_SET);
if(len<0){
while( (readCount=fread(buffer, 1, bufferLen, fSource)) > 0 ){
nBytes += readCount;
fwrite(buffer, readCount, 1, fTarget);
}
}else{
n = (int)ceil((double)((double)len/bufferLen));
for(i=1; i<=n; i++){
if(len-nBytes < bufferLen){ bufferLen = len-nBytes; }
readCount = fread(buffer, 1, bufferLen, fSource);
fwrite(buffer, readCount, 1, fTarget);
nBytes += readCount;
}
}
fflush(fTarget);
free(buffer);
return nBytes;
}
fcopy(fSource, 0, -1, fTarget, 0);
文件内容插入函数
int finsert(FILE *fp, long offset, void *buffer, int len){
long fileSize = fsize(fp);
FILE *fpTemp;
if(offset>fileSize || offset<0 || len<0){
return -1;
}
if(offset == fileSize){
fseek(fp, offset, SEEK_SET);
if(!fwrite(buffer, len, 1, fp)){
return -1;
}
}
if(offset < fileSize){
fpTemp = tmpfile();
fcopy(fp, 0, offset, fpTemp, 0);
fwrite(buffer, len, 1, fpTemp);
fcopy(fp, offset, -1, fpTemp, offset+len);
freopen(FILENAME, "wb+", fp );
fcopy(fpTemp, 0, -1, fp, 0);
fclose(fpTemp);
}
return 0;
}
文件内容删除函数
int fdelete(FILE *fp, long offset, int len){
long fileSize = getFileSize(fp);
FILE *fpTemp;
if(offset>fileSize || offset<0 || len<0){
return -1;
}
fpTemp = tmpfile();
fcopy(fp, 0, offset, fpTemp, 0);
fcopy(fp, offset+len, -1, fpTemp, offset);
freopen(FILENAME, "wb+", fp );
fcopy(fpTemp, 0, -1, fp, 0);
fclose(fpTemp);
return 0;
}
|