파일 내용을 C 문자열로 읽는 방법은 무엇입니까?
C에서 파일을 열고 그 내용을 문자열(char*, char[] 등)로 읽는 가장 간단한 방법(오류 발생률이 가장 낮고 코드 행이 가장 적은 방법)은 무엇입니까?
버퍼 전체를 raw memory chunk로 메모리에 로드하여 스스로 해석하는 경향이 있습니다.그러면 표준 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);
반면에 윈도우는 조금 더 까다롭고 불행히도 테스트할 컴파일러는 없지만 기능은 다음과 같습니다.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 */
stdin이나 파이프와 같은 특수 파일을 읽는 경우 fstat를 사용하여 파일 크기를 미리 가져올 수 없습니다.또한 바이너리 파일 fget을 읽는 경우 '\0' 문자가 포함되어 있기 때문에 문자열 크기 정보가 손실됩니다.파일을 읽는 가장 좋은 방법은 읽기 및 재할당을 사용하는 것입니다.
#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;
}
주의: 이것은 위에서 수락한 답변을 수정한 것입니다.
에러 체크를 완료하고, 이 방법을 소개합니다.
파일이 1 GiB보다 클 때 종료할 크기 체커를 추가했습니다.프로그램이 전체 파일을 너무 많은 램을 사용하고 컴퓨터가 크래시 될 수 있는 문자열에 넣기 때문에 이렇게 했습니다.다만, 그것이 마음에 들지 않는 경우는, 코드에서 삭제해 주세요.
#include <stdio.h>
#include <stdlib.h>
#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TOO_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 whole large file in one string
if (length > 1073741824) {
*err = FILE_TOO_LARGE;
return NULL;
}
buffer = (char *)malloc(length + 1);
if (length) {
read_length = fread(buffer, 1, length, f);
if (length != read_length) {
free(buffer);
*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
}
else {
// process data
free(f_data);
}
파일이 텍스트이고 텍스트를 한 줄씩 가져오려면 fgets()를 사용하는 것이 가장 쉬운 방법입니다.
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
★★★★★★★★★를 사용하고 있는 경우는glib
g_file_get_module을 사용할 수 있습니다.
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);
}
}
위의 답변에서 방금 수정했습니다.
#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;
}
아무것도 null에 대해 체크되지 않기 때문에 이것은 매우 조잡한 해결책입니다.
참고로 여기 답변에 따라 나만의 버전을 추가하겠습니다.제 코드는 크기(char)를 고려하여 코멘트를 추가합니다.
// 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);
C에서 파일을 열고 내용을 문자열로 읽는 가장 간단한 방법(오류 발생률이 가장 낮고 코드 행이 가장 적은 방법, 그러나 해석하고 싶은 경우)은 무엇입니까?
슬프게도, 몇 년이 지난 후의 답변은 오류가 발생하기 쉽고 많은 답변이 적절한 문자열 형성이 결여되어 있습니다.
#include <stdio.h>
#include <stdlib.h>
// Read the file into allocated memory.
// Return NULL on error.
char* readfile(FILE *f) {
// f invalid? fseek() fail?
if (f == NULL || fseek(f, 0, SEEK_END)) {
return NULL;
}
long length = ftell(f);
rewind(f);
// Did ftell() fail? Is the length too long?
if (length == -1 || (unsigned long) length >= SIZE_MAX) {
return NULL;
}
// Convert from long to size_t
size_t ulength = (size_t) length;
char *buffer = malloc(ulength + 1);
// Allocation failed? Read incomplete?
if (buffer == NULL || fread(buffer, 1, ulength, f) != ulength) {
free(buffer);
return NULL;
}
buffer[ulength] = '\0'; // Now buffer points to a string
return buffer;
}
텍스트 파일에 늘 문자가 포함되어 있는 경우 할당된 데이터에는 모든 파일 데이터가 포함되지만 문자열은 짧은 것으로 나타납니다.더 나은 코드는 발신자가 처리할 수 있도록 길이 정보도 반환합니다.
char* readfile(FILE *f, size_t *ulength_ptr) {
...
if (ulength_ptr) *ulength_ptr == *ulength;
...
}
쉽고 깔끔한(파일의 내용이 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' 카테고리의 다른 글
Java 문자열 비교 방법 (0) | 2022.07.30 |
---|---|
메서드에서 메서드를 하나만 호출합니다. (0) | 2022.07.30 |
스택 할당, 패딩 및 정렬 (0) | 2022.07.30 |
불투명 데이터 유형의 정적 할당 (0) | 2022.07.30 |
Vuejs - 템플릿의 헤더 섹션을 부모로 이동 (0) | 2022.07.30 |