open, create, close

本文深入讲解了Linux系统中文件操作的核心函数,包括open、creat和close。详细解释了open函数的参数、返回值及各种标志位的作用,通过实例演示了不同标志组合的效果。同时,对比了open与creat函数的异同,以及如何正确使用这些函数来创建和管理文件。

1.open 系统调用

说明:
调用open函数打开或者创建一个文件。函数定义如下: 
#include <fcntl.h>  
int open(const char *pathname, int flag);  
int open(const char *pathname, int flag, mode_t mode);//只有新创建文件时才会使用该函数  
//返回值,如果成功返回文件描述符,如果出错返回-1  
使用open返回的文件描述符作为参数传递给write或read,按照惯例,UNIX中文件描述符0与标准输入相关联,文件描述符1与标准输出相关联,文件描述符2与标准出错输出相关联。依照POSIX标准,0、1、2通常被替换成符号常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO(定义在头文件unistd.h中)。文件描述符的范围为0~OPEN_MAX。pathname为文件的绝对路径或相对路径。
flag用于指定文件的打开/创建模式,这3个常量定义在fcntl.h中,这3个参数是必选的,而且只能选择一个:
O_RDONLY       只读模式
O_WRONLY      只写模式
O_RDWR         读写模式

下面的常量是可选的:

O_APPEND       每次写操作都写入文件的末尾。

O_CREAT        如果指定文件不存在,则创建这个文件。如果存在则直接打开文件。如果创建新文件,而mode参数没有指定,则创建的文件权限不定。 

O_EXCL          如果文件不存在,则返回错误。如果同时指定了O_CREAT,而文件已经存在,则会出错。 用此测试一个文件是否存在,如果不存在,则创建此文件。

O_TRUNC        如果文件存在,并且以只写/读写方式打开,则清空文件全部内容。

O_NOCTTY       如果路径名指向终端设备,不要把这个设备用作控制终端。

O_NONBLOCK     如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)。

下面三个标志也是可选的,他们是Single UNIX Specification中同步输入和输出选项的一部分:

O_DSYNC        等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。 //??

O_RSYNC        read 等待所有写入同一区域的写操作完成后再进行。

O_SYNC         等待物理 I/O 结束后再 write,包括更新文件属性的 I/O。

可选参数可以和必选参数一起使用,并且可以使用多个,如果要以读写方式打开一个文件,如果该文件已经存在,则

将文件清空,如果没有存在,则新创建文件,flag应该为:O_WRONLY | O_CREAT | O_TRUNC

mode用于在创建新文件时指定文件的权限,参数的:

 

实践:

如果使用O_CREAT 多次,则第一次创建文件,接下来直接打开文件。 

#include <stdio.h>  
#include <fcntl.h>    
int main(void){  
        int fd;  
        if((fd = open("./a.txt",O_RDONLY|O_CREAT, S_IRUSR))<0){  
                perror("open");  
        }  
        close(fd);  
        return 0;  
}  

运行结果: 

  1. yan@yan-vm:~/ctest$ ./a.out  
  2. yan@yan-vm:~/ctest$ ll a.txt  
  3. -r-------- 1 yan yan 0 Jun  5 07:48 a.txt  
  4. yan@yan-vm:~/ctest$ ./a.out  
  5. yan@yan-vm:~/ctest$ ./a.out   

如果同时使用O_CREAT和O_EXCL,并且文件已经存在,则会出错;如果文件不存在,则创建文件,并且这个操作是原子操作。

#include <stdio.h>  
#include <fcntl.h>    
int main(void){  
        int fd;  
        if((fd = open("./a.txt",O_RDONLY|O_CREAT|O_EXCL))<0){  
                perror("open");  
        }  
        close(fd);  
        return 0;  
}  

 运行结果: 

  1. yan@yan-vm:~/ctest$ ll a.txt  
  2. -rw-rw-r-- 1 yan yan 0 Jun  5 07:55 a.txt  
  3. yan@yan-vm:~/ctest$ ./a.out  
  4. open: File exists  

 

如果单独使用O_EXCL,并且文件不存在,则会出错;如果文件已经存在,不会报错,也不会创建文件。

#include <stdio.h>  
#include <fcntl.h>    
int main(void){  
        int fd;  
        if((fd = open("./a.txt",O_RDONLY|O_EXCL))<0){  
                perror("open");  
        }  
        close(fd);  
        return 0;  
}  

运行结果: 

  1. root@yan-virtual-machine:~# ll a.txt  
  2. ls: 无法访问a.txt: 没有那个文件或目录  
  3. root@yan-virtual-machine:~# ./open  
  4. -bash: ./open: 没有那个文件或目录  
  5. root@yan-virtual-machine:~# touch a.txt  
  6. root@yan-virtual-machine:~# ./a.out  
  7. root@yan-virtual-machine:~#   

2.creat函数

使用creat函数创建一个新文件,如果原来该文件存在,会将这个文件的长度截短为0。函数定义如下: 

#include <fcntl.h>  
int creat(const char *pathname, mode_t mode);  

如果成功则返回为只写打开的文件描述符,出错则返回-1。 

此函数等效于: 

  1. open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);  

后面的mode_t就是ugo的权限(同open函数),注意,如果creat函数创建了一个可读写的文件,但是因为creat只返回可写的文件描述符,所以使用返回的文件描述符读的时候会出错。例子如下: 

#include <stdio.h>  
#include <fcntl.h>    
int main(void){  
        int fd;  
        if((fd = creat("./a.txt", S_IRUSR|S_IWUSR|S_IXUSR))<0){  
                perror("creat");  
        }  
  
        char buf[100];  
        if(read(fd,buf,100) < 0){   //返回的文件描述符不允许读,但是文件的权限还是rwx的
                perror("read");  
        }    
        close(fd);  
        return 0;  
}  

执行结果为: 

  1. yan@yan-vm:~/ctest$ ./a.out  
  2. read: Bad file descriptor   

如果文件已经存在,再次creat该文件,原来的文件将被删除,重新生成一个空文件。  

#include <stdio.h>  
#include <fcntl.h>    
int main(void){  
        int fd;  
        if((fd = creat("./a.txt", S_IRUSR|S_IWUSR|S_IXUSR))<0){  
                perror("creat");  
        }    
        close(fd);  
        return 0;  
}  

运行结果: 

root@virtual-machine:~# cat a.txt
123
root@virtual-machine:~# ./a.out
root@virtual-machine:~# cat a.txt
root@virtual-machine:~# 

3.close函数

close函数关闭一个打开的文件。函数定义如下:  

  1. #include <unistd.h> 
  1. int close(int filedes);  

如果成功返回0,出错返回-1.关闭一个文件时还会释放该进程加在文件上的所有记录锁。

转载于:https://www.cnblogs.com/QingCHOW/p/4595834.html

在编程中,创建和关闭文件是常见的操作,尤其是在处理文件流时。以 C# 为例,可以使用 `File.Create()` 方法创建文件,并通过 `Close()` 方法关闭文件流以释放资源。以下是一个完整的示例,展示如何创建文件、写入数据、读取数据并最终关闭文件流: 在 C# 中,`File.Create()` 方法会返回一个 `FileStream` 对象,该对象可以用于后续的读写操作。创建文件后,应始终调用 `Close()` 或 `Dispose()` 方法来释放与文件流关联的资源,避免文件被锁定或占用[^1]。 ```csharp using System; using System.IO; class Program { static void Main() { string filePath = "example.txt"; // 创建文件并写入内容 using (FileStream fs = File.Create(filePath)) { using (StreamWriter sw = new StreamWriter(fs)) { sw.WriteLine("Hello, world!"); } } // 文件流在此自动关闭 // 读取文件内容 using (FileStream fs = File.OpenRead(filePath)) { using (StreamReader sr = new StreamReader(fs)) { string content = sr.ReadToEnd(); Console.WriteLine(content); } } // 文件流在此自动关闭 } } ``` 上述代码使用了 `using` 语句,确保即使在发生异常的情况下,文件流也会被正确关闭。`using` 语句会自动调用 `Dispose()` 方法,该方法等效于 `Close()` 操作。通过这种方式,可以有效避免文件被其他进程占用的问题[^1]。 ### 文件流管理的重要性 在处理文件流时,务必确保在完成操作后及时关闭流。如果未正确关闭文件流,可能会导致以下问题: - **文件被锁定**:其他进程无法访问当前被占用的文件。 - **资源泄漏**:未释放的文件流会占用系统资源,可能导致性能下降或程序崩溃。 - **数据丢失**:缓冲区中的数据可能未被完全写入文件,导致信息丢失。 因此,在任何涉及文件操作的编程语言中,都应遵循“打开 → 操作 → 关闭”的标准流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值