파일 또는 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
'programing' 카테고리의 다른 글
| Visual Studio 2010 매우 느리고 사용할 수 없음 (0) | 2023.10.19 |
|---|---|
| MySQL 구문 오류 - JSON (0) | 2023.10.14 |
| 경고 수신 "기능 'strlen'에 대한 암묵적 선언" (0) | 2023.10.14 |
| 부트스트랩 3 RC 1에서 type ahead 자바스크립트 모듈은 어디에 있습니까? (0) | 2023.10.14 |
| Oracle: tablea, tableb에서 *를 선택합니다. 여기서 a.fielda (+)=b.fieldb -- (+)란 무엇입니까? (0) | 2023.10.14 |