文件I/O操作

继学习进程

#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define BUFSIZE 1024  
#define MSG_STR "Hello World\n" 
#define cleanup 

int main(int argc, char*argv[])
{
  int    fd=-1; 
  int    rv=-1;
  char  buf[BUFSIZE];
fd=open("file.txt",O_RDWR|O_CREAT|O_TRUNC,0666); 
  if(fd<0)  

{

perror("Open/Create file test.txt failure");

return 0;

   } 

printf("Open file returned file descriptor [%d]\n", fd);

if((rv=write(fd,MSG_STR, strlen(MSG_STR)))<0)

{

printf("Write %d bytes into file failure: %s\n", rv, strerror(errno));

cleanup;


}

//memset(buf, 0, sizeof(buf));

if((rv=read(fd, buf, sizeof(buf)))<0)

{

printf ("Read data from file failure:%s\n", strerror(errno));

cleanup;

}

printf("Read %d bytes data from file : %s\n",rv, buf);

cleanup;

close(fd);

return 0;

}

三、文件I/O操作函数,open()函数
int open(const char *path, int oflag, .../&mode_t mode*/)
open()系统调用用来打开一个文件,并返回一个文件描述符(file description), 并且该文件描述符是当前进程最小、未使用的文件描述符数值。
参数:
path: 要打开的文件、设备的路径
oflag: 由多个选项进行“或”运算构造oflag参数 。

  • 必选: O_RDONLY (只读)、 O_WRONLY(只写)、 O_RDWR(读写)
  • 可选: O_APPEND 每次写时都追加到文件的尾端。
    O_CREAT 文件不存在则创建它,使用该选项需要第三个参数mode
    O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0;
    O_NONBLOCK 如果path是一个FIFO、块设备、字符特殊文件则此选项为文件的本次打开和后续的I/O操作
    设置非阻塞模式方式。
    O_EXEC、O_SEARCH、O_CLOEXEC、O_NOCTTY…
    mode: oflag带O_CREAT选项时可以用来创建文件,这时必须带该参数用来指定创建文件的权限模式,如066。 否则不
    需要。使用示例代码:
int fd; 
 fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666); 
 fd = open(“text.txt”, O_WRONLY|O_APPEND);

####creat()系统调用

int creat(const char *path,mode_t mode);

此函数用来创建一个新文件并返回其fd。它等价于
open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

####close()系统调用

int close(int fd);

该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,
内核将会自动关闭它所有打开的文件。

####write()系统调用

ssize_t write(int fd, const void *buf, size_t nbytes);

write()函数用来往打开的文件描述符fd指向的文件中写入buf指向的数据,其中nbytes指定要写入的数据大小。如果返回值
<0则说明写入出错,譬如尝试往一个只读的文件中写入则会抛错,错误的原因系统会保存到errno变量中去。如果>0则为实
际写入的数据大小。

####lseek()系统调用

off_t lseek(int fd, off_t offset, int whence);

我们在从文件里读出内容,或往文件写如内容的时候都有一个起始地址,这个起始地址就是当前文件偏移量,当我们对文件
进行读写的时候都会使文件偏移量往后偏移。这点就类似于我们打开记事本开始编辑文本时的光标,我们读或写入时从光标所在位置开始读写,每读写一个字节都会使光标往后偏移。通过lseek()这个函数我们可以调整文件偏移量的地址。
其中 whence 可以是以下三个值:
SEEK_SET 文件头
SEEK_CUR 当前位置
SEEK_END 文件尾
而offset就是相对于whence 的偏移量,譬如:
lseek(fd, 0, SEEK_SET); 将文件偏移量设置到了文件开始的第一个字节上;
lseek(fd, 0, SEEK_END); 将文件偏移量设置到文件最后一个字节上;
lseek(fd, -1, SEEK_END); 将文件偏移量设置到文件最后的倒数第一个字节上;
####read()系统调用

ssize_t read(int fd, void *buf, size_t nbytes);

read()函数用来从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去,最多不要超过nbytes个字节,这里
的nbytes一般是buf剩余的空间大小。如read成功,则返回实际读到的字节数(由nbytes或读到文件尾决定,其中EOF宏用
来判断是否到了文件尾),如果返回值小于0则表示出错,如尝试读一个没有权限读的文件时就会抛错。

####dup() 和 dup2()系统调用

int dup(int fd);
int dup2(int fd, int fd2);


这两个函数都可以用来复制一个新的文件描述符来指向fd对应的文件。这两个系统调用经常用在标准输入、标准输出、标准
出错重定向。
dup()返回的新文件描述符一定是当前可用文件描述符中的最小数值;
dup2可以用fd2参数来指定新的文件描述符。如果fd2已经打开,则先关闭。如fd等于fd2, 则dup2返回fd2, 而不关闭它。

####stat()和fstat()系统调用

int stat(const char * restrict path, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);


这两个函数都是用来返回文件或目录的相关信息,只是stat()的第一个参数是文件名,而fstat()的第一个参数是文件打开的相
应文件描述符。其中struct stat结构体的定义如下:

struct stat {
 dev_t st_dev; /* ID of device containing file */
 ino_t st_ino; /* inode number */
 mode_t st_mode; /* protection */
 nlink_t st_nlink; /* number of hard links */
 uid_t st_uid; /* user ID of owner */
 gid_t st_gid; /* group ID of owner */
 dev_t st_rdev; /* device ID (if special file) */
 off_t st_size; /* total size, in bytes */
 blksize_t st_blksize; /* blocksize for filesystem I/O */
 blkcnt_t st_blocks; /* number of 512B blocks allocated */
 time_t st_atime; /* time of last access */
 time_t st_mtime; /* time of last modification */
 time_t st_ctime; /* time of last status change */
 };

vim stat.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main (int argc, char **argv)
{
 struct stat stbuf;
 
 stat("stat.c", &stbuf);
 printf("File Mode: %o Real Size: %luB, Space Size: %luB\n", stbuf.st_mode, stbuf.st_size,
stbuf.st_blksize);
 
 return 0;
}

####access()系统调用

int access(const char *path, int mode);

access()可以用来测试文件是否存在或测试其权限位,其中第一个参数path是相应的文件路径名,第二个参数是要测试的模
式。其中mode说明如下:
R_OK 测试读许可权
W_OK 测试写许可权
X_OK 测试执行许可权
F_OK 测试文件是否存在

####unlink()系统调用
用来删除文件,其本质是让文件的链接记数自减。调用该函数将path指定的文件的链接数减1,如果对该文件还有其他链接存在,则仍可以通过其他链接访问该文件的数据。只有当链接记数达到0时,该文件的内容才可被删除。如果有进程打开了该文件,其内容也不能被删除。关闭一个文件时,内核首先检查打开该文件的进程个数,如果这个记数达到0,内核再去检查它的链接记数,如果记数也是0,那么就删除该文件内容。

rename()系统调用

int rename(const char *oldname, const char *newname);

将文件重命名
####文件夹的相关调用
int mkdir(const char *pathname, mode_t mode); 创建文件夹
int rmdir(const char *pathname); 删除文件夹
DIR *opendir(const char *pathname); 打开文件夹
struct dirent * readdir(DIR *dp); 读文件夹
int closedir(IDR *dp); 关闭文件夹
int chdir(const char * pathname); 改变工作目录

###DS18B20温度探测
####1、内核以及文件
sudo raspi.config配置内核
配置存在问题,如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QwxfBIfW-1677653204196)(null)]
没有root权限,无法实现该功能

lsmod

显示当前所以加载的驱动
解决:iot22已经装好驱动
lsmod | grep w1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mZJqHZZu-1677653204248)(null)]
仅查看w1相关驱动协议
ls /sys/bus/查看所有总线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x1HjZ8Xc-1677653204319)(null)]
ls /sys/bus/w1/devices/温度传感器所在路径
cat /sys/bus/w1/devices/28-0317320a8aff/w1_slave采样数据保存地址:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6iHZxuU-1677653204227)(null)]
由于电场会产生磁场导致电平出现误差,对该数据进行CRC校验(循环冗余校验),一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-heOD25hl-1677653204271)(null)]
####2、代码
MAN 1函数命令,man2系统调用,man 3库函数

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main(int argc,char *argv[])
{ 
        int       fd;//打开文件返回值
        char  buf[128];//内容是字节,一般是2的幂次方大小
        fd = open("/sys/bus/w1/devices/28-0317320a8aff/w1_slave",O_RDONLY); //打开文件只读
       read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
      printf("buf: %s/n",buf);
      close(fd);

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aYiPxHVI-1677653204303)(null)]
如图,存在乱码
是因为没有把buf倒干净的原因
初始化bufmemset(buf, 0, sizeof(buf));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rxzb5m76-1677653204213)(null)]
增加输出温度显示:

{ 
        int       fd;//打开文件返回值
        char  buf[128];//内容是字节,一般是2的幂次方大小
		char  *ptr
        fd = open("/sys/bus/w1/devices/28-0317320a8aff/w1_slave",O_RDONLY); //打开文件只读
       read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
	   memset(buf, 0, sizeof(buf))
      printf("buf: %s/n",buf);
	  strstr("t == NULL");
	  if(ptr == NULL)//NULL=0,但是ptr是指针只能存储地址,所以此处的NULL==(viod)*0  ????****此处存在疑问
      close(fd);

}

atof将数据转换为浮点型,a:ascii,to:to,f:float;同理,atoi:转换为整数,atoll:转换为长整数
将温度转换为浮点数后输出:

{ 
        int       fd;//打开文件返回值
        char  buf[128];//内容是字节,一般是2的幂次方大小
		char  *ptr
		float temp;
        fd = open("/sys/bus/w1/devices/28-0317320a8aff/w1_slave",O_RDONLY); //打开文件只读
       read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
	   memset(buf, 0, sizeof(buf))
      printf("buf: %s/n",buf);
	  strstr("t == NULL");
	  if(ptr == NULL)//NULL=0,但是ptr是指针只能存储地址,所以此处的NULL==(viod)*0  ????****此处存在疑问
	  
      close(fd);

}
```[TOC]

继一月学习进程

```#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define BUFSIZE 1024  
#define MSG_STR "Hello World\n" 
#define cleanup 

int main(int argc, char*argv[])
{
  int    fd=-1; 
  int    rv=-1;
  char  buf[BUFSIZE];
fd=open("file.txt",O_RDWR|O_CREAT|O_TRUNC,0666); 
  if(fd<0)  

{

perror("Open/Create file test.txt failure");

return 0;

   } 

printf("Open file returned file descriptor [%d]\n", fd);

if((rv=write(fd,MSG_STR, strlen(MSG_STR)))<0)

{

printf("Write %d bytes into file failure: %s\n", rv, strerror(errno));

cleanup;


}

//memset(buf, 0, sizeof(buf));

if((rv=read(fd, buf, sizeof(buf)))<0)

{

printf ("Read data from file failure:%s\n", strerror(errno));

cleanup;

}

printf("Read %d bytes data from file : %s\n",rv, buf);

cleanup;

close(fd);

return 0;

}

###三、文件I/O操作函数
#####open()函数
int open(const char *path, int oflag, .../&mode_t mode*/)
open()系统调用用来打开一个文件,并返回一个文件描述符(file description), 并且该文件描述符是当前进程最小、未使用的文件描述符数值。
参数:
path: 要打开的文件、设备的路径
oflag: 由多个选项进行“或”运算构造oflag参数 。

  • 必选: O_RDONLY (只读)、 O_WRONLY(只写)、 O_RDWR(读写)
  • 可选: O_APPEND 每次写时都追加到文件的尾端。
    O_CREAT 文件不存在则创建它,使用该选项需要第三个参数mode
    O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0;
    O_NONBLOCK 如果path是一个FIFO、块设备、字符特殊文件则此选项为文件的本次打开和后续的I/O操作
    设置非阻塞模式方式。
    O_EXEC、O_SEARCH、O_CLOEXEC、O_NOCTTY…
    mode: oflag带O_CREAT选项时可以用来创建文件,这时必须带该参数用来指定创建文件的权限模式,如066。 否则不
    需要。使用示例代码:
int fd; 
 fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666); 
 fd = open(“text.txt”, O_WRONLY|O_APPEND);

####creat()系统调用

int creat(const char *path,mode_t mode);

此函数用来创建一个新文件并返回其fd。它等价于
open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

####close()系统调用

int close(int fd);

该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,
内核将会自动关闭它所有打开的文件。

####write()系统调用

ssize_t write(int fd, const void *buf, size_t nbytes);

write()函数用来往打开的文件描述符fd指向的文件中写入buf指向的数据,其中nbytes指定要写入的数据大小。如果返回值
<0则说明写入出错,譬如尝试往一个只读的文件中写入则会抛错,错误的原因系统会保存到errno变量中去。如果>0则为实
际写入的数据大小。

####lseek()系统调用

off_t lseek(int fd, off_t offset, int whence);

我们在从文件里读出内容,或往文件写如内容的时候都有一个起始地址,这个起始地址就是当前文件偏移量,当我们对文件
进行读写的时候都会使文件偏移量往后偏移。这点就类似于我们打开记事本开始编辑文本时的光标,我们读或写入时从光标所在位置开始读写,每读写一个字节都会使光标往后偏移。通过lseek()这个函数我们可以调整文件偏移量的地址。
其中 whence 可以是以下三个值:
SEEK_SET 文件头
SEEK_CUR 当前位置
SEEK_END 文件尾
而offset就是相对于whence 的偏移量,譬如:
lseek(fd, 0, SEEK_SET); 将文件偏移量设置到了文件开始的第一个字节上;
lseek(fd, 0, SEEK_END); 将文件偏移量设置到文件最后一个字节上;
lseek(fd, -1, SEEK_END); 将文件偏移量设置到文件最后的倒数第一个字节上;
####read()系统调用

ssize_t read(int fd, void *buf, size_t nbytes);

read()函数用来从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去,最多不要超过nbytes个字节,这里
的nbytes一般是buf剩余的空间大小。如read成功,则返回实际读到的字节数(由nbytes或读到文件尾决定,其中EOF宏用
来判断是否到了文件尾),如果返回值小于0则表示出错,如尝试读一个没有权限读的文件时就会抛错。

####dup() 和 dup2()系统调用

int dup(int fd);
int dup2(int fd, int fd2);


这两个函数都可以用来复制一个新的文件描述符来指向fd对应的文件。这两个系统调用经常用在标准输入、标准输出、标准
出错重定向。
dup()返回的新文件描述符一定是当前可用文件描述符中的最小数值;
dup2可以用fd2参数来指定新的文件描述符。如果fd2已经打开,则先关闭。如fd等于fd2, 则dup2返回fd2, 而不关闭它。

####stat()和fstat()系统调用

int stat(const char * restrict path, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);


这两个函数都是用来返回文件或目录的相关信息,只是stat()的第一个参数是文件名,而fstat()的第一个参数是文件打开的相
应文件描述符。其中struct stat结构体的定义如下:

struct stat {
 dev_t st_dev; /* ID of device containing file */
 ino_t st_ino; /* inode number */
 mode_t st_mode; /* protection */
 nlink_t st_nlink; /* number of hard links */
 uid_t st_uid; /* user ID of owner */
 gid_t st_gid; /* group ID of owner */
 dev_t st_rdev; /* device ID (if special file) */
 off_t st_size; /* total size, in bytes */
 blksize_t st_blksize; /* blocksize for filesystem I/O */
 blkcnt_t st_blocks; /* number of 512B blocks allocated */
 time_t st_atime; /* time of last access */
 time_t st_mtime; /* time of last modification */
 time_t st_ctime; /* time of last status change */
 };

vim stat.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main (int argc, char **argv)
{
 struct stat stbuf;
 
 stat("stat.c", &stbuf);
 printf("File Mode: %o Real Size: %luB, Space Size: %luB\n", stbuf.st_mode, stbuf.st_size,
stbuf.st_blksize);
 
 return 0;
}

####access()系统调用

int access(const char *path, int mode);

access()可以用来测试文件是否存在或测试其权限位,其中第一个参数path是相应的文件路径名,第二个参数是要测试的模
式。其中mode说明如下:
R_OK 测试读许可权
W_OK 测试写许可权
X_OK 测试执行许可权
F_OK 测试文件是否存在

####unlink()系统调用
用来删除文件,其本质是让文件的链接记数自减。调用该函数将path指定的文件的链接数减1,如果对该文件还有其他链接存在,则仍可以通过其他链接访问该文件的数据。只有当链接记数达到0时,该文件的内容才可被删除。如果有进程打开了该文件,其内容也不能被删除。关闭一个文件时,内核首先检查打开该文件的进程个数,如果这个记数达到0,内核再去检查它的链接记数,如果记数也是0,那么就删除该文件内容。

rename()系统调用

int rename(const char *oldname, const char *newname);

将文件重命名
####文件夹的相关调用
int mkdir(const char *pathname, mode_t mode); 创建文件夹
int rmdir(const char *pathname); 删除文件夹
DIR *opendir(const char *pathname); 打开文件夹
struct dirent * readdir(DIR *dp); 读文件夹
int closedir(IDR *dp); 关闭文件夹
int chdir(const char * pathname); 改变工作目录

###DS18B20温度探测
####1、内核以及文件
sudo raspi.config配置内核
配置存在问题,如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bk3qbkqL-1677653281168)(null)]
没有root权限,无法实现该功能

lsmod

显示当前所以加载的驱动
解决:iot22已经装好驱动
lsmod | grep w1
仅查看w1协议
ls /sys/bus/w1/devices/温度传感器所在路径
cat /sys/bus/w1/devices/28-0317320a8aff/w1_slave采样数据保存地址:

由于电场会产生磁场导致电平出现误差,对该数据进行CRC校验(循环冗余校验),一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

MAN 1函数命令,man2系统调用,man 3库函数

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main(int argc,char *argv[])
{ 
        int       fd;//打开文件返回值
        char  buf[128];//内容是字节,一般是2的幂次方大小
        fd = open("/sys/bus/w1/devices/28-0317320a8aff/w1_slave",O_RDONLY); //打开文件只读
       read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
      printf("buf: %s/n",buf);
      close(fd);

}

存在乱码
是因为没有把buf倒干净的原因
初始化buf```memset(buf, 0, sizeof(buf));

{
int fd;//打开文件返回值
char buf[128];//内容是字节,一般是2的幂次方大小
char *ptr
fd = open(“/sys/bus/w1/devices/28-0317320a8aff/w1_slave”,O_RDONLY); //打开文件只读
read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
memset(buf, 0, sizeof(buf))
printf(“buf: %s/n”,buf);
strstr(“t == NULL”);
if(ptr == NULL)//NULL=0,但是ptr是指针只能存储地址,所以此处的NULL==(viod)*0 ???****此处存在疑问
close(fd);

}

```atof```将数据转换为浮点型,a:ascii,to:to,f:float;同理,atoi:转换为整数,atoll:转换为长整数
将温度转换为浮点数后输出:

{
int fd;//打开文件返回值
char buf[128];//内容是字节,一般是2的幂次方大小
char *ptr
float temp;
fd = open(“/sys/bus/w1/devices/28-0317320a8aff/w1_slave”,O_RDONLY); //打开文件只读
read(fd,buf,sizof(buf));//从fd读文件内容, buf是装fd的容器,sizof(buf)容器大小
memset(buf, 0, sizeof(buf))
printf(“buf: %s/n”,buf);
strstr(“t == NULL”);
if(ptr == NULL)//NULL=0,但是ptr是指针只能存储地址,所以此处的NULL==(viod)*0

  close(fd);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值