1、什么是系统调用
所有的操作系统都提供多种服务的入口点,程序由此向内核请求服务。这些可直接进入内核的入口点被称为系统调用。
2、什么是文件
文件是系统资源(内存、硬盘、一般设备、进程间通信的通道等)的一个抽象。对系统资源进行访问的一个通用接口。普通文件
一般意义上的文件,作为数据存储在磁盘中,可以随机访问文件的内容。Linux系统中的文件是面向字节的,文件的内容以字节为单位进行存储和访问。目录
目录是一种特殊的文件,目录可以像普通文件一样打开、关闭以及进行相应的操作。管道
管道是Linux中的一种进程间通信的机制。设备文件
设备文件没有具体的内容,对设备文件的读写操作实际上与某个设备的输入输出操作关联在一起。符号链接
符号链接的内容是指向另一个文件的路径。当对符号链接进行操作时,系统会根据情况将这个操作转移到它所指向的文件上去,而不是对它本身进行操作。socket
socket也是一种进程间通信的方式,与管道不同的是,它们可以在不同的主机上进行通信,也就是网络通信。3、文件描述符
(1)所有执行I/O操作的系统调用使用文件描述符来表示打开的文件。(2)文件描述符是一个非负整数。
(3)文件描述符可以表示各种类型的打开的文件。
(4)对文件的操作只要使用文件描述符即可指定所操作的文件。
4、系统调用函数
(1) open()系统调用可以打开或创建一个文件。
头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main()
{
// 打开或创建一个文件
int fd = open("abc.c", O_RDONLY | O_CREAT, 0777);
if (fd == -1)
{
printf ("打开文件失败\n");
perror ("open");
printf ("%s\n", strerror(errno));
}
close(fd);
return 0;
}
(2)read()系统调用从打开的文件中读取数据。
头文件
#include <unistd.h>
函数原型
ssize_t read(int fd, void *buf, size_t count);
示例:
/* 读一个完整的数据,防止比如已经接近文件结尾,
或者正在从管道或者终端读取数据,或者 read()被信号中断
*/
int main()
{
int fd = open("Parking.c", O_RDONLY, 0777);
if (fd == -1)
{
perror ("open");
return -1;
}
char buf[SIZE] = {0};
char *p = buf;
int count = SIZE-1; // 每一次要读的数据个数
ssize_t ret = 0;
while (ret = read(fd, p, count))
{
if (ret == -1)
{
if (errno == EAGAIN || errno == EINTR)
{
continue;
}
break;
}
// 读完
if (count == ret)
{
printf ("文件读取结束\n");
break;
}
count -= ret; // 下次要读的数据
p += ret; // 将指针指向这次读到的数据的后一个字节
}
printf ("len = %d\n", strlen(buf));
return 0;
}
(3)write()系统调用向打开的文件写数据。
头文件
#include <unistd.h>
函数原型
ssize_t write(int fd, const void *buf, size_t count);
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define SIZE 1024
int main()
{
int fd = open("abc", O_WRONLY|O_CREAT, 0777);
if (fd == -1)
{
perror ("open");
return -1;
}
char buf[SIZE] = {0};
while(1)
{
fgets (buf, SIZE, stdin);
if (strncmp ("end", buf, 3) == 0)
break;
ssize_t ret = write(fd, buf, strlen(buf));
if (ret == -1)
{
perror ("write");
}
printf ("要写的字节数; %d, 实际写的字节数: %d\n", SIZE, ret);
}
close (fd);
return 0;
}
(4)close()系统调用关闭一个打开的文件。
头文件
#include <unistd.h>
函数原型
int close(int fd);
(5)lseek系统调用可以改变文件偏移量(File Offset)。文件偏移量是一个整数,表示距文件起始处的字节数。
头文件
#include <sys/types.h>
#include <unistd.h>
函数原型
off_t lseek(int fildes, off_t offset, int whence);
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd = open("abc", O_WRONLY | O_CREAT, 0777);
if (fd == -1)
{
perror ("open");
return -1;
}
char *buf = "Hello Word!";
// 设置偏移指针 20 个字节
lseek(fd, 20, SEEK_SET);
// 将缓存区内数据写入abc
write(fd, buf, strlen(buf));
close(fd);
return 0;
}
5、标准IO
(1)fopen用于打开一个标准I/O流
头文件
函数原型
"r"或"rb":以只读方式打开。
"w"或"wb":以只写方式打开,并把文件长度截短为零。
"a"或"ab":以写方式打开,新内容追加在文件尾。
"r+"或"rb+"或"r+b":以更新方式打开(读和写)。
"w+"或"wb+"或"w+b":以更新方式打开,并把文件长度截短为零。
"a+"或"ab+"或"a+b":以更新方式打开,新内容追加在文件尾。
#include <stdio.h>
函数原型
FILE *fopen(const char *path, const char *mode);
"w"或"wb":以只写方式打开,并把文件长度截短为零。
"a"或"ab":以写方式打开,新内容追加在文件尾。
"r+"或"rb+"或"r+b":以更新方式打开(读和写)。
"w+"或"wb+"或"w+b":以更新方式打开,并把文件长度截短为零。
"a+"或"ab+"或"a+b":以更新方式打开,新内容追加在文件尾。
注:字母b表示文件是一个二进制文件而不是文本文件。
示例:
#include <stdio.h>
int main()
{
FILE *fp = fopen("ab1", "ab+");
if (fp == NULL)
{
perror ("fopen");
return -1;
}
printf ("打开成功!\n");
return 0;
}
(2)fread()用于从一个文件流里读取数据。
头文件
函数原型
#include <stdio.h>
函数原型
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
示例:
#include <stdio.h>
#define SIZE 1024
int main()
{
FILE *fp = fopen("Parking.c", "ab+");
if (fp == NULL)
{
perror ("fopen");
return -1;
}
char buf[SIZE] = {0};
// feof 判断是否读到文件结尾,如果读到文件结尾,它返回一个非0 的值
int ret;
while (ret = fread(buf, sizeof(char), SIZE-1, fp))
{
buf[ret*sizeof(char)] = '\0';
printf ("%s\n", buf);
}
if (ret == 0 && !feof(fp))
{
perror ("fread");
return -1;
}
printf ("文件读取结束\n");
return 0;
}
(3) fwrite()从指定的数据缓冲区里取出数据记录,并把它们写到输出流中。它的返回值是成功写入的记录个数。
头文件
#include <stdio.h>
函数原型
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
示例:
#include <stdio.h>
#define SIZE 1024
int main()
{
FILE *fp1 = fopen("1.ppt", "ab+");
if (fp1 == NULL)
{
perror ("fopen fp1");
return -1;
}
FILE *fp2 = fopen("2.ppt", "ab+");
if (fp2 == NULL)
{
perror ("fopen fp2");
return -1;
}
char buf[SIZE] = {0};
// feof 判断是否读到文件结尾,如果读到文件结尾,它返回一个非0 的值
int ret;
while (ret = fread(buf, sizeof(char), SIZE-1, fp1))
{
fwrite(buf, sizeof(char), SIZE-1, fp2);
}
if (ret == 0 && !feof(fp1))
{
perror ("fread fp1");
return -1;
}
printf ("文件读取结束\n");
fclose(fp1);
fclose(fp2);
return 0;
}
(4)fclose()函数用于关闭指定的文件流。
头文件
#include <stdio.h>
函数原型
int fclose(FILE *fp);
(5)fseek()
用于在文件流里为下一次读写操作指定位置。
头文件
#include <stdio.h>
函数原型
int fseek(FILE *stream, long offset, int whence);
从文件流里取出下一个字节并把它作为一个字符返回。当它到达文件结尾或出现错误时,返回EOF。getc()和fgetc()一样,但它有可能被实现为一个宏。getchar()相当于getc(stdin)。
头文件
#include <stdio.h>
函数原型
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
(7)fputc()
把一个字符写到一个输出文件流中,它返回写入的值,如果失败,则返回EOF。类似fgetc()和getc(),putc()的作用也相当于fputc(),但它可能被实现为一个宏。putchar()相当于putc(c, stdout),它把单个字符写到标准输出。
头文件
#include <stdio.h>
函数原型
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
注意:putchar和getchar都是把字符当作int类型而不是char类型来使用的,这就允许文件结尾EOF取值为-1。
应用:数据读取
#include <stdio.h>
#define SIZE 1024
typedef struct student
{
int id;
char name[20];
}STU;
void write_data(STU *a, int len) // len为传过来的写入数据个数
{
FILE *fp = fopen("student", "w+");
if (fp == NULL)
{
perror ("fopen");
return;
}
// 要写入个数
fwrite(&len, sizeof(int), 1, fp);
int i;
for (i = 0; i < len; i++)
{
// 写入数据长度
int lenth = sizeof(a[i]);
fwrite(&lenth, sizeof(int), 1, fp);
// 写入数据
fwrite(&a[i], sizeof(STU), 1, fp);
}
fclose(fp);
}
void read_data()
{
FILE *fp = fopen("student", "ab+");
if (fp == NULL)
{
perror ("fopen");
return;
}
// 读记录的个数
int count;
fread (&count, sizeof(int), 1, fp);
printf ("记录个数是:%d\n", count);
int i;
STU tmp;
for (i = 0; i < count; i++)
{
int len;
fread (&len, sizeof(int), 1, fp);
// 读取数据
fread (&tmp, len, 1, fp);
printf ("id = %d, name = %s\n", tmp.id, tmp.name);
}
fclose(fp);
}
int main()
{
int i;
STU a[20];
for (i = 0; i < 20; i++)
{
a[i].id = i+1;
sprintf (a[i].name, "zhang%d", i+1);
}
int len = sizeof(a)/sizeof(a[0]);
//写入数据
write_data(a, len);
// 读数据
read_data();
return 0;
}