C에서 파일의 내용을 문자열로 읽는 방법은 무엇입니까?
C에서 파일을 열고 그 내용을 문자열 (char *, char [] 등)로 읽는 가장 간단한 방법 (오류 발생 가능성이 가장 적고 코드 줄이 가장 적지 만 해석하려는 경우)은 무엇입니까?
나는 전체 버퍼를 원시 메모리 청크로 메모리에로드하고 직접 구문 분석을 수행하는 경향이 있습니다. 이렇게하면 여러 플랫폼에서 표준 lib가 수행하는 작업을 가장 잘 제어 할 수 있습니다.
이것은 내가 이것을 위해 사용하는 스텁입니다. fseek, ftell 및 fread의 오류 코드를 확인할 수도 있습니다. (명확성을 위해 생략 됨).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data / extract strings here...
}
안타깝게도 OS 의존도가 높은 또 다른 솔루션은 파일에 대한 메모리 매핑입니다. 일반적으로 읽기 성능과 응용 프로그램보기 및 운영 체제 파일 캐시가 실제 메모리를 공유 할 수 있으므로 메모리 사용량이 줄어드는 이점이 있습니다.
POSIX 코드는 다음과 같습니다.
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
반면에 Windows는 조금 더 까다 롭고 불행히도 테스트 할 컴파일러가 없지만 기능은 CreateFileMapping()
및 MapViewOfFile()
.
"문자열로 내용을 읽음"이 파일에 코드 0의 문자가 포함되어 있지 않음을 의미하는 경우 getdelim () 함수를 사용할 수도 있습니다.이 함수는 메모리 블록을 받아 필요한 경우 재 할당하거나 전체 버퍼를 지정된 구분 기호 나 파일 끝을 만날 때까지 파일을 읽습니다. 전체 파일을 읽으려면 구분 기호로 '\ 0'을 전달하십시오.
이 기능은 GNU C 라이브러리, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994 에서 사용할 수 있습니다 .
샘플 코드는 다음과 같이 간단 해 보일 수 있습니다.
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp);
if ( bytes_read != -1) {
/* Success, now the entire file is in the buffer */
파일이 텍스트이고 텍스트를 한 줄씩 가져 오려면 가장 쉬운 방법은 fgets ()를 사용하는 것입니다.
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
stdin 또는 파이프와 같은 특수 파일을 읽는 경우 fstat를 사용하여 미리 파일 크기를 가져올 수 없습니다. 또한 바이너리 파일을 읽는 경우 fgets는 포함 된 '\ 0'문자로 인해 문자열 크기 정보를 잃게됩니다. 파일을 읽는 가장 좋은 방법은 read 및 realloc을 사용하는 것입니다.
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main () {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
참고 : 이것은 위에서 허용 된 답변을 수정 한 것입니다.
여기에 오류 검사를 완료하는 방법이 있습니다.
파일이 1GiB보다 클 때 종료 할 크기 검사기를 추가했습니다. 프로그램이 너무 많은 램을 사용하고 컴퓨터를 충돌시킬 수있는 문자열에 전체 파일을 넣기 때문에 이렇게했습니다. 그러나 신경 쓰지 않는다면 코드에서 제거 할 수 있습니다.
#include <stdio.h>
#include <stdlib.h>
#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TO_LARGE 2
#define FILE_READ_ERROR 3
char * c_read_file(const char * f_name, int * err, size_t * f_size) {
char * buffer;
size_t length;
FILE * f = fopen(f_name, "rb");
size_t read_length;
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
// 1 GiB; best not to load a hole large file in one string
if (length > 1073741824) {
*err = FILE_TO_LARGE;
return NULL;
}
buffer = (char *)malloc(length + 1);
if (length) {
read_length = fread(buffer, 1, length, f);
if (length != read_length) {
*err = FILE_READ_ERROR;
return NULL;
}
}
fclose(f);
*err = FILE_OK;
buffer[length] = '\0';
*f_size = length;
}
else {
*err = FILE_NOT_EXIST;
return NULL;
}
return buffer;
}
그리고 오류를 확인하려면 :
int err;
size_t f_size;
char * f_data;
f_data = c_read_file("test.txt", &err, &f_size);
if (err) {
// process error
}
If you're using glib
, then you can use g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Just modified from the accepted answer above.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
This is a pretty crude solution because nothing is checked against null.
I will add my own version, based on the answers here, just for reference. My code takes into consideration sizeof(char) and adds a few comments to it.
// Open the file in read mode.
FILE *file = fopen(file_name, "r");
// Check if there was an error.
if (file == NULL) {
fprintf(stderr, "Error: Can't open file '%s'.", file_name);
exit(EXIT_FAILURE);
}
// Get the file length
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);
// Create the string for the file contents.
char *buffer = malloc(sizeof(char) * (length + 1));
buffer[length] = '\0';
// Set the contents of the string.
fread(buffer, sizeof(char), length, file);
// Close the file.
fclose(file);
// Do something with the data.
// ...
// Free the allocated string space.
free(buffer);
easy and neat(assuming contents in the file are less than 10000):
void read_whole_file(char fileName[1000], char buffer[10000])
{
FILE * file = fopen(fileName, "r");
if(file == NULL)
{
puts("File not found");
exit(1);
}
char c;
int idx=0;
while (fscanf(file , "%c" ,&c) == 1)
{
buffer[idx] = c;
idx++;
}
buffer[idx] = 0;
}
참고URL : https://stackoverflow.com/questions/174531/how-to-read-the-content-of-a-file-to-a-string-in-c
'programing' 카테고리의 다른 글
Eclipse : 선언 된 패키지가 예상 패키지와 일치하지 않습니다. (0) | 2020.10.07 |
---|---|
IISExpress를 실행하는 로컬 호스트에 연결하려고 할 때 ERR_CONNECTION_REFUSED를 해결하는 방법-오류 502 (Visual Studio에서 디버그 할 수 없음)? (0) | 2020.10.07 |
어떤 유닉스 셸을 사용하고 있는지 어떻게 알 수 있습니까? (0) | 2020.10.07 |
rsync가 .htaccess 파일을 동기화하지 않습니다. (0) | 2020.10.07 |
Laravel Query Builder를 사용하여 하위 쿼리에서 선택하는 방법은 무엇입니까? (0) | 2020.10.07 |