在之前的学习中,忘文件中写的内容都是字符串或字符,本节学习如何写入其他各种类型的数据。
回看write和read函数的形式:
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
其中,第二个参数都是一个无类型的指针,只不过之前一直将这里定义为一个字符串,其实,这个指针可以指向各种形式数据的地址。
写入一个整数
demo7.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd; // file description
int data = 100;
int data2 = 0;
fd = open("./file1",O_RDWR|O_CREAT|O_TRUNC, 0600);
printf("file description = %d, open successfully!\n",fd);
write(fd, &data, sizeof(int));
lseek(fd,0,SEEK_SET);
read(fd, &data2, sizeof(int));
printf("context:%d\n",data2);
close(fd); //close after writing
return 0;
}
运行代码:
注意,如果此时打开file1:(此时需要使用vi打开)
发现是乱码,但是这并不影响程序运行时的读取和写入。
写入一个结构体
demo7.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
struct Test
{
int i;
char c;
};
int main()
{
int fd; // file description
struct Test data = {30,'k'};
struct Test data2;
fd = open("./file1",O_RDWR|O_CREAT|O_TRUNC, 0600);
printf("file description = %d, open successfully!\n",fd);
write(fd, &data, sizeof(struct Test));
lseek(fd,0,SEEK_SET);
read(fd, &data2, sizeof(struct Test));
printf("data.i:%d,data.c=%c\n",data2.i,data2.c);
close(fd); //close after writing
return 0;
}
运行代码:
写入一个结构体数组
demo7.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
struct Test
{
int i;
char c;
};
int main()
{
int fd; // file description
struct Test data[2] = {{30,'k'},{100,'p'}};
struct Test data2[2];
fd = open("./file1",O_RDWR|O_CREAT|O_TRUNC, 0600);
printf("file description = %d, open successfully!\n",fd);
write(fd, &data, sizeof(struct Test)*2);
lseek(fd,0,SEEK_SET);
read(fd, &data2, sizeof(struct Test)*2);
printf("data[0].i:%d,data[0].c=%c\n",data2[0].i,data2[0].c);
printf("data[1].i:%d,data[1].c=%c\n",data2[1].i,data2[1].c);
close(fd); //close after writing
return 0;
}
运行代码:
写入一个链表
demo7.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
struct Test
{
int data;
struct Test *next;
};
int main()
{
int fd; // file description
struct Test head = {20,NULL};
struct Test node1 = {30,NULL};
struct Test node2 = {40,NULL};
head.next = &node1;
node1.next = &node2;
fd = open("./file1",O_RDWR|O_CREAT|O_TRUNC, 0600);
printf("file description = %d, open successfully!\n",fd);
write(fd, &head, sizeof(struct Test));
write(fd, &node1, sizeof(struct Test));
write(fd, &node2, sizeof(struct Test));
lseek(fd,0,SEEK_SET);
struct Test node_read_1 = {0,NULL};
struct Test node_read_2 = {0,NULL};
struct Test node_read_3 = {0,NULL};
read(fd, &node_read_1, sizeof(struct Test));
read(fd, &node_read_2, sizeof(struct Test));
read(fd, &node_read_3, sizeof(struct Test));
printf("no.1=%d\n",node_read_1.data);
printf("no.2=%d\n",node_read_2.data);
printf("no.3=%d\n",node_read_3.data);
close(fd);
return 0;
}
运行代码:
但是以上的代码有点笨,且容错性太低,首先读取和写入应该封装成函数,并且我认为通常在读取链表的时候,不一定知道链表有多少元素,所以应该一边用尾插法动态创建链表一边读取。
改进代码demo8.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
int data;
struct Test *next;
};
struct Test *insertBehind(struct Test *head, struct Test *new)
{
struct Test *p = head;
if(p == NULL){
head = new;
return head;
}
while(p->next != NULL){
p = p->next;
} //将p先移动到链表的尾部
p->next = new;
return head;
}
void writeLink2File(int fd,struct Test *p){
while(p != NULL){
write(fd, p, sizeof(struct Test));
p = p->next;
}
}
void readLinkFromFile(int fd,struct Test *head){
struct Test *new;
int size = lseek(fd,0,SEEK_END); //先计算文件大小
lseek(fd,0,SEEK_SET); //然后不要忘记把光标移到文件头
while(1){
new = (struct Test *)malloc(sizeof(struct Test));
read(fd, new, sizeof(struct Test));
printf("link data:%d\n",new->data);
if(lseek(fd,0,SEEK_CUR) == size){ //每次读取一个数据之后,动态创建下一个链表节点之前,都要判断“当前光标是否已经在文件尾”,如果是,说明读取已经完成
printf("read finish\n");
break;
}
head = insertBehind(head,new);
}
}
int main()
{
int fd; // file description
struct Test head = {20,NULL};
struct Test node1 = {30,NULL};
struct Test node2 = {40,NULL};
head.next = &node1;
node1.next = &node2;
fd = open("./file1",O_RDWR|O_CREAT|O_TRUNC, 0600);
printf("file description = %d, open successfully!\n",fd);
writeLink2File(fd,&head);
struct Test *head_recv = NULL; //准备创建一个新的链表用于接收
readLinkFromFile(fd,head_recv);
close(fd);
return 0;
}