且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

从文件或标准输入读取

更新时间:2023-11-17 23:13:52

首先,让程序告诉你什么是错的通过检查错误号,这是设置在失败,如在 fseek的 FTELL

其他(托尼奥&安培; LatinSuD)曾与标准输入处理与检查文件名解释的错误。也就是说,首先检查 ARGC (参数计数),以查看是否有指定的任何命令行参数如果(argc个→1),处理 - 作为一个特殊的情况下,这意味着标准输入

如果没有指定参数,则假定输入(去)来自标准输入,这是一个没有文件,并在 fseek的功能上的失败。

在流,在那里你可以不使用文件在磁盘上的导向库函数的情况下(即 fseek的 FTELL ),你只需要数字节读取(包括结尾的换行字符)的数量,直到接收 EOF (结束文件)。

有关处理大型文件的使用情况您可以通过使用与fgets 为char数组在(文本)文件字节更加有效地读取加快速度。对于一个二进制文件,你需要使用的fopen(为const char *文件名,RB),并使用 FREAD 而不是龟etc /与fgets

您还可以检查为的feof(标准输入) / FERROR(标准输入)使用字节计数时方法从流中读取数据时发现任何错误。

下面的示例应该是C99的兼容性和移植。

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;长getSizeOfInput(FILE *输入){
   长retvalue = 0;
   INT℃;   如果(输入!=标准输入){
      如果(-1 == fseek的(输入,0L,SEEK_END)){
         fprintf中(标准错误,错误寻求结束:%S \\ n字符串错误(错误));
         出口(EXIT_FAILURE);
      }
      如果(-1 ==(retvalue = FTELL(输入))){
         fprintf中(标准错误,FTELL失败:%S \\ n字符串错误(错误));
         出口(EXIT_FAILURE);
      }
      如果(-1 == fseek的(输入,0L,SEEK_SET)){
         fprintf中(标准错误,错误寻求启动:%S \\ n字符串错误(错误));
         出口(EXIT_FAILURE);
      }
   }其他{
      / *标准输入,我们需要整个流中读取直到EOF * /
      而(EOF!=(C =龟etc(输入))){
         retvalue ++;
      }
   }   返回retvalue;
}INT主(INT ARGC,字符** argv的){
   FILE *输入;   如果(argc个大于1){
      如果(!的strcmp(的argv [1], - )){
         输入=标准输入;
      }其他{
         输入= FOPEN(的argv [1],R);
         如果(NULL ==输入){
            fprintf中(标准错误,无法打开%s的:%S \\ n,
                  ARGV [1],字符串错误(错误));
            出口(EXIT_FAILURE);
         }
      }
   }其他{
      输入=标准输入;
   }   的printf(大小的文件:%LD \\ N,getSizeOfInput(输入));   返回EXIT_SUCCESS;
}

I am writing a utility which accepts either a filename, or reads from stdin.

I would like to know the most robust / fastest way of checking to see if stdin exists (data is being piped to the program) and if so reading that data in. If it doesn't exist, the processing will take place on the filename given. I have tried using the following the test for size of stdin but I believe since it's a stream and not an actual file, it's not working as I suspected it would and it's always printing -1. I know I could always read the input 1 character at a time while != EOF but I would like a more generic solution so I could end up with either a fd or a FILE* if stdin exists so the rest of the program will function seamlessly. I would also like to be able to know its size, pending the stream has been closed by the previous program.

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

Terminal:

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

First, ask the program to tell you what is wrong by checking the errno, which is set on failure, such as during fseek or ftell.

Others (tonio & LatinSuD) have explained the mistake with handling stdin versus checking for a filename. Namely, first check argc (argument count) to see if there are any command line parameters specified if (argc > 1), treating - as a special case meaning stdin.

If no parameters are specified, then assume input is (going) to come from stdin, which is a stream not file, and the fseek function fails on it.

In the case of a stream, where you cannot use file-on-disk oriented library functions (i.e. fseek and ftell), you simply have to count the number of bytes read (including trailing newline characters) until receiving EOF (end-of-file).

For usage with large files you could speed it up by using fgets to a char array for more efficient reading of the bytes in a (text) file. For a binary file you need to use fopen(const char* filename, "rb") and use fread instead of fgetc/fgets.

You could also check the for feof(stdin) / ferror(stdin) when using the byte-counting method to detect any errors when reading from a stream.

The sample below should be C99 compliant and portable.

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