检查文件指针是否指向有效文件的快速方法
Fast way to check if file pointer points to a valid file
我正在寻找快速(对于性能关键型代码)、安全和跨平台的方法来检查 FILE*
是否确实指向了之前成功调用 fopen()
的文件。
使用 ftell()
询问当前位置是一种方法,但是
我怀疑它是否最快、准确、安全,或者没有比这种方式更直接、更专注的方法了。
在C语言中有3种指针值:
- 值为 NULL,因为程序员初始化了它们(或者因为它们利用了默认的静态初始化)。
- 由 return 指针函数 return 编辑的值,例如
fopen
或 malloc
(并且尚未传递给 fclose
或 free
).
- 1 和 2 都不为真的值。
一个简单的事实是,如果你有一个类型 3 的指针,语言中没有任何机制可以告诉你指针是否有效。如果你有一个指针p
,它可能是从malloc
获得的,也可能不是,但你不记得了,没有办法要求编译器或运行-时间系统来告诉你如果它当前指向有效内存。如果你有一个 FILE 指针 fp
可能是从 fopen
获得的,但你不记得了,没有办法要求编译器或 运行-time 系统告诉你它目前是否 "points to" 一个有效的文件。
因此,由程序员 您 来跟踪指针值,并使用编程实践来帮助您确定指针值是否有效。
这些方式包括:
- 始终将指针变量初始化为 NULL 或指向有效的内容。
- 当您调用 return 是指针的函数时,例如
fopen
或 malloc
,请始终测试 return 值以查看它是否为 NULL,如果它是,return 提早或打印错误消息或任何适当的内容。
- 当您完成动态分配的指针,并通过调用
fclose
或 free
或等效函数释放它时,始终将其设置回 NULL。
如果你虔诚地做这三件事,那么你可以通过做
来测试一个指针是否有效
if(p != NULL)
或
if(p)
类似地,如果你虔诚地做那些事情,你可以通过做
来测试指针是否无效
if(p == NULL)
或
if(!p)
但是如果您虔诚地执行了第 1 步和第 3 步,那么这些测试只有才能可靠地工作。如果您还没有,则有可能 - 并且很可能 - 各种指针值非 NULL 但无效。
以上是一种策略。我应该指出,第 1 步和第 3 步并不是绝对必要的。另一个策略是虔诚地应用步骤 2,永远不要保留——永远不要尝试使用——可能为空的指针。如果像 fopen
或 malloc
return NULL 这样的函数,您要么立即退出程序,要么立即从您所在的任何函数中退出 return,通常带有一个失败代码,告诉你的来电者你无法完成你的工作(因为你无法打开你需要的文件,或者你无法分配你需要的内存)。在严格应用规则 2 的程序中,您甚至不需要测试指针的有效性,因为此类程序中的所有指针值都是有效的。 (好吧,只要虔诚地应用规则 2,所有指针都是有效的。如果你忘记应用规则 2,哪怕一次,事情就会开始崩溃。)
如果对 fopen
的调用成功,但您想知道您是否刚刚打开了文件或其他内容,我知道两种通用方法:
在文件描述符上使用 fstat
(或在刚刚打开的同一路径名上使用 stat
),然后检查模式位。
尝试在文件描述符上查找。如果这按预期工作,它可能是一个文件;如果不是,那就是管道或插座或类似的东西。
(1) 的代码可能类似于
struct stat st;
fstat(fileno(fp), &st);
if(st.st_mode & S_IFMT) == S_IFREG)
/* it's a regular file */
为了执行 (2),我通常寻求偏移量 1,然后测试以查看我所处的偏移量。如果我在 1,它是一个可搜索的文件,对于程序的其余部分,我倒退到 0。但如果 I 仍为 0,则它不是可搜索的文件。 (当然,我会在打开文件后立即执行一次,并将结果记录在我自己的与打开文件关联的标志中,因此对性能的影响很小。)
我正在寻找快速(对于性能关键型代码)、安全和跨平台的方法来检查 FILE*
是否确实指向了之前成功调用 fopen()
的文件。
使用 ftell()
询问当前位置是一种方法,但是
我怀疑它是否最快、准确、安全,或者没有比这种方式更直接、更专注的方法了。
在C语言中有3种指针值:
- 值为 NULL,因为程序员初始化了它们(或者因为它们利用了默认的静态初始化)。
- 由 return 指针函数 return 编辑的值,例如
fopen
或malloc
(并且尚未传递给fclose
或free
). - 1 和 2 都不为真的值。
一个简单的事实是,如果你有一个类型 3 的指针,语言中没有任何机制可以告诉你指针是否有效。如果你有一个指针p
,它可能是从malloc
获得的,也可能不是,但你不记得了,没有办法要求编译器或运行-时间系统来告诉你如果它当前指向有效内存。如果你有一个 FILE 指针 fp
可能是从 fopen
获得的,但你不记得了,没有办法要求编译器或 运行-time 系统告诉你它目前是否 "points to" 一个有效的文件。
因此,由程序员 您 来跟踪指针值,并使用编程实践来帮助您确定指针值是否有效。
这些方式包括:
- 始终将指针变量初始化为 NULL 或指向有效的内容。
- 当您调用 return 是指针的函数时,例如
fopen
或malloc
,请始终测试 return 值以查看它是否为 NULL,如果它是,return 提早或打印错误消息或任何适当的内容。 - 当您完成动态分配的指针,并通过调用
fclose
或free
或等效函数释放它时,始终将其设置回 NULL。
如果你虔诚地做这三件事,那么你可以通过做
来测试一个指针是否有效if(p != NULL)
或
if(p)
类似地,如果你虔诚地做那些事情,你可以通过做
来测试指针是否无效if(p == NULL)
或
if(!p)
但是如果您虔诚地执行了第 1 步和第 3 步,那么这些测试只有才能可靠地工作。如果您还没有,则有可能 - 并且很可能 - 各种指针值非 NULL 但无效。
以上是一种策略。我应该指出,第 1 步和第 3 步并不是绝对必要的。另一个策略是虔诚地应用步骤 2,永远不要保留——永远不要尝试使用——可能为空的指针。如果像 fopen
或 malloc
return NULL 这样的函数,您要么立即退出程序,要么立即从您所在的任何函数中退出 return,通常带有一个失败代码,告诉你的来电者你无法完成你的工作(因为你无法打开你需要的文件,或者你无法分配你需要的内存)。在严格应用规则 2 的程序中,您甚至不需要测试指针的有效性,因为此类程序中的所有指针值都是有效的。 (好吧,只要虔诚地应用规则 2,所有指针都是有效的。如果你忘记应用规则 2,哪怕一次,事情就会开始崩溃。)
如果对 fopen
的调用成功,但您想知道您是否刚刚打开了文件或其他内容,我知道两种通用方法:
在文件描述符上使用
fstat
(或在刚刚打开的同一路径名上使用stat
),然后检查模式位。尝试在文件描述符上查找。如果这按预期工作,它可能是一个文件;如果不是,那就是管道或插座或类似的东西。
(1) 的代码可能类似于
struct stat st;
fstat(fileno(fp), &st);
if(st.st_mode & S_IFMT) == S_IFREG)
/* it's a regular file */
为了执行 (2),我通常寻求偏移量 1,然后测试以查看我所处的偏移量。如果我在 1,它是一个可搜索的文件,对于程序的其余部分,我倒退到 0。但如果 I 仍为 0,则它不是可搜索的文件。 (当然,我会在打开文件后立即执行一次,并将结果记录在我自己的与打开文件关联的标志中,因此对性能的影响很小。)