在C中,我应该如何阅读文本文件并打印所有字符串

Ric*_*ard 81 c file text-files

我有一个名为的文本文件 test.txt

我想编写一个可以读取此文件并将内容打印到控制台的C程序(假设该文件仅包含ASCII文本).

我不知道如何获取我的字符串变量的大小.像这样:

char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF)
        printf("%s",str);
    fclose(file);
}
Run Code Online (Sandbox Code Playgroud)

大小999不起作用,因为返回的字符串fscanf可能大于该值.我怎么解决这个问题?

Alo*_*hal 121

最简单的方法是读取一个字符,并在阅读后立即打印:

int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
    while ((c = getc(file)) != EOF)
        putchar(c);
    fclose(file);
}
Run Code Online (Sandbox Code Playgroud)

cint上面,因为EOF是负数,而平原char可能是unsigned.

如果要以块的形式读取文件,但没有动态内存分配,则可以执行以下操作:

#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;

file = fopen("test.txt", "r");
if (file) {
    while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
        fwrite(buf, 1, nread, stdout);
    if (ferror(file)) {
        /* deal with error */
    }
    fclose(file);
}
Run Code Online (Sandbox Code Playgroud)

上面的第二种方法实质上是如何使用动态分配的数组读取文件:

char *buf = malloc(chunk);

if (buf == NULL) {
    /* deal with malloc() failure */
}

/* otherwise do this.  Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
    /* as above */
}
Run Code Online (Sandbox Code Playgroud)

fscanf()使用%sas格式的方法会丢失有关文件中空格的信息,因此不会将文件复制到stdout.


lfz*_*cki 54

这里有很多关于以块状态阅读它的好答案,我将向您展示一个小技巧,它将所有内容一次性读取到缓冲区并打印出来.

我不是说它更好.事实并非如此,而里卡多有时可能会很糟糕,但我觉得这对于简单的案例来说是一个很好的解决方案.

我在评论中撒了一些,因为有很多事情要发生.

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

char* ReadFile(char *filename)
{
   char *buffer = NULL;
   int string_size, read_size;
   FILE *handler = fopen(filename, "r");

   if (handler)
   {
       // Seek the last byte of the file
       fseek(handler, 0, SEEK_END);
       // Offset from the first to the last byte, or in other words, filesize
       string_size = ftell(handler);
       // go back to the start of the file
       rewind(handler);

       // Allocate a string that can hold it all
       buffer = (char*) malloc(sizeof(char) * (string_size + 1) );

       // Read it all in one operation
       read_size = fread(buffer, sizeof(char), string_size, handler);

       // fread doesn't set it so put a \0 in the last position
       // and buffer is now officially a string
       buffer[string_size] = '\0';

       if (string_size != read_size)
       {
           // Something went wrong, throw away the memory and set
           // the buffer to NULL
           free(buffer);
           buffer = NULL;
       }

       // Always remember to close the file.
       fclose(handler);
    }

    return buffer;
}

int main()
{
    char *string = ReadFile("yourfile.txt");
    if (string)
    {
        puts(string);
        free(string);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

让我知道它是否有用或者你可以从中学到一些东西:)

  • 使用`ftell`和`fseek`来查找文件的大小是不安全的:https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek() +和+ FTELL()+至+计算+ + A +定期+文件的大小+ + (3认同)
  • 您可以使用 `calloc(2)` 而不是 `malloc(1)` 来跳过必须设置空终止符的步骤。 (3认同)
  • 它不应该读为 `buffer[string_size] = '\0';` 而不是 `string_size+1` 吗?Afaik 实际字符串从`0` 到`string_size-1` 并且`\0` 字符因此需要在`string_size`,对吗? (2认同)

Sag*_*hah 13

而是直接将字符打印到控制台上,因为文本文件可能非常大,您可能需要大量内存.

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

int main() {

    FILE *f;
    char c;
    f=fopen("test.txt","rt");

    while((c=fgetc(f))!=EOF){
        printf("%c",c);
    }

    fclose(f);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


DVK*_*DVK 6

使用"read()"代替o fscanf:

ssize_t read(int fildes, void *buf, size_t nbyte);
Run Code Online (Sandbox Code Playgroud)

描述

read()函数应尝试nbyte从与打开文件描述符相关联的文件中读取字节,并将其读fildes入指向的缓冲区buf.

这是一个例子:

http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html

该例子的工作部分:

f=open(argv[1],O_RDONLY);
while ((n=read(f,l,80)) > 0)
    write(1,l,n);
Run Code Online (Sandbox Code Playgroud)

另一种方法是一次使用getc/ putc来读/写1个字符.效率低很多.一个很好的例子:http://www.eskimo.com/~scs/cclass/notes/sx13.html