标准I/O之文件定位(fseek)和文件I/O

文件操作标准库函数

 C 语言中,fseekftell 和 rewind 是用于文件操作的标准库函数,它们帮助管理文件流的位置。

标准IO之文件定位:

fseek()   ftell()  rewind()

int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始
      偏移offset字节的长度。
参数:stream  要移动文件指针的目标文件流对象。
      注意:不支持设备文件,一般用于普通文件。
      offset  要在文件内偏移的距离,单位字节。
                如果值为整数,则向文件末尾偏移
              如果值为负数,则向文件开头偏移
      whence  偏移的起始位置,由系统定义的三个宏开始。
          SEEK_SET  文件的开头位置 
        SEEK_CUR  文件的当前位置
        SEEK_END  文件的末尾位置

返回值:    
    成功: 返回 0
    失败:  -1;

如果从文件的指定位置向后偏移过程中已经超过了文件的当前末尾位置,则会自动以'\0'来填充文件内容,从而形成一种被称为"空洞文件" 的特殊文件。

rewind()  等效于:fseek(stream,0L,SEEK_SET);

long ftell(FILE *stream);rewind(fp);
功能:获取当前文件流指针的具体位置,一般以文件
     开头到当前指针的字节数为返回值。
参数:stream 要返回指针距离的文件流对象
返回值:成功 获取到的距离长度,单位是字节
        失败 -1;

终端缓冲区结束测试情况

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    /* 1
    printf("hello");
    while(1)
    sleep(1);
    */ 

    /* 2
    int i=0;
    for(i=0;i<1025;i++)
    {
    
        //printf("a");
        fputc('a',stdout);//  stdin stdout stderr 
    }

    while(1)
    sleep(1);
    */ 
/*3
    printf("hello");
    */ 


    printf("hello");
    fflush(stdout);
    while(1)
    sleep(1);
    return 0;
}

文件中传输的缓冲区结束情况判断

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    FILE* fp = fopen("1.txt","w");
    if(NULL == fp)
    {
        return 1;
    }

    /* 1
    char buf[]="hello";
    fputs(buf,fp);

    while(1)
        sleep(1);
    */ 


    /*2 
    int i=0;
    for(i = 0 ;i<4097;i++)
    {
        fputc('a',fp);
    }
    while(1)
        sleep(1);
    return 0;
    */

    /*
    char buf[]="hello";
    fputs(buf,fp);
    return 0;
    */ 

    char buf[]="hello";
    fputs(buf,fp);
    fflush(fp);

    while(1)
        sleep(1);

    return 0;

}

 在文件 I/O 中,openclosewrite 和 read 是用于文件操作的基本函数。它们通常在 POSIX 标准下使用,特别是在 Unix 和 Linux 系统中。下面是对这几个函数的详细介绍及使用方法。

1. open 函数

函数原型:

int open(const char *pathname, int flags, mode_t mode);

参数:

  • pathname:要打开的文件的路径名。
  • flags:打开文件的标志,决定文件的打开模式(如只读、只写等)。
  • mode:指定文件的权限(在创建新文件时使用)。

返回值:

  • 成功时,返回一个非负整数(文件描述符)。
  • 失败时,返回 -1,并设置 errno 以指示错误类型。

常见的 flags

  • O_RDONLY:以只读方式打开。
  • O_WRONLY:以只写方式打开。
  • O_RDWR:以读写方式打开。
  • O_CREAT:如果文件不存在,则创建文件。
  • O_TRUNC:如果文件存在且以写入方式打开,则清空文件。

示例:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = open("example.txt", O_CREAT | O_WRONLY, 0644);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 进行文件操作

    close(fd);  // 关闭文件
    return 0;
}

2. close 函数

函数原型:

int close(int fd);

参数:

  • fd:要关闭的文件描述符。

返回值:

  • 成功时,返回 0。
  • 失败时,返回 -1,并设置 errno。

示例:

#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 进行文件操作

    if (close(fd) == -1) {
        perror("close");
        return 1;
    }

    return 0;
}

3. write 函数

函数原型:

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

参数:

  • fd:要写入的文件描述符。
  • buf:指向要写入数据的缓冲区。
  • count:要写入的字节数。

返回值:

  • 成功时,返回实际写入的字节数。
  • 失败时,返回 -1,并设置 errno。

示例:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = open("example.txt", O_CREAT | O_WRONLY, 0644);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    const char *text = "Hello, World!\n";
    ssize_t bytes_written = write(fd, text, 14);
    if (bytes_written == -1) {
        perror("write");
        close(fd);
        return 1;
    }

    close(fd);
    return 0;
}

4. read 函数

函数原型:

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

参数:

  • fd:要读取的文件描述符。
  • buf:指向存储读取数据的缓冲区。
  • count:要读取的字节数。

返回值:

  • 成功时,返回实际读取的字节数(可能小于 count,如果到达文件末尾)。(这个值一般都需要用到,记住它的含义,时读时写,和write函数配合使用,读多少,我就写多少)
  • 读完时,返回 0。
  • 失败时,返回 -1,并设置 errno。

示例:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    char buffer[100];//
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    if (bytes_read == -1) {
        perror("read");
        close(fd);
        return 1;
    }

    buffer[bytes_read] = '\0';  // 添加字符串结束符
    printf("Read: %s", buffer);

    close(fd);
    return 0;
}

注意事项

  1. 错误处理: 始终检查 openclosewrite 和 read 的返回值,以处理可能出现的错误。
  2. 文件权限: 使用 mode 参数时,要确保设置正确的文件权限,以允许合适的读/写操作。
  3. 缓冲区: 在 read 和 write 操作时,确保缓冲区足够大,以存储所需的数据。
  4. 文件描述符: 每次打开文件时,系统会分配一个新的文件描述符。确保在使用后关闭文件描述符,以避免资源泄漏。

通过使用这些函数,可以在 C 语言中进行文件的读写操作,确保能够正确管理和操作文件。

练习:复制功能(重要)

#include <stdio.h> 
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, const char *argv[])
{
	if(argc<3)
	{
		fprintf(stderr, "input ./a.out 1 2\n");//注意输入的规范  类似于 cp 1.txt 2.txt
		return 1;
	}
	int fd = open(argv[1],O_RDONLY);
	int dest = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);

	if(-1==fd||-1==dest)//这里有个小细节,常数写左边,如果你少输入一个=,则会报错,常数在右边就是正常赋值,不会报错,但会使结果异常,左值必须是变量,不可以是常数。
	{
		fprintf(stderr, "open error\n");
		return 1;
	}

	while(1)
	{
		char buf[1024] = {0};//每次循环都要清空,不可以在while外面,要不然传了一次下一次还是会传上一次buf内的内容
		int ret = read(fd,buf,sizeof(buf));
		if(ret<=0)//文件读完ret=0;读取出错ret=-1;反正都是结束程序,一块处理  
		{
			break;
		}
		int ch = write(dest,buf,ret);//一定要read函数读完返回值判断完,读取成功,才可以写入,而且每次写入的内容都是read返回值大小(返回值为读到有效字节数),时读时传,这样就可以传二进制文件和文本文件都能传。
		if(ch==-1)
		{
			fprintf(stderr, "write error\n");
			return 1;
		}
	}
	close(fd);
	close(dest);//打开使用完别忘记关闭
	return 0;
}

使用open、close、read、write函数完成复制函数。

文本文件(1.txt)中不会出现‘\0’这个符号,所有我们上面操作的是文本文件1.txt  我们用write函数写入时,最后的count必须是有效字符数,这里传的是hello 5个字节,所有可以用strlen(buf)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值