freopen() 在给定无效路径时创建文件
freopen() creates a file when given an invalid path
我有一个程序获取两个路径作为命令行参数。第一个参数(实际上是第二个,因为第一个是命令名称本身)是程序从中读取的文件(输入文件)的路径。第二个是程序写入的文件(输出文件)的路径。
int main(int argc, char *argv[])
{
int num;
/*if there are too many arguments print an error message*/
if(argc > 3)
{
perror("too many arguments");
return EXIT_FAILURE;
}
/*if there is at least one argument use it as path to input file*/
if(argc > 1)
if (!freopen(argv[1], "r", stdin)) {
perror("Path of input file is Invalid");
return EXIT_FAILURE;
}
/*if there are two arguments use the second one as output*/
if(argc == 3)
if (!freopen(argv[2], "w", stdout))
{
perror("Path of output file is Invalid");
return EXIT_FAILURE;
}
/*more code....*/
}
/*(compiled to run file "dtoa.out")*/
该程序工作正常:如果提供了有效的输入和路径输出路径,它将从文件中读取和写入,如果提供的参数太多或输入文件的路径无效,程序将打印一个错误信息并退出。
问题是提供了无效的输出文件路径:
$./dtoa ./tests/ExistingInput1.txt ./tests/NonExistingOutput.txt
在这种情况下,程序将只创建丢失的输出文件,而不是 returning NULL
并打印错误消息,这是不受欢迎的行为。我该如何更改它,以便在找不到文件时,该方法将 return NULL
而不是创建新文件?
这是记录在案的行为。如果文件不存在,则创建它。
尝试使用模式为'r'的fopen并检查文件指针是否为NULL,这样你就可以知道文件是否存在。
示例:
char path[256];
scanf("%s", path);
FILE* fp = NULL;
fp = fopen(path, "r");
if (!fp)
{
printf("The file doesen't exist!");
}
"r+"
模式技巧(在问题的评论中给出)可以
足够了,但也使 stdout
可供阅读。
(这是个问题吗?)
而不是使用 freopen()
你可以使用 open()
而不是
O_CREAT
标志。
然后可以将得到的文件描述符代入标准输出
dup2()
.
http://man7.org/linux/man-pages/man2/open.2.html
http://man7.org/linux/man-pages/man2/dup.2.html
这是一个最小的例子。
$ rm -f output.txt
$ ./prog_c output.txt
before
after
$ touch output.txt
$ ./prog_c output.txt
before
$ cat output.txt
after
$
源代码:
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
// for printf()
#include<stdio.h>
// for open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined _MSC_VER // compiling with visual-studio
# include <io.h>
#endif
// for dup2() and close()
#include <unistd.h>
int
main(int argc,
char **argv)
{
printf("before\n");
fflush(stdout); // in case something is pending in buffer...
if(argc>1)
{
#if defined _MSC_VER // compiling with visual-studio
int fd=_open(argv[1], _O_WRONLY|_O_TRUNC); // no _O_CREAT
#else
int fd=open(argv[1], O_WRONLY|O_TRUNC); // no O_CREAT
#endif
if(fd!=-1)
{
dup2(fd, STDOUT_FILENO);
close(fd);
}
}
printf("after\n");
return 0;
}
The problem is when provided with invalid output file path [...] the program will just create the missing output file instead of returning NULL
这是用 w
模式(或基于 w
或 a
的任何其他模式)打开文件的记录行为。如果那不是您想要的——并且您应该考虑事实是否如此——那么您需要使用不同的模式,至少在最初是这样。如果文件不存在,所有 r
模式都会导致 fopen()
和 freopen
失败,正如您所要求的那样。其中一些以允许读写的方式打开文件,例如,
if (argc == 3) {
if (!freopen(argv[2], "r+", stdout)) {
perror("Path of output file is Invalid");
return EXIT_FAILURE;
}
}
如果你想确保stdout
的模式不允许写入,and/or如果你想确保目标文件即使没有写入也被截断,那么你可以重新打开它两次,首先以基于读取的模式,如果成功,则以只写模式:
if (argc == 3) {
if (!freopen(argv[2], "r+", stdout)) {
perror("freopen (output)");
return EXIT_FAILURE;
}
if (!freopen(NULL, "w", stdout)) {
perror("freopen (output)");
return EXIT_FAILURE;
}
}
我有一个程序获取两个路径作为命令行参数。第一个参数(实际上是第二个,因为第一个是命令名称本身)是程序从中读取的文件(输入文件)的路径。第二个是程序写入的文件(输出文件)的路径。
int main(int argc, char *argv[])
{
int num;
/*if there are too many arguments print an error message*/
if(argc > 3)
{
perror("too many arguments");
return EXIT_FAILURE;
}
/*if there is at least one argument use it as path to input file*/
if(argc > 1)
if (!freopen(argv[1], "r", stdin)) {
perror("Path of input file is Invalid");
return EXIT_FAILURE;
}
/*if there are two arguments use the second one as output*/
if(argc == 3)
if (!freopen(argv[2], "w", stdout))
{
perror("Path of output file is Invalid");
return EXIT_FAILURE;
}
/*more code....*/
}
/*(compiled to run file "dtoa.out")*/
该程序工作正常:如果提供了有效的输入和路径输出路径,它将从文件中读取和写入,如果提供的参数太多或输入文件的路径无效,程序将打印一个错误信息并退出。
问题是提供了无效的输出文件路径:
$./dtoa ./tests/ExistingInput1.txt ./tests/NonExistingOutput.txt
在这种情况下,程序将只创建丢失的输出文件,而不是 returning NULL
并打印错误消息,这是不受欢迎的行为。我该如何更改它,以便在找不到文件时,该方法将 return NULL
而不是创建新文件?
这是记录在案的行为。如果文件不存在,则创建它。
尝试使用模式为'r'的fopen并检查文件指针是否为NULL,这样你就可以知道文件是否存在。 示例:
char path[256];
scanf("%s", path);
FILE* fp = NULL;
fp = fopen(path, "r");
if (!fp)
{
printf("The file doesen't exist!");
}
"r+"
模式技巧(在问题的评论中给出)可以
足够了,但也使 stdout
可供阅读。
(这是个问题吗?)
而不是使用 freopen()
你可以使用 open()
而不是
O_CREAT
标志。
然后可以将得到的文件描述符代入标准输出
dup2()
.
http://man7.org/linux/man-pages/man2/open.2.html
http://man7.org/linux/man-pages/man2/dup.2.html
这是一个最小的例子。
$ rm -f output.txt
$ ./prog_c output.txt
before
after
$ touch output.txt
$ ./prog_c output.txt
before
$ cat output.txt
after
$
源代码:
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
// for printf()
#include<stdio.h>
// for open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined _MSC_VER // compiling with visual-studio
# include <io.h>
#endif
// for dup2() and close()
#include <unistd.h>
int
main(int argc,
char **argv)
{
printf("before\n");
fflush(stdout); // in case something is pending in buffer...
if(argc>1)
{
#if defined _MSC_VER // compiling with visual-studio
int fd=_open(argv[1], _O_WRONLY|_O_TRUNC); // no _O_CREAT
#else
int fd=open(argv[1], O_WRONLY|O_TRUNC); // no O_CREAT
#endif
if(fd!=-1)
{
dup2(fd, STDOUT_FILENO);
close(fd);
}
}
printf("after\n");
return 0;
}
The problem is when provided with invalid output file path [...] the program will just create the missing output file instead of returning
NULL
这是用 w
模式(或基于 w
或 a
的任何其他模式)打开文件的记录行为。如果那不是您想要的——并且您应该考虑事实是否如此——那么您需要使用不同的模式,至少在最初是这样。如果文件不存在,所有 r
模式都会导致 fopen()
和 freopen
失败,正如您所要求的那样。其中一些以允许读写的方式打开文件,例如,
if (argc == 3) {
if (!freopen(argv[2], "r+", stdout)) {
perror("Path of output file is Invalid");
return EXIT_FAILURE;
}
}
如果你想确保stdout
的模式不允许写入,and/or如果你想确保目标文件即使没有写入也被截断,那么你可以重新打开它两次,首先以基于读取的模式,如果成功,则以只写模式:
if (argc == 3) {
if (!freopen(argv[2], "r+", stdout)) {
perror("freopen (output)");
return EXIT_FAILURE;
}
if (!freopen(NULL, "w", stdout)) {
perror("freopen (output)");
return EXIT_FAILURE;
}
}