如何从下往上逐行遍历文件?例如,这是我从上到下遍历它的代码:
void *readFileTB(char *str1)
{
int size = 1024;
char *buffer = malloc(size);
FILE *fp;
fp = fopen("testfile.txt", "r");
while(fgets(buffer, 1024, fp)) //get a line from a file
{
printf(buffer);
}
return 0;
}
如果文件包含:
line1onetest
line2twotest
line3threetest
如果执行此功能将打印以下内容:
line1onetest
line2twotest
line3threetest
如何编写一个执行上述功能但功能相反的函数,以便输出以下内容?
line3threetest
line2twotest
line1onetest
有什么想法吗?
答案 0 :(得分:5)
一行一行有点困难。如果我们从字节开始,那很简单:我们首先fseek
到底部之前一点:
if(fseek(fp, 256, SEEK_END) == -1) { /* handle error */ }
由于我们在结束之前寻找了256个字节,因此我们可以读取256个字节。然后我们可以回寻256个字节等,直到我们到达文件的顶部。
现在,如果您正在尝试读取文本行,这可能很棘手:您需要在文件末尾读取一些字节并找到最后一个换行符。如果没有,你就读不够,你需要阅读更多内容。一旦你找到它,你的线就从那里开始。要阅读下一行,您需要再次向后搜索,并且不要超过上一行开头。
答案 1 :(得分:4)
在这里,我对它进行了一些编码并对整个事情进行了编码。我不知道它是否有任何好处,但至少你可以了解它是如何工作的。 (我觉得有更好的方法可以做到这一点)
$ gcc -Wall -o reverser main.c
<强>用法:强>
$ ./reverser text.txt
text.txt内容:
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
结果:
}
return 0;
print_rev_file(argv[1]);
return 1;
if(argc != 2)
int main(int argc, char *argv[]){
<强>的main.c 强>
#include <header.h>
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
<强> header.h:强> 注意:使用双下划线是不好的形式,因为许多编译器都使用它们。
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
///SUPPORT for get_line
size_t __file_size(FILE ** file); //It'd make sense to homogenize the parameters...
char * __get_line_copy(FILE ** file, size_t chunk_size, size_t position);
char * __get_line(int line_number, FILE ** file, size_t chunk_size);
size_t __nth_line(FILE ** file, int line_number, size_t chunk_size);
unsigned int __line_count(FILE ** file, size_t chunk_size);
#define file_size(x) __file_size(&x)
size_t __file_size(FILE ** file){
size_t old_pos = ftell(*file);
fseek(*file, 0, SEEK_END);
int file_size = ftell(*file);
fseek(*file, 0, old_pos);
return file_size;
}
char * __get_line_copy(FILE ** file, size_t chunk_size, size_t position){
int i;
char c;
char * buffer = malloc(chunk_size);
memset(buffer, 0, chunk_size);
size_t old_pos = ftell(*file);
fseek(*file, position, SEEK_SET);
for(i = 0; (i < chunk_size && (c = fgetc(*file)) != '\n' && !feof(*file)); i++){
*(buffer+i) = c;
}
*(buffer+chunk_size) = '\0';
fseek(*file, 0, old_pos);
return buffer;
}
#define FIRST 0
#define LAST -1
#define get_line(x, y, z) __get_line(x, &y, z);
char * __get_line(int line_number, FILE ** file, size_t chunk_size){
char * line = __get_line_copy(file, chunk_size, __nth_line(file, line_number, chunk_size));
return line;
}
size_t __nth_line(FILE ** file, int line_number, size_t chunk_size){
int i = 0, index;
size_t old_pos = ftell(*file);
fseek(*file, 0, SEEK_SET);
if(line_number > 0){
while(i <= line_number && !feof(*file)){
if(fgetc(*file) == '\n')
i++;
}
} else {
while(!feof(*file)){
if(fgetc(*file) == '\n')
i++;
}
index = i + (line_number+1);
fseek(*file, 0, SEEK_SET);
int i = 0;
while(i < index){
if(fgetc(*file) == '\n')
i++;
}
}
size_t position = ftell(*file);
fseek(*file, 0, old_pos);
return position;
}
#define line_count(x, y) __line_count(&x, y)
unsigned int __line_count(FILE ** file, size_t chunk_size){
int i = 1;
while(!feof(*file))
if(fgetc(*file) == '\n')
i++;
return i;
}
int print_rev_file(char * filename, size_t buffer){
FILE * file = fopen(filename, "r");
if(file == NULL){
return -1;
}
int i, lines = line_count(file, buffer);
for(i = 0; i < lines; i++){
char * line = get_line(LAST-i, file, buffer);
puts(line);
free(line);
}
return 0;
}
int main(int argc, char *argv[]){
if(argc != 2)
return 1;
print_rev_file(argv[1], 64);
return 0;
}
答案 2 :(得分:1)
GNU coreutils中有一个名为 tac 的实用程序就是这样做的。
您可以在下面查看它的来源。
http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob_plain;f=src/tac.c;hb=HEAD