Unix C中的一些文件操作(判断是否存在,文件打开,删除等)

本文介绍两种检查文件是否存在性的方法:一是使用access函数,通过不同amode参数检查文件的各种权限及存在性;二是利用fopen尝试打开文件进行判断。此外还介绍了文件的删除与基本操作。
判断文件存在
1,用函数access,头文件是stdio.h,原型:
int   access(const   char   *filename,   int   amode);
amode参数为0时表示检查文件的存在性,如果文件存在,返回0,不存在,返回-1。
这个函数还可以检查其它文件属性:
06     检查读写权限
04     检查读权限
02     检查写权限
01     检查执行权限
00     检查文件的存在性
在UNIX和VC下实验成功。
好处是 fopen(..,"r")不好,当无读权限时一不行了。
而这个就算这个文件没有读权限,也可以判断这个文件存在于否
存在返回0,不存在返回-1
#include <stdio.h>
int main()
{
      if((access("file.txt",0)) == 0) {
            remove("file.txt")  /*文件删除操作*/             
    }   
printf ("%d",access("111",0));
}
2,用fopen函数来判断,可以用在为了打开文件的地方,可以使用参数"r"或者"rb"
#include <stdio.h>
#include <stdlib.h>

int main(){
FILE *fp;

if ((fp = fopen("sample.txt", "r")) == NULL) {
printf("File Open Error/n");
exit(1);
}
fclose(fp);
printf("File Exist/n");
}
return 0;
}
文件删除操作
int result;

result = remove("C://sample.txt");
if (result != 0)
{
printf("削除に失敗しました。/n");
}
文件打开关闭操作
sFile *fd;
if((fd = fopen(filename, "ab")) == NULL)
{
return -1;
}
fprintf("文件出力操作");
fclose(fd);
}

<think>我们讨论的是C语言文件操作判断文件存在文件指针不为空的情况。根据引用[1]和引用[2],我们通常用fopen函数打开文件,如果文件存在,fopen会返回NULL。但是,用户提到了一种特殊情况:文件存在文件指针不为空。这通常不会发生,因为当文件存在且以只读模式打开时,fopen会返回NULL。然而,可能存在一些特殊情况,比如文件打开前被删除,或者权限问题等,但一般情况下,文件存在时fopen返回NULL。但是,用户的问题描述了一种看似矛盾的情况:文件存在,但文件指针(即fopen的返回值)不为空。这在实际编程中可能是由于以下原因:1.文件在fopen之后被立即删除,但程序还没有关闭文件指针。2.程序逻辑错误,可能误判了文件存在性(比如用其他方式判断文件存在,但fopen却返回了非空指针)。通常,我们使用fopen的返回值来判断文件是否成功打开。如果返回NULL,则打开失败,失败原因可能是文件存在或没有权限等。我们可以通过perror或errno来获取具体的错误信息。然而,如果fopen返回了非空指针,但随后我们又发现文件存在(例如,通过其他方式检查文件在磁盘上不存在),这可能是因为:-在打开文件后,文件删除了(在Unix/Linux系统中,即使文件删除,只要程序还打开着,文件内容仍然可以通过文件描述符访问,直到文件被关闭。但在Windows中,如果文件删除,通常无法再通过原有路径访问)。-程序使用了不同的路径(比如相对路径和绝对路径的混淆)导致判断文件存在而实际上文件指针指向的是另一个位置的文件。因此,要判断文件存在文件指针不为空的情况,我们可以这样做:1.使用fopen打开文件,如果文件指针不为空,说明文件打开成功(但此时文件可能被删除,尤其是在Unix-like系统上)。2.如果我们想确认文件是否仍然存在文件系统中,可以使用其他函数(如stat)来检查文件存在性。注意:在文件打开后,即使文件删除,在Unix-like系统上,stat可能会返回文件存在(因为文件名链接被删除,但文件内容还存在直到所有文件描述符关闭),而在Windows中,如果文件删除,则无法再通过原路径访问。所以,在C语言中,我们可以这样处理:步骤:1.使用fopen打开文件,如果返回NULL,则文件打开失败(可能是文件存在或其他错误)。2.如果返回非空,但我们需要确认文件是否存在(防止在打开后被删除),可以使用stat函数(需要包含<sys/stat.h>)来检查文件是否存在。但是注意:在打开文件后,我们有了文件指针,通常可以继续使用该指针进行读写,直到关闭。即使文件删除(在Unix-like系统上),只要文件指针有效,我们仍然可以读写。所以,通常我们不需要在打开后还去检查文件是否存在,因为文件指针已经代表了文件的访问权限。因此,用户的问题可能是在一个特定的场景下:他们希望确保文件打开后仍然存在文件系统中(即没有被删除)。这时,我们可以用stat函数来检查。示例代码:```c#include<stdio.h>#include<stdlib.h>#include<sys/stat.h>//用于stat函数intmain(){constchar*filename="test.txt";FILE*pf=fopen(filename,"r");if(pf==NULL){perror("fopenfailed");returnEXIT_FAILURE;}//现在,我们想检查文件是否仍然存在文件系统中structstatbuffer;if(stat(filename,&buffer)!=0){//stat失败,可能文件存在(已经被删除?)printf("文件存在文件系统中(可能被删除)\n");//但注意:在Unix-like系统中,即使文件删除,只要fopen成功了,我们仍然可以读取文件内容//所以这里只是检查文件是否存在(即硬链接是否存在)}else{printf("文件存在\n");}//使用文件指针进行操作...fclose(pf);return0;}```注意:在Unix-like系统上,如果我们在打开文件后,文件删除,那么stat会返回-1并且errno设置为ENOENT(文件存在)。但是,我们仍然可以通过文件指针读取文件内容,因为文件的实际数据在磁盘上直到所有文件描述符关闭才会被删除。所以,用户的问题“文件存在文件指针不为空”可能是指这种文件删除的情况。在代码中,我们可以通过stat来检查文件是否存在(即文件是否存在),而文件指针仍然有效。但是,这种检查通常不是必须的,因为文件指针有效就可以继续操作。除非有特殊需求,比如需要确保文件文件系统中可见(不被删除),才需要这样检查。另外,在Windows系统中,如果文件删除,则通过文件指针读写可能会失败(具体行为可能依赖于文件系统和操作系统版本)。所以,跨平台程序需要谨慎处理。总结:-通常,我们只需检查fopen的返回值是否NULL判断文件是否成功打开。-如果打开文件删除,在Unix-like系统上,我们仍然可以读写,但在Windows上可能会出错。-如果需要检查文件是否存在文件系统中(即文件是否存在),可以使用stat函数。因此,对于用户的问题,我们可以通过结合fopen和stat函数来处理这种特殊情况。注意:上面的代码中,我们使用了stat函数,它的原型是:intstat(constchar*path,structstat*buf);成功返回0,失败返回-1。如果用户不需要关心文件是否删除,那么直接使用文件指针即可。如果关心,则可以在打开后使用stat检查。但是,注意:在打开文件后,文件删除,然后我们使用stat检查同一个路径,会失败(文件存在)。而文件指针此时仍然有效(在Unix-like系统上)。所以,用户的问题中“文件存在文件指针不为空”的情况,在Unix-like系统上是可能发生的。我们通过stat可以检测到这种情况。相关问题:1.在C语言中,如何检查文件是否存在?2.在文件打开后,文件删除,会发生什么?3.如何安全地处理文件操作以避免文件删除导致的问题?4.在Windows和Unix-like系统上,文件删除后,已打开文件指针行为有何不同?</think>在C语言中,文件指针不为空但文件实际不存在的情况**通常不会发生**。因为当文件存在时,`fopen()`函数会返回`NULL`指针(参考引用[2])。但某些特殊场景可能导致文件指针非空而文件实际不可用,以下是解决方案: --- ### 核心判断逻辑 ```c #include <stdio.h> #include <errno.h> // 关键:包含错误处理头文件 int main() { FILE *pf = fopen("test.txt", "r"); // 1. 首先检查文件指针是否NULL(标准做法) if (pf == NULL) { perror("fopen failed"); return 1; } // 2. 特殊场景检测:文件指针非空但文件实际不可访问 if (fgetc(pf) == EOF && ferror(pf)) { printf("文件指针非空,但实际读取失败(可能文件删除或损坏)\n"); printf("系统错误码: %d\n", errno); // 打印具体错误原因 } fclose(pf); return 0; } ``` --- ### 关键原理说明 1. **`fopen()`的行为**(引用[2]): - 当文件存在时,`fopen("file", "r")` **必然返回`NULL`** - 此时`errno`会被设置为`ENOENT`(错误码2) 2. **异常场景分析**: - 文件在`fopen`后**被其他进程删除** - 文件系统损坏或权限突然变化 - 网络文件系统(NFS)延迟导致状态不一致 - **此时文件指针非空,但实际I/O操作会失败** 3. **检测方法**: - 尝试读取一个字符(`fgetc()`) - 用`ferror()`检测流错误(引用[1]) - 通过`errno`获取系统错误码(需`#include <errno.h>`) --- ### 错误码对照表 | 错误码 | 宏定义 | 含义 | |--------|------------|-----------------------| | 2 | `ENOENT` | 文件存在 | | 5 | `EIO` | 硬件I/O错误 | | 13 | `EACCES` | 权限不足 | | 116 | `ESTALE` | NFS文件句柄失效 | --- ### 完整解决方案 ```c #include <stdio.h> #include <errno.h> #include <string.h> void check_file_consistency(FILE *fp) { if (fp == NULL) return; // 尝试读取一个字节 int ch = fgetc(fp); if (ch == EOF) { if (ferror(fp)) { printf("[异常] 文件指针非空但读取失败\n"); printf("├─ 系统错误: %s\n", strerror(errno)); if (errno == ESTALE) { printf("└─ 警告: 文件可能被外部删除!\n"); } } } else { // 回退已读取的字符 ungetc(ch, fp); } } int main() { FILE *pf = fopen("ghost.txt", "r"); if (pf == NULL) { perror("标准错误: fopen失败"); } else { printf("文件指针非空,开始一致性检查...\n"); check_file_consistency(pf); fclose(pf); } return 0; } ``` --- ### 典型输出示例 ```text 文件指针非空,开始一致性检查... [异常] 文件指针非空但读取失败 ├─ 系统错误: Stale file handle └─ 警告: 文件可能被外部删除! ``` --- ### 最佳实践建议 1. **优先依赖`fopen()`的返回值**:正常逻辑中无需额外检查 2. **关键系统使用`stat()`前置检查**: ```c #include <sys/stat.h> struct stat st; if (stat("file.txt", &st) != 0) { // 文件存在或不可访问 } ``` 3. **处理网络文件时**:增加重试机制和`ESTALE`错误处理 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值