多次打开和关闭文本文件并从延续中阅读

发布于 2025-02-03 13:09:41 字数 69 浏览 2 评论 0 原文

我有一个文本文件,然后将其打开并阅读其中一行,然后关闭文本文件。我在循环下调用我的功能,但是每次此函数都读取文本文件的第一行

I have a text file, and I open it and read one line of it, and close the text file. I'm calling my function under a for loop, but each time this function reads the first line of a text file, how can I fix it to read from the continuation

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

土豪 2025-02-10 13:09:41

can 使用 fseek 在关闭和重新打开后将自己重新定位在文件中,但是这样做是非常不寻常的。实际上,如此不寻常,以至于我认为这是完全错误的。这是一些示例代码,演示了如何执行此操作以及更典型的循环。这里的每个循环都会读取文件的前2行,假设每行都足够小。处理长行超出了这个问题的范围。

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

FILE * xfopen(const char *path, const char *mode);
void xfseek(FILE *stream, long offset, int whence, const char *);
long xftell(FILE *stream, const char *);
void xfclose(FILE *stream, const char *);


int
main(int argc, char *argv[])
{
    const char *path = argc > 1 ? argv[1] : "input";

    /* Read the first two lines of the file, closing the file on each
     * iteration. This is ** not ** the usual way to do this, and is
     * included here for demonstration
     * purposes only.  DO NOT DO THIS.
     * It is very unusual to close and re-open the file on each iteration.
     */
    long position = 0;
    for( int line = 1; line < 3; line++ ){
        FILE *ifp = xfopen(path, "r");
        char buf[1024];
        xfseek(ifp, position, SEEK_SET, path);
        fgets(buf, sizeof buf, ifp);  /* (1) */
        printf("line %d: %s", line, buf);
        position = xftell(ifp, path);
        xfclose(ifp, path);  /* !! */
    }

    /* The more usual way to read each line of a file is to simply
     * read it with repeated calls to the appropriate read method
     * (fgets, fread, fgetc, etc.)  Each subsequent read starts
     * where the previous read finished.
     */
    FILE *ifp = xfopen(path, "r");
    for( int line = 1; line < 3; line++ ){
        char buf[1024];
        fgets(buf, sizeof buf, ifp);  /* (1) */
        printf("line %d: %s", line, buf);
    }
    xfclose(ifp, path);
    return 0;
}



FILE *
xfopen(const char *path, const char *mode)
{
    FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
        *mode == 'r' ? stdin : stdout;
    if( fp == NULL ){
        perror(path);
        exit(EXIT_FAILURE);
    }
    return fp;
}


void
xfseek(FILE *stream, long offset, int whence, const char *name)
{
    if( fseek(stream, offset, whence) == -1){
        perror(name);
        exit(EXIT_FAILURE);
    }
}

long
xftell(FILE *stream, const char *name)
{
    long ret = ftell(stream);
    if( ret == -1 ){
        perror(name);
        exit(EXIT_FAILURE);
    }
    return ret;
}

void
xfclose(FILE *stream, const char *name)
{
    if( fclose(stream) ){
        perror(name);
        exit(EXIT_FAILURE);
    }
}

注意:(1)它是读者的练习。将其作为一种练习也许有点像是有点淘汰,但是处理这些问题的烦恼强烈指向使用标准成语的原因。如果要打印文件的前两行,请使用的某些变体(int count = 0;(c = fgetc(fp))!= null&amp;&amp; count&lt; 2;){如果(c =='\ n')count += 1; putchar(c); } 。将读取功能作为循环的条件(几乎)总是最好的选择。

You can use fseek to reposition yourself in the file after closing and reopening, but it is very unusual to do so. So unusual, in fact, that I would suggest it is completely wrong. Here's some sample code that demonstrates how to do that, as well as a more typical loop. Each loop here reads the first 2 lines of the file, assuming each line is sufficiently small; handling long lines is beyond the scope of this question.

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

FILE * xfopen(const char *path, const char *mode);
void xfseek(FILE *stream, long offset, int whence, const char *);
long xftell(FILE *stream, const char *);
void xfclose(FILE *stream, const char *);


int
main(int argc, char *argv[])
{
    const char *path = argc > 1 ? argv[1] : "input";

    /* Read the first two lines of the file, closing the file on each
     * iteration. This is ** not ** the usual way to do this, and is
     * included here for demonstration
     * purposes only.  DO NOT DO THIS.
     * It is very unusual to close and re-open the file on each iteration.
     */
    long position = 0;
    for( int line = 1; line < 3; line++ ){
        FILE *ifp = xfopen(path, "r");
        char buf[1024];
        xfseek(ifp, position, SEEK_SET, path);
        fgets(buf, sizeof buf, ifp);  /* (1) */
        printf("line %d: %s", line, buf);
        position = xftell(ifp, path);
        xfclose(ifp, path);  /* !! */
    }

    /* The more usual way to read each line of a file is to simply
     * read it with repeated calls to the appropriate read method
     * (fgets, fread, fgetc, etc.)  Each subsequent read starts
     * where the previous read finished.
     */
    FILE *ifp = xfopen(path, "r");
    for( int line = 1; line < 3; line++ ){
        char buf[1024];
        fgets(buf, sizeof buf, ifp);  /* (1) */
        printf("line %d: %s", line, buf);
    }
    xfclose(ifp, path);
    return 0;
}



FILE *
xfopen(const char *path, const char *mode)
{
    FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
        *mode == 'r' ? stdin : stdout;
    if( fp == NULL ){
        perror(path);
        exit(EXIT_FAILURE);
    }
    return fp;
}


void
xfseek(FILE *stream, long offset, int whence, const char *name)
{
    if( fseek(stream, offset, whence) == -1){
        perror(name);
        exit(EXIT_FAILURE);
    }
}

long
xftell(FILE *stream, const char *name)
{
    long ret = ftell(stream);
    if( ret == -1 ){
        perror(name);
        exit(EXIT_FAILURE);
    }
    return ret;
}

void
xfclose(FILE *stream, const char *name)
{
    if( fclose(stream) ){
        perror(name);
        exit(EXIT_FAILURE);
    }
}

Notes: (1) It is left as an exercise for the reader how best to handle short reads (eg, when fgets returns NULL) or long lines (eg, when fgets completely fills the buffer but fails to read an entire line). Perhaps it is a bit of a cop-out to leave that as an exercise, but the annoyance of dealing with those issues points strongly towards reasons for using the standard idiom. If you want to print the first two lines of the file, use some variation of for( int count = 0; (c = fgetc(fp)) != NULL && count < 2; ) { if( c == '\n' ) count += 1; putchar(c); }. Putting the read function as a condition of the loop is (almost) always the best choice.

菊凝晚露 2025-02-10 13:09:41

这些评论已经就您正在尝试的其他替代方案提出了建议。但是,无论是正确的方法,您所陈述的问题似乎很清楚,这很清楚要使用 fseek() et。在打开和关闭文件时查看连续的行。

要打开和关闭文件,每次访问并显示连续的行,您必须首先知道要查看的每个位置都位于该文件中。确实,正如您已经标记的那样, fseek(fseek() =“ https://www.tutorialspoint.com/c_standard_library/c_function_ftell.htm” rel =“ nofollow noreferrer”> ftell())可以使用。以下伪代码步骤说明了一种可能性:

//store file pointer locations of each line in file:
FILE *fp = fopen(fn, "r");
if(fp)
{
    for(int i = 0; i < l_cnt; i++)
    {
        pos[i] = ftell(fp);
        fgets(line, sizeof line, fp);
    }
}
fclose(fp);

然后...

//alternately open and close file to view successive lines at stored positions
for(int i = 0; i < line_cnt; i++)
{
    FILE *fp = fopen(fn, "r");
    if(fp)
    {
        fseek(fp, pos[i], 0);
        fgets(line, sizeof line, fp);
        printf("line %d: %s\n", i, line);
        fclose(fp);
    }       
} 

更完整

The comments have already made suggestions on other alternatives for what you are attempting. But regardless whether it is the right approach or not, it seems pretty clear that your stated ask is clear about wanting to use fseek() et. al to view successive lines when opening and closing a file.

To open and close a file, and each time access and display a successive line, you must first know where each of the locations to be viewed are located within that file. Indeed, as you have tagged, fseek(), (as well as ftell()) can be used to do this. The following pseudo code steps illustrate one possibility:

//store file pointer locations of each line in file:
FILE *fp = fopen(fn, "r");
if(fp)
{
    for(int i = 0; i < l_cnt; i++)
    {
        pos[i] = ftell(fp);
        fgets(line, sizeof line, fp);
    }
}
fclose(fp);

Then...

//alternately open and close file to view successive lines at stored positions
for(int i = 0; i < line_cnt; i++)
{
    FILE *fp = fopen(fn, "r");
    if(fp)
    {
        fseek(fp, pos[i], 0);
        fgets(line, sizeof line, fp);
        printf("line %d: %s\n", i, line);
        fclose(fp);
    }       
} 

There is a more complete source and run-time example here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文