将文本文件读入 C 缓冲区的正确方法? [英] Correct way to read a text file into a buffer in C?
问题描述
我正在处理我想在处理它们时读入缓冲区的小文本文件,所以我想出了以下代码:
<代码>...字符源[1000000];FILE *fp = fopen("TheFile.txt", "r");如果(fp != NULL){而((符号= getc(fp))!= EOF){strcat(源代码,&符号);}fclose(fp);}...
这是将文件内容放入缓冲区的正确方法还是我滥用了strcat()
?
然后我这样遍历缓冲区:
for(int x = 0; (c = source[x]) != ' '; x++){//处理字符}
char source[1000000];FILE *fp = fopen("TheFile.txt", "r");如果(fp != NULL){而((符号= getc(fp))!= EOF){strcat(源代码,&符号);}fclose(fp);}
这段代码有很多问题:
- 它非常慢(您一次提取一个字符的缓冲区).
- 如果文件大小超过
sizeof(source)
,这很容易导致缓冲区溢出. - 真的,当你更仔细地观察它时,这段代码根本不应该工作.如手册页所述:
<块引用><块引用>
strcat()
函数将空终止字符串 s2 的副本附加到空终止字符串 s1 的末尾,然后添加一个终止` '.
您将一个字符(不是以 NUL 结尾的字符串!)附加到一个可能以或不以 NUL 结尾的字符串中.唯一时间,根据手册页的描述,如果文件中的每个字符都以 NUL 结尾,我可以想象这种工作是否有效,在这种情况下,这将毫无意义.所以是的,这绝对是对 strcat()
的严重滥用.
以下是可以考虑使用的两种替代方法.
如果您提前知道最大缓冲区大小:
#include #define MAXBUFLEN 1000000字符源[MAXBUFLEN + 1];FILE *fp = fopen("foo.txt", "r");如果(fp != NULL){size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);如果 ( ferror( fp ) != 0 ) {fputs("读取文件出错", stderr);} 别的 {源[newLen++] = ' ';/* 只是为了安全.*/}fclose(fp);}
或者,如果您不这样做:
#include #include 字符 * 源 = NULL;FILE *fp = fopen("foo.txt", "r");如果(fp != NULL){/* 转到文件末尾.*/如果(fseek(fp,0L,SEEK_END)== 0){/* 获取文件的大小.*/long bufsize = ftell(fp);if (bufsize == -1) {/* 错误 */}/* 将我们的缓冲区分配到那个大小.*/source = malloc(sizeof(char) * (bufsize + 1));/* 回到文件的开头.*/if (fseek(fp, 0L, SEEK_SET) != 0) {/* 错误 */}/* 将整个文件读入内存.*/size_t newLen = fread(source, sizeof(char), bufsize, fp);如果 ( ferror( fp ) != 0 ) {fputs("读取文件出错", stderr);} 别的 {源[newLen++] = ' ';/* 只是为了安全.*/}}fclose(fp);}免费(来源);/* 不要忘记稍后调用 free()!*/
I'm dealing with small text files that i want to read into a buffer while i process them, so i've come up with the following code:
...
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
...
Is this the correct way of putting the contents of the file into the buffer or am i abusing strcat()
?
I then iterate through the buffer thus:
for(int x = 0; (c = source[x]) != ' '; x++)
{
//Process chars
}
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
There are quite a few things wrong with this code:
- It is very slow (you are extracting the buffer one character at a time).
- If the filesize is over
sizeof(source)
, this is prone to buffer overflows. - Really, when you look at it more closely, this code should not work at all. As stated in the man pages:
The
strcat()
function appends a copy of the null-terminated string s2 to the end of the null-terminated string s1, then add a terminating ` '.
You are appending a character (not a NUL-terminated string!) to a string that may or may not be NUL-terminated. The only time I can imagine this working according to the man-page description is if every character in the file is NUL-terminated, in which case this would be rather pointless. So yes, this is most definitely a terrible abuse of strcat()
.
The following are two alternatives to consider using instead.
If you know the maximum buffer size ahead of time:
#include <stdio.h>
#define MAXBUFLEN 1000000
char source[MAXBUFLEN + 1];
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = ' '; /* Just to be safe. */
}
fclose(fp);
}
Or, if you do not:
#include <stdio.h>
#include <stdlib.h>
char *source = NULL;
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = ' '; /* Just to be safe. */
}
}
fclose(fp);
}
free(source); /* Don't forget to call free() later! */
这篇关于将文本文件读入 C 缓冲区的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!