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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3463426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:08:53  来源:igfitidea点击:

In C, how should I read a text file and print all strings

cfiletext-files

提问by Richard

I have a text file named test.txt

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

I want to write a C program that can read this file and print the content to the console (assume the file contains only ASCII text).

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

I don't know how to get the size of my string variable. Like this:

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

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

The size 999doesn't work because the string returned by fscanfcan be larger than that. How can I solve this?

大小999不起作用,因为返回的字符串fscanf可能比它大。我该如何解决这个问题?

回答by Alok Singhal

The simplest way is to read a character, and print it right after reading:

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

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

cis intabove, since EOFis a negative number, and a plain charmay be unsigned.

cint上面的,因为EOF是负数,而普通的char可能是unsigned

If you want to read the file in chunks, but without dynamic memory allocation, you can do:

如果你想分块读取文件,但没有动态内存分配,你可以这样做:

#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);
}

The second method above is essentially how you will read a file with a dynamically allocated array:

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

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 */
}

Your method of fscanf()with %sas format loses information about whitespace in the file, so it is not exactly copying a file to stdout.

您的fscanf()with %sas 格式方法会丢失文件中有关空格的信息,因此它并没有完全将文件复制到stdout.

回答by lfzawacki

There are plenty of good answers here about reading it in chunks, I'm just gonna show you a little trick that reads all the content at once to a buffer and prints it.

这里有很多关于分块阅读的好答案,我只是要向您展示一个小技巧,将所有内容一次读取到缓冲区并打印出来。

I'm not saying it's better. It's not, and as Ricardo sometimes it can be bad, but I find it's a nice solution for the simple cases.

我不是说它更好。事实并非如此,因为 Ricardo 有时可能会很糟糕,但我发现对于简单的情况,这是一个不错的解决方案。

I sprinkled it with comments because there's a lot going on.

我在其中添加了评论,因为发生了很多事情。

#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 
#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;
}
in the last position // and buffer is now officially a string buffer[string_size] = '
ssize_t read(int fildes, void *buf, size_t nbyte);
'; 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; }

Let me know if it's useful or you could learn something from it :)

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

回答by Sagar Shah

Instead just directly print the characters onto the console because the text file maybe very large and you may require a lot of memory.

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

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

回答by DVK

Use "read()" instead o fscanf:

使用“read()”代替 fscanf:

char *fgets(char *str, int num, FILE *stream);

DESCRIPTION

The read() function shall attempt to read nbytebytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf.

描述

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

Here is an example:

下面是一个例子:

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

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

Working part from that example:

该示例的工作部分:

while (fgets(str, 100, file)) /* printf("%s", str) */;


An alternate approach is to use getc/putcto read/write 1 char at a time. A lot less efficient. A good example: http://www.eskimo.com/~scs/cclass/notes/sx13.html

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

回答by Edu

You can use fgetsand limit the size of the read string.

您可以使用fgets和限制读取字符串的大小。

#include <stdio.h>
#include <stdlib.h>
int main() {

int num;
FILE *fptr; 



if ((fptr = fopen("/root/Desktop/my_pass.txt","r")) == NULL) {       // checks if file exists
    puts("File not exists");
    exit(1);                    // for exit(1) is required #include <stdlib.h> 
} else 

fscanf(fptr,"%d", &num);                

printf("My pass is:  %d\n", num);           
fclose(fptr); 

return 0;
}

You can change the whilein your code to:

您可以while将代码中的更改为:

#include <stdio.h>
#define BLOCK   1000

int main() {
    FILE *f=fopen("teste.txt","r");
    int size;
    char buffer[BLOCK];
    // ...
    while((size=fread(buffer,BLOCK,sizeof(char),f)>0)
            fwrite(buffer,size,sizeof(char),stdout);
    fclose(f);
    // ...
    return 0;
}

回答by RBerteig

Two approaches leap to mind.

想到了两种方法。

First, don't use scanf. Use fgets()which takes a parameter to specify the buffer size, and which leaves any newline characters intact. A simple loop over the file that prints the buffer content should naturally copy the file intact.

首先,不要使用scanf. 使用fgets()which 接受一个参数来指定缓冲区大小,并保留所有换行符不变。打印缓冲区内容的文件上的简单循环应该自然地完整地复制文件。

Second, use fread()or the common C idiom with fgetc(). These would process the file in fixed-size chunks or a single character at a time.

其次,使用fread()或 常见的 C 习语fgetc()。这些将一次处理固定大小的块或单个字符的文件。

If you must process the file over white-space delimited strings, then use either fgetsor freadto read the file, and something like strtokto split the buffer at whitespace. Don't forget to handle the transition from one buffer to the next, since your target strings are likely to span the buffer boundary.

如果您必须通过空格分隔的字符串处理文件,则使用fgetsfread读取文件,以及strtok在空格处拆分缓冲区之类的东西。不要忘记处理从一个缓冲区到下一个缓冲区的转换,因为您的目标字符串可能跨越缓冲区边界。

If there is an external requirement to use scanfto do the reading, then limit the length of the string it might read with a precision field in the format specifier. In your case with a 999 byte buffer, then say scanf("%998s", str);which will write at most 998 characters to the buffer leaving room for the nul terminator. If single strings longer than your buffer are allowed, then you would have to process them in two pieces. If not, you have an opportunity to tell the user about an error politely without creating a buffer overflow security hole.

如果有外部要求用于scanf读取,则使用格式说明符中的精度字段限制它可能读取的字符串的长度。在您使用 999 字节缓冲区的情况下,然后说scanf("%998s", str);哪个最多将 998 个字符写入缓冲区,为 nul 终止符留出空间。如果允许比缓冲区长的单个字符串,则必须将它们分成两部分进行处理。如果没有,您就有机会礼貌地告诉用户错误,而不会造成缓冲区溢出安全漏洞。

Regardless, always validate the return values and think about how to handle bad, malicious, or just malformed input.

无论如何,始终验证返回值并考虑如何处理错误的、恶意的或格式错误的输入。

回答by Odin

##代码##

回答by rigon

You could read the entire file with dynamic memory allocation, but isn't a good idea because if the file is too big, you could have memory problems.

您可以使用动态内存分配读取整个文件,但这不是一个好主意,因为如果文件太大,您可能会遇到内存问题。

So is better read short parts of the file and print it.

所以最好阅读文件的简短部分并打印出来。

##代码##