简体   繁体   English

C - 从文件中读取特定行

[英]C - read specific line from file

I'm trying to read a specific line from a file and I can get the line number but I'm not sure how to go about doing it, this is what I have so far: 我正在尝试从文件中读取一个特定的行,我可以得到行号,但我不知道如何去做,这是我到目前为止:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  FILE *file;
  file = fopen("temp.txt","r");
  char tmp[256]={0x0};
  char *tmpline;
  int numline = 1;
  while(file != NULL && fgets(tmp, sizeof(tmp),file) !=NULL)
  {
    tmpline = strstr(tmp,"status:green");

    if(tmpline) {
      printf("%d - %s", numline, tmpline);
    }

    numline++;
  }
  if (file != NULL) fclose(file);

  return 0;
}

The test file looks like: 测试文件如下所示:

s1.server.com
127.0.0.1 
status:green

s2.server.com
127.0.0.1 
status:red

s3.server.com
127.0.0.1 
status:red

s4.server.com
127.0.0.1 
status:green

The output that I have is: 我的输出是:

3 - status:green 
15 - status:green

But what I really want it to show is: 但我真正希望它展示的是:

s1.server.com
s4.server.com

I want it to search for "status:green" then go back a few lines to show which server it belongs to 我希望它搜索“status:green”然后返回几行以显示它属于哪个服务器

It sounds as if you need to do one of two things. 听起来好像你需要做两件事之一。

Simpler option : keep a little circular buffer of lines. 更简单的选项 :保持一个小的循环缓冲线。 Read into line 0, line 1, line 2, ..., line n-1, line 0, line 1, etc. Then, when you see the text you want, look in entry (current_index - 2) mod buffer_size. 读入第0行,第1行,第2行,...,第n-1行,第0行,第1行等。然后,当您看到所需的文本时,请查看条目(current_index - 2)mod buffer_size。 (Here it sounds as if a buffer size of 3 will suffice.) (听起来好像缓冲区大小为3就足够了。)

More sophisticated option : actually parse the input so that for each block you work out the server name, its IP address and its status, and then display the information you need using that. 更复杂的选项 :实际解析输入,以便为每个块计算服务器名称,IP地址和状态,然后使用它来显示所需的信息。

The "more sophisticated option" would be substantially more work, but more robust if the syntax of your input ever changes (eg, with optional extra lines with more information about the server -- multiple IP addresses or multiple names, perhaps). 如果输入的语法发生变化(例如,使用可选的额外行以及有关服务器的更多信息 - 可能是多个IP地址或多个名称),“更复杂的选项”将更加有效,但更强大。

There are some other things you could do that I think are worse. 还有一些你可以做的事我认为更糟糕。 (1) Call ftell on each line and put the results of that in a circular buffer, and then use fseek when you see "status:green". (1)调用ftell每行和放结果在一个环形缓冲区,然后用fseek当你看到“状态:绿色”。 (2) Read the whole file using code like you currently have, building up a list of "good" servers' line numbers. (2)使用您当前拥有的代码读取整个文件,构建“好”服务器的行号列表。 Then go through the file again and report the good ones. 然后再次浏览该文件并报告好的文件。 I think these are both uglier and less efficient than the approaches I listed above. 我认为这些都比我上面列出的方法更丑陋,效率更低。 There's one possible advantage: you can adapt them to count in "stanzas" separated by blank lines, without needing to parse things properly. 有一个可能的优点:你可以调整它们来计算用空行分隔的“节”,而不需要正确解析事物。 That would get you part of the flexibility of the "more sophisticated" approach I mentioned, without needing a proper parser. 这将使您获得我提到的“更复杂”方法的灵活性,而无需适当的解析器。

And here's a hybrid possibility: don't use a circular buffer, but one whose size can increase if need be. 这里有一个混合的可能性:不要使用循环缓冲区,但如果需要,可以增加其大小。 Start at the first entry in the buffer each time you see a blank line. 每次看到空白行时,从缓冲区中的第一个条目开始。 Let the buffer grow if there are "long" stanzas. 如果有“长”节,请让缓冲区增长。 Then when you see "status:green", do whatever processing you need to on the (presumably complete) stanza now held in your buffer. 然后,当您看到“status:green”时,对缓冲区中现在(可能是完整的)节进行任何处理。

None of the above is necessary, of course, if you're sure that the file format will never change. 当然,如果您确定文件格式永远不会改变,则上述所有内容都不是必需的。

If the test file (and production file) is well-formed then you can do something like the following (error checking left out for brevity!): 如果测试文件(和生产文件)格式正确,那么您可以执行以下操作(为简洁起见,请忽略错误检查!):

typedef struct _SERVERSTATUS
{
    char* name;
    char* ip;
    char* status;
} SERVERSTATUS;


SERVERSTATUS ss;

ss.name = calloc(256);
ss.ip = calloc(256);
ss.status = calloc(256);

while (!feof(file))
{
    fgets(ss.name, file);
    fgets(ss.ip, file);
    fgets(ss.status, file);

    if (!strcmp(ss.status, "status:green"))
       printf("%s\n", ss.name);
}

free(ss.name);
free(ss.ip);
free(ss.status);

Edit: You also have to handle the whitespace between the file entries! 编辑:您还必须处理文件条目之间的空白! That's, um, left as an exercise for the questioner 那是,嗯,留下作为提问者的练习

Read the first and third lines in each group. 阅读每组中的第一行和第三行。 Search for status:green and, if found, print the server name. 搜索status:green ,如果找到,则打印服务器名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM