2017-03-16 43 views
0

有没有干净的方式来打开这样的文件,而无需系统调用:的fopen一个文件,并跳过字符

ID*_LogConfig.csv 

我尝试以下,但它并没有奏效。

/*Read setup file*/ 
getcwd(cwd, sizeof(cwd)); 
snprintf(source, sizeof(source),"%s/ID%*d_LogConfig.csv",cwd); 
if(NULL == (input = fopen(source,"r"))) 
{ 
    snprintf(errbuffer,sizeof(errbuffer), "Could not open file %s - check existence/rights\n", source); 
    exitHandler(1, errbuffer); 
} 

它输出:

/mnt/dataflash/canfilter.d/ID*_LogConfig.csv not found 

但是与例如cat /mnt/dataflash/canfilter.d/ID*_LogConfig.csv它显示文件内容。

我的折衷的解决方案将是一个系统调用ll ID*_LogConfig.csv并使用输出文件名。

+0

'll'不是系统调用。这是一个由shell调用的程序。这也是预制棒替代品的外壳。 – StoryTeller

+1

不是'%* d'期望宽度和'int'参数吗?尝试'snprintf(source,sizeof(source),“%s /%s”,cwd,“ID * _LogConfig.csv”);' – chux

+0

什么是'cwd'?什么是“源”?什么是'errbuffer'?请将这些定义添加到您的问题中。 – wildplasser

回答

0

有没有干净的方式来打开这样的文件,而无需系统调用

fopen()利用系统调用的。没有系统调用,您无法“打开”文件。

如果您指的是system(3)函数,那么您可能会遇到一些痛苦 - 从性能,可靠性和安全角度出发,最好尽可能避免它。

如果你想打开'所有匹配模式的文件',那么看glob(3),这可能是你的shell用来处理这种通配符的东西。 您将需要遍历每个产生的路径,每个调用fopen()fread()fclose()。的glob(3)

用法示例:

#include <stdio.h> 
#include <glob.h> 

void main(void) { 
    int ret; 
    int i; 
    glob_t glob_info; 

    ret = glob("*.csv", 0, NULL, &glob_info); 
    if (ret != 0) 
    { 
     fprintf(stderr, "glob() failed: %d\n", ret); 
     return; 
    } 

    for (i = 0; i < glob_info.gl_pathc; i++) { 
     printf("%d: %s\n", i, glob_info.gl_pathv[i]); 
    } 

    globfree(&glob_info); 
} 

这是不是一个真正的好主意,打开大量的文件,并把流作为一个单一的“东西”(因为你与你的cat例如做)。

由于@Andrew已经指出的那样,你必须要小心你使用printf()格式字符串... 您提供以下内容:%s/ID%*d_LogConfig.csv。甲%表示格式说明的开始,因此你给以下各项:

  • %s - 一个char *(字符串)参数如下
  • %*d - 类似%d,但*意味着精度被设置作为int参数,然后是号码本身。

例如:

printf(">%s< >%*d<\n", "Hello", 5, 3); 

将输出:(注意5个字符的%d输出)

>Hello< > 3< 

如果你是一个*后,然后就放了*在格式字符串。 如果您在%之后,那么您需要转义%,但将%%置于格式字符串中。

2

此行

snprintf(source, sizeof(source),"%s/ID%*d_LogConfig.csv",cwd); 

可能不会产生你所想象的那样。

%*d部分是格式说明具有场宽度,per the POSIX printf() documentation

场宽度,或精度,或两者,可以由 (“*”)来指示。在这种情况下,类型为int的参数提供了 字段的宽度或精度。应用程序应确保参数 指定字段宽度或精度,或两者都以 的顺序出现在参数之前(如果有的话)进行转换。负字段宽度 被视为“ - ”标志,后跟正字段宽度。如果精度被忽略,则采用负的 精度。在格式字符串 包含“%N $”转换规范的形式,场宽度 或精度可通过在序列“*米$”,其中m是在范围[1,{NL_ARGMAX一个 十进制整数来指示}]给出的位置中 参数列表(format参数之后)包含字段宽度或精度,例如一个整数参数 的:

printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec); 

因此,这条线

snprintf(source, sizeof(source),"%s/ID%*d_LogConfig.csv",cwd); 

预计两个更多要传递的整数参数。既然你没有通过它们,你就会调用未定义的行为。

看到这个答案:https://stackoverflow.com/a/19897395/4756299

-2

确定我解决了“问题”通过使用以下: (加工LS -t的输出,并使用最新的文件作为配置文件中)

/*Search for config-file*/ 
FILE *file_config; 
file_config = popen("ls -t ID*_LogConfig.csv","r"); 
if (file_config == NULL) { 
    exitHandler(1, "Error opening date pipe."); 
} 
fgets(configfile, sizeof(configfile), file_config); 
if (strlen(configfile) > 0) 
    configfile[strlen(configfile)-1] = '\0'; 
else { 
    exitHandler(1, "Could not find a ID*_LogConfig.csv\n"); 
} 
getcwd(cwd, sizeof(cwd)); 
snprintf(source, sizeof(source),"%s/%s",cwd,configfile); 

/*Read setup file*/ 
if(NULL == (input = fopen(source,"r"))) 
{ 
    snprintf(errbuffer,sizeof(errbuffer), "Could not open file |%s| - check existence/rights\n", source); 
    exitHandler(1, errbuffer); 
} 

看来,这是唯一的简单方法。

感谢所有。

+0

'configfile [strlen(configfile)-1] ='\ 0';'当configfile [0] == 0时产生UB。这是偶然的罕见事件,但也可能是黑客利用。 – chux

+0

这不是一个好的解决方案,而且您似乎还添加了一项要求**使用最新的文件作为配置文件**。 – Attie