programing

파일 또는 stdin에서 읽기

itmemos 2023. 10. 14. 09:36
반응형

파일 또는 stdin에서 읽기

저는 파일명을 받아들이거나 stdin에서 읽어주는 유틸리티를 쓰고 있습니다.

stdin이 존재하는지(데이터를 프로그램에 피핑하고 있음) 확인하고 해당 데이터를 읽는 가장 강력한/빠른 방법을 알고 싶습니다.존재하지 않는 경우, 주어진 파일명에 대한 처리가 이루어집니다.나는 다음 테스트를 사용하여 크기를 측정해 보았습니다.stdin하지만 실제 파일이 아닌 스트림이기 때문에 제가 생각했던 것처럼 작동하지 않고 항상 인쇄되고 있습니다.-1. 한 번에 입력한 문자를 항상 읽을 수 있다는 것을 알고 있습니다!= EOF이지만 stdin이 존재하면 fd 또는 FILE*로 끝나 나머지 프로그램이 원활하게 작동할 수 있도록 좀 더 포괄적인 솔루션을 원합니다.이전 프로그램에서 스트림이 닫힐 때까지 크기도 알고 싶습니다.

long getSizeOfInput(FILE *input){
  long retvalue = 0;
  fseek(input, 0L, SEEK_END);
  retvalue = ftell(input);
  fseek(input, 0L, SEEK_SET);
  return retvalue;
}

int main(int argc, char **argv) {
  printf("Size of stdin: %ld\n", getSizeOfInput(stdin));
  exit(0);
}

터미널:

$ echo "hi!" | myprog
Size of stdin: -1

잘못 생각하시는군요.

하려는 작업:

stdin이 존재하는 경우 사용자가 파일 이름을 제공했는지 여부를 확인합니다.

대신 해야 할 일:

사용자가 파일 이름을 제공하는 경우 파일 이름을 사용합니다.그 외는 stdin을 사용합니다.

모두 읽고 버퍼링 상태를 유지하지 않는 한 수신 스트림의 전체 길이를 알 수 없습니다.당신은 파이프 안으로 다시 들어가려고 할 수 없습니다.이것은 파이프가 작동하는 방식의 한계입니다.파이프는 모든 작업에 적합하지 않으며 중간 파일이 필요한 경우도 있습니다.

먼저 프로그램에 확인하여 무엇이 잘못되었는지 알려달라고 요청합니다.errno, 고장으로 설정되어 있습니다. 예를 들어.fseek아니면ftell.

다른 사람들(토니오 & 라틴어 SuD)은 stdin을 처리하는 것과 파일 이름을 확인하는 것의 실수를 설명했습니다.즉, 첫번째 체크argc(argument 카운트) 지정된 명령줄 매개 변수가 있는지 확인합니다.if (argc > 1), 대접하기-특별한 경우의 의미로서stdin.

파라미터가 지정되지 않은 경우 입력이 다음에서 시작된다고 가정합니다.stdin, 파일이 아닌 스트림입니다. 그리고fseek기능이 작동하지 않습니다.

스트림의 경우, 디스크 중심의 파일 라이브러리 함수(즉, file-on-disk oriented library functions)를 사용할 수 없습니다.fseek그리고.ftell), EOF(파일 끝)를 수신할 때까지 읽는 바이트 수(뒤로 가는 줄 문자 포함)만 세면 됩니다.

에는 를 수 있습니다.fgets(텍스트) 파일의 바이트를 보다 효율적으로 읽을 수 있도록 char 배열에 적용합니다.다를 .fopen(const char* filename, "rb")합니다.freadfgetc/fgets.

여부도 할 수 .feof(stdin)/ferror(stdin)스트림에서 읽을 때 오류를 탐지하기 위해 바이트 counting 방법을 사용하는 경우.

아래 샘플은 C99를 준수하고 휴대성이 있어야 합니다.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

long getSizeOfInput(FILE *input){
   long retvalue = 0;
   int c;

   if (input != stdin) {
      if (-1 == fseek(input, 0L, SEEK_END)) {
         fprintf(stderr, "Error seek end: %s\n", strerror(errno));
         exit(EXIT_FAILURE);
      }
      if (-1 == (retvalue = ftell(input))) {
         fprintf(stderr, "ftell failed: %s\n", strerror(errno));
         exit(EXIT_FAILURE);
      }
      if (-1 == fseek(input, 0L, SEEK_SET)) {
         fprintf(stderr, "Error seek start: %s\n", strerror(errno));
         exit(EXIT_FAILURE);
      }
   } else {
      /* for stdin, we need to read in the entire stream until EOF */
      while (EOF != (c = fgetc(input))) {
         retvalue++;
      }
   }

   return retvalue;
}

int main(int argc, char **argv) {
   FILE *input;

   if (argc > 1) {
      if(!strcmp(argv[1],"-")) {
         input = stdin;
      } else {
         input = fopen(argv[1],"r");
         if (NULL == input) {
            fprintf(stderr, "Unable to open '%s': %s\n",
                  argv[1], strerror(errno));
            exit(EXIT_FAILURE);
         }
      }
   } else {
      input = stdin;
   }

   printf("Size of file: %ld\n", getSizeOfInput(input));

   return EXIT_SUCCESS;
}

당신은 이것이 어떻게 이루어지는지 보는 것이 좋을 것입니다.cat예를 들어, 유틸리티.

여기 코드 참조.인수로 파일 이름이 없거나 "-"인 경우stdin입력에 사용됩니다.stdin데이터가 푸시되지 않더라도 해당 위치에 있게 됩니다(그러나 그러면 읽기 호출이 영원히 기다릴 수도 있습니다).

사용자가 파일 이름을 제공하지 않는 한 stdin에서 읽을 수 있습니까?

그렇지 않은 경우 특별한 "파일 이름"을 처리합니다.- 'stdin다'에서 읽음을 합니다..cat file | myprogram -을 하려면myprogam file파일에서 읽기를 원한다면요

int main(int argc,char *argv[] ) {
  FILE *input;
  if(argc != 2) {
     usage();
     return 1;
   }
   if(!strcmp(argv[1],"-")) {
     input = stdin;
    } else {
      input = fopen(argv[1],"rb");
      //check for errors
    }

*nix를 사용하는 경우 stdin이 fifo인지 확인할 수 있습니다.

 struct stat st_info;
 if(fstat(0,&st_info) != 0)
   //error
  }
  if(S_ISFIFO(st_info.st_mode)) {
     //stdin is a pipe
  }

비록 그것이 사용자가 하는 일을 처리할 수는 없겠지만.myprogram <file

stdin이 터미널/콘솔인지 확인할 수 있습니다.

if(isatty(0)) {
  //stdin is a terminal
}

로 입니다.feof내 생각엔 그럴 것 같습니다.

당신이 원하는 것은 stdin이 단말기에 연결되어 있는지 아닌지를 아는 것이지, 단말기가 존재하는지를 아는 것이 아닙니다.항상 존재하지만 셸을 사용하여 무언가를 파이프링하거나 파일을 읽을 때 터미널에 연결되지 않습니다.

termios.h 기능을 통해 파일 디스크립터가 단말기에 연결되어 있는지 확인할 수 있습니다.

#include <termios.h>
#include <stdbool.h>

bool stdin_is_a_pipe(void)
{
    struct termios t;
    return (tcgetattr(STDIN_FILENO, &t) < 0);
}

stdin의 터미널 특성을 가져오려고 합니다.파이프에 연결되지 않은 경우 아티에 연결되어 tcgetattr 함수 호출이 성공합니다.파이프를 검출하기 위해 tcgetattr failure를 확인합니다.

언급URL : https://stackoverflow.com/questions/3495092/read-from-file-or-stdin

반응형