C에서 텍스트 파일을 읽고 모든 문자열을 인쇄하는 방법


99

이름이 텍스트 파일이 있습니다. test.txt

이 파일을 읽고 내용을 콘솔에 인쇄 할 수있는 C 프로그램을 작성하고 싶습니다 (파일에 ASCII 텍스트 만 포함되어 있다고 가정).

내 문자열 변수의 크기를 얻는 방법을 모르겠습니다. 이렇게 :

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이 그보다 클 수 있기 때문에 크기 가 작동하지 않습니다 . 어떻게 해결할 수 있습니까?

답변:


139

가장 간단한 방법은 문자를 읽고 읽은 후 바로 인쇄하는 것입니다.

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

c는 음수 int이기 때문에 위이며 EOF일반 charunsigned.

동적 메모리 할당없이 파일을 청크로 읽으려면 다음을 수행 할 수 있습니다.

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

위의 두 번째 방법은 기본적으로 동적으로 할당 된 배열로 파일을 읽는 방법입니다.

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()with %sas 형식 의 방법은 파일의 공백에 대한 정보를 잃어 버리기 때문에 파일을 stdout.


c / c ++에서 파일을 열지 않고도 파일에서 데이터를 읽을 수 있습니까 ??
Sagar Patel

텍스트 파일에 쉼표로 구분 된 정수 값이 포함되어 있으면 어떻게됩니까? 코드가 무엇인지보다 대답을 편집 할 수 있습니다.
Mohsin

위의 내용은 모든 종류의 텍스트 파일에 적용됩니다. CSV 파일에서 숫자를 구문 분석하려면 다른 문제입니다.
Alok Singhal

1
@overexchange 질문은 줄에 대해 말하는 것이 아니라 파일을 읽고 그 내용을 stdout.
Alok Singhal

1
@shjeff 파일은 EOF 문자를 포함 할 수 없습니다. 참고 cINT이며, C가 보장됩니다 EOF유효한 문자가 동일하지 않습니다.
Alok Singhal 2017

61

여기에는 청크로 읽는 것에 대한 좋은 답변이 많이 있습니다. 모든 내용을 한 번에 버퍼로 읽어서 인쇄하는 작은 트릭을 보여 드리겠습니다.

더 낫다는 말이 아닙니다. 그렇지 않고 Ricardo가 때때로 나쁠 수 있지만 간단한 경우에는 좋은 해결책이라고 생각합니다.

많은 일이 일어나고 있기 때문에 코멘트를 뿌렸습니다.

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

유용하거나 배울 수 있는지 알려주세요 :)


2
buffer[string_size] = '\0';대신 읽어야 하지 string_size+1않습니까? AFAIK 실제 문자열에서 이동 0string_size-1\0문자 따라서에서 할 필요가 string_size오른쪽?
aepsil0n

4
사용 ftellfseek파일의 크기를 찾는 것은 안전하지 : securecoding.cert.org/confluence/display/seccode/...
조아킴

1
이 코드에는 메모리 누수가 포함되어 있으므로 파일을 닫지 마십시오. 누락이fclose(handle)
조아킴

1
fclose (handle)을 호출하는 오타가 있습니다. fclose (handler) 여야합니다.
Eduardo Cobuci

3
널 (NULL) 종료자를 설정 calloc(2)하지 않고 malloc(1)건너 뛰는 대신 사용할 수 있습니다 .

14

대신 텍스트 파일이 매우 클 수 있고 많은 메모리가 필요할 수 있으므로 문자를 콘솔에 직접 인쇄하십시오.

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

6

fscanf 대신 "read ()"를 사용하십시오.

ssize_t read(int fildes, void *buf, size_t nbyte);

기술

read () 함수는 nbyte열린 파일 설명자와 연관된 파일에서에서 fildes가리키는 버퍼로 바이트 를 읽으려고 시도합니다 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하여 한 번에 한 문자 씩 읽고 쓰는 것입니다. 훨씬 덜 효율적입니다. 좋은 예 : http://www.eskimo.com/~scs/cclass/notes/sx13.html


read특정 수의 문자를 읽을 수 있습니다. 버퍼를 채울만큼 충분히 읽은 다음 버퍼를 화면에 덤프하고 지우고 파일 끝까지 반복합니다.
bta 2010 년

1

두 가지 접근 방식이 떠 오릅니다.

첫째, scanf. 사용 fgets()버퍼 크기를 지정하는 매개 변수를, 그대로 어떤 개행 문자를 떠난다. 버퍼 내용을 인쇄하는 파일에 대한 간단한 루프는 자연스럽게 파일을 그대로 복사해야합니다.

둘째, 사용 fread()또는 함께 일반적인 C 관용구 fgetc(). 이들은 파일을 고정 된 크기의 청크 또는 한 번에 하나의 문자로 처리합니다.

공백으로 구분 된 문자열을 통해 파일을 처리해야하는 경우 fgets또는 중 하나를 사용 fread하여 파일을 읽고 strtok버퍼를 공백으로 분할하는 것과 같은 방법 을 사용하십시오. 대상 문자열이 버퍼 경계에 걸쳐있을 가능성이 있으므로 한 버퍼에서 다음 버퍼로의 전환을 처리하는 것을 잊지 마십시오.

scanf읽기를 수행하는 데 사용할 외부 요구 사항이 있는 경우 형식 지정자의 정밀도 필드를 사용하여 읽을 수있는 문자열의 길이를 제한합니다. 999 바이트 버퍼 scanf("%998s", str);를 사용하는 경우 nul 종결자를위한 공간을 남겨두고 버퍼에 최대 998 문자를 쓸 것이라고 말 하십시오. 버퍼보다 긴 단일 문자열이 허용되는 경우 두 부분으로 처리해야합니다. 그렇지 않은 경우 버퍼 오버플로 보안 구멍을 만들지 않고 정중하게 오류에 대해 사용자에게 알릴 수 있습니다.

어쨌든 항상 반환 값의 유효성을 검사하고 잘못되거나 악의적이거나 잘못된 입력을 처리하는 방법에 대해 생각하십시오.


1

fgets읽기 문자열의 크기를 사용 하고 제한 할 수 있습니다 .

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

while코드에서를 다음과 같이 변경할 수 있습니다 .

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

0

동적 메모리 할당으로 전체 파일을 읽을 수 있지만 파일이 너무 크면 메모리 문제가 발생할 수 있기 때문에 좋은 생각이 아닙니다.

따라서 파일의 짧은 부분을 읽고 인쇄하는 것이 좋습니다.

#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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.