Bad*_*dda 8 c io file fgets file-processing
我有一个文件,其中我想迭代而不处理当前行的任何类型.我正在寻找的是去确定文本文件行的最佳方法.例如,将当前行存储到变量中似乎没用,直到我到达预定行.
示例:
file.txt的
foo
fooo
fo
here
Run Code Online (Sandbox Code Playgroud)
通常,为了得到here,我会做的事情如下:
FILE* file = fopen("file.txt", "r");
if (file == NULL)
perror("Error when opening file ");
char currentLine[100];
while(fgets(currentLine, 100, file))
{
if(strstr(currentLine, "here") != NULL)
return currentLine;
}
Run Code Online (Sandbox Code Playgroud)
但是fgets必须完全阅读三行并且currentLine必须存储foo,fooo并且fo.
有没有更好的方法来做到这一点,知道here第4行?有点像go to文件?
您无法直接访问文本文件的给定行(除非所有行都具有相同的字节大小;并且对于UTF8, Unicode字符可以采用可变数量的字节,1到6;并且在大多数情况下,行具有各种长度 - 从一行到另一行不同).所以你不能使用fseek(因为你事先不知道文件偏移量).
但是(至少在Linux系统上),行以\n(换行符)结束.所以你可以逐字节读取并计算它们:
int c= EOF;
int linecount=1;
while ((c=fgetc(file)) != EOF) {
if (c=='\n')
linecount++;
}
Run Code Online (Sandbox Code Playgroud)
然后,您不需要存储整行.
因此,您可以通过这种方式到达第45行(使用while ((c=fgetc(file)) != EOF) && linecount<45)...),然后在POSIX系统上读取整行fgets或更好的getline(3)(参见本示例).请注意,执行fgets或getline很可能会再建fgetc,或至少与它分享一些代码.请记住,<stdio.h> 被缓冲的 I/O,见setvbuf用来(3)和相关的功能.
另一种方法是两遍读取文件.第一遍在一些有效的数据结构(向量,哈希表,树......)中存储每行开始的偏移量(使用ftell(3) ...).第二遍使用该数据结构来检索偏移量(行开始),然后使用fseek(3)(使用该偏移量).
第三种方式,POSIX特定,将使用mmap(2)将文件内存映射到您的虚拟地址空间(这适用于不太大的文件,例如小于几千兆字节).小心(您可能需要mmap一个额外的结束页面,以确保数据是零字节终止),然后您将能够使用strchr(3)与'\n'
PS.顺便说一下,线的概念(和行尾标记)因操作系统而异.在Linux上,行尾是一个\n字符.据传,Windows上的线路以等结尾\r\n......
小智 5
FILE *C中的A 是chars 的流.在可搜索文件中,您可以char使用文件指针来解决这些问题fseek().但除此之外,文件中没有"特殊字符",换行符只是另一个普通字符.
所以总之,不,你不能直接跳到文本文件的一行,只要你事先不知道行的长度.
C中的此模型对应于典型操作系统提供的文件.如果你考虑一下,要知道各行的起点,你的文件系统就必须在某处存储这些信息.这意味着要特别处理文本文件.
然而你可以做的只是计算线而不是模式匹配,如下所示:
#include <stdio.h>
int main(void)
{
char linebuf[1024];
FILE *input = fopen("seekline.c", "r");
int lineno = 0;
char *line;
while (line = fgets(linebuf, 1024, input))
{
++lineno;
if (lineno == 4)
{
fputs("4: ", stdout);
fputs(line, stdout);
break;
}
}
fclose(input);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
823 次 |
| 最近记录: |