在C中,我应该如何读取文本文件并打印所有string
我有一个名为test.txt
的文本文件
我想写一个C程序,可以读取这个文件,并将内容打印到控制台(假定文件只包含ASCII文本)。
我不知道如何获得我的stringvariables的大小。 喜欢这个:
char str[999]; FILE * file; file = fopen( "test.txt" , "r"); if (file) { while (fscanf(file, "%s", str)!=EOF) printf("%s",str); fclose(file); }
999
的大小不起作用,因为fscanf
返回的string可能比这个大。 我该如何解决这个问题?
最简单的方法是阅读一个字符,并在阅读后立即打印:
int c; FILE *file; file = fopen("test.txt", "r"); if (file) { while ((c = getc(file)) != EOF) putchar(c); fclose(file); }
c
是上面的int
,因为EOF
是一个负数,并且一个普通的char
可以是unsigned
。
如果你想以块的forms读取文件,但是没有dynamic内存分配,你可以这样做:
#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); }
上述第二种方法基本上是如何读取具有dynamic分配数组的文件:
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 */ }
你的方法fscanf()
与%s
作为格式丢失有关文件中的空白信息,所以它不完全复制文件到stdout
。
这里有很多关于大块阅读的很好的答案,我只是要告诉你一个小技巧,一次读取所有的内容到缓冲区并打印出来。
我不是说这样比较好 事实并非如此,正如里卡多有时可能不好,但我觉得这是一个很好的解决scheme。
因为有很多事情发生,所以我把它和评论撒在一起。
#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; }
让我知道如果它是有用的,或者你可以从中学到东西:)
而是直接将字符打印到控制台上,因为文本文件可能非常大,而且您可能需要大量的内存。
#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; }
使用“read()”而不是fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
描述
read()函数将尝试从与打开的文件描述符
fildes
关联的文件中读取nbyte
字节到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);
另一种方法是使用getc
/ putc
来一次读取/写入1个字符。 效率低很多 一个很好的例子: http : //www.eskimo.com/~scs/cclass/notes/sx13.html
有两种方法可以跳跃。
首先,不要使用scanf
。 使用fgets()
需要一个参数来指定缓冲区大小,并保持任何换行符不变。 打印缓冲区内容的文件的一个简单的循环应该自然地完整地复制文件。
其次,使用fread()
或fgetc()
的通用C语言。 这些将一次处理固定大小的块或单个字符的文件。
如果你必须通过以空格分隔的string来处理文件,那么使用fgets
或者fread
来读取文件,以及像strtok
这样的以空格分隔缓冲区的东西。 不要忘记处理从一个缓冲区到下一个缓冲区的转换,因为您的目标string可能跨越缓冲区边界。
如果有外部要求使用scanf
进行读取,则使用格式说明符中的精度字段限制可能读取的string的长度。 在你的情况下,一个999字节的缓冲区,然后说scanf("%998s", str);
这将写入最多998个字符的缓冲区,为nul终止符留下空间。 如果允许单个string长于缓冲区,那么您将不得不将它们分成两部分。 如果没有,你有机会有礼貌地告诉用户一个错误,而不会造成缓冲区溢出安全漏洞。
无论如何,请始终validation返回值,并考虑如何处理不良,恶意或错误的input。
您可以使用fgets并限制读取string的大小。
char * fgets ( char * str, int num, FILE * stream );
在你的代码中,你可以改变:
while(fgets(str, 100, file) != EOF)
您可以使用dynamic内存分配来读取整个文件,但不是一个好主意,因为如果文件太大,可能会出现内存问题。
所以更好地阅读文件的短小部分并打印出来。
#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; }