how to check stdin for piped data

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • HowardL
    New Member
    • Oct 2009
    • 6

    how to check stdin for piped data

    Hi,
    I would like to be able to either pipe data into my prog from stdin or get data from a file.
    If I try to check by using
    Code:
     if( Console.In.Peek() != -1 )
        {
          Console.WriteLine("GOT STDIN");
          return;
        }
    ...it blocks and user must hit return to continue.
    Is there a test I can do in C# that will not block?
    Thanks
  • tlhintoq
    Recognized Expert Specialist
    • Mar 2008
    • 3532

    #2
    If it were a WinForm app I would suggest reacting to the keypress event.
    That way as soon as any key is pressed you can move on to whatever you like.
    Does it have to be a console app?

    Comment

    • Plater
      Recognized Expert Expert
      • Apr 2007
      • 7872

      #3
      Does this work?
      Console.OpenSta ndardInput().Le ngth

      Comment

      • HowardL
        New Member
        • Oct 2009
        • 6

        #4
        Thanks for your replies.
        > Does it have to be a console app? - reacting to the keypress event
        Yes it is just a filter app.

        I think you CAN get keypress events in a Console app but
        I don't think piped data would cause a keypress event and
        the program will not be taking any Q&A user input.
        The program will filter a stream of floating point numbers.
        I wanted the user to be able to supply the stream either:
        - piped in on the command line
        . . eg: echo "1.2334 2.345 3.456 " | myprog
        - or from a file supplied by user as arg[0]

        If neither is supplied the prog will create it's own sample data.

        I couldnt get anything out of "Console.OpenSt andardInput().L ength"
        Code:
            //Console.WriteLine("Console.OpenStandardInput().Length= {0}", 
            //                                   Console.OpenStandardInput().Length );
            // exception: The stream does not support seeking (with or without piped data)
        Here is an example of my novice level and the things I have tried:
        Code:
        using System;
        using System.Text; // for ReadKey()
        using System.IO;   // for StreamReader etc
        
        class MyProg
        {
          static void Main(string[] args)
          {
            //string s1;
            //int i;
            char c;
        
            Console.WriteLine("-----test-----");
        
        /****  So far everything has blocked the same as Console.Read():         ****/
            while( Console.In.Peek() != -1 ) // blocks at first read... 
            {
              //s1 = Console.ReadLine();
              //Console.Write(s1);
        
              //i = Console.Read();
              //Console.Write("{0} ", i);
        
              c = (char)Console.Read();
              Console.Write("{0} ", c);
        
              //c = Console.ReadKey();   // even with:  using System.Text; still gets:
              //     Error: System.Console' does not contain a definition for `ReadKey'
              //Console.Write("{0} ", c);
            }
        /****/
            
        /****  This works to read stdin but still blocks... * /
            TextReader trIn = Console.In;
            while( trIn.Peek() != -1 )
            {
              //Console.WriteLine("trIn.Length= {0} ", trIn.Length );
              // `System.IO.TextReader' does not contain a definition for `Length'
              c = (char)trIn.Read();
              Console.Write("{0} ", c );
            }
            trIn.close();
        / ****/
        
        /**** This works to read stdin but still blocks the same:
        
            StreamReader srIn= new StreamReader(Console.OpenStandardInput());
            while( srIn.Peek() != -1 )
            {
              //Console.WriteLine("srIn.Length= {0} ", srIn.Length );
              //  System.IO.StreamReader' does not contain a definition for `Length'
              //  
              c = (char)srIn.Read();
              Console.Write("{0} ", c);
              if(c == 'x') break;  
            }
            srIn.Close();
        ****/
        
        /****
            if( Console.In )  
              Error: Cannot implicitly convert type `System.Console.In' to `bool'
        ****
            if( (bool)Console.In )
              Error: Cannot convert type `System.Console.In' to `bool'
        ****
            if( Console.In.Good )  // no member "Good"
              Console.Write("Console.In ");
            else 
              Console.Write("NO Console.In ");
        ****/
        
            //Console.WriteLine("Console.In= {0}", Console.In ); 
            // ouptput:  Console.In= System.IO.SynchronizedReader
        
            //Console.WriteLine("Console.OpenStandardInput().Length= {0}", 
            //                                   Console.OpenStandardInput().Length );
            // exception: The stream does not support seeking (with or without piped data)
        
            //Console.WriteLine("Console.In.Length= {0}", Console.In.Length ); 
            // error: System.IO.TextReader' does not contain a definition for `Length'
          }
        }
        There are so many objects and methods in C# I get lost.
        I had thought that this would be doable in C# but maybe not. (I wonder why not)
        I guess I'll have to get user to indicate input method as a CL argument.
        Thanks for the ideas, Howard

        Comment

        • GaryTexmo
          Recognized Expert Top Contributor
          • Jul 2009
          • 1501

          #5
          Have a look here...


          You can check to see if a key is available with Console.KeyAvai lable, then you can read it out of the stream at that point.

          Does that help any?

          Comment

          • HowardL
            New Member
            • Oct 2009
            • 6

            #6
            So Console.KeyAvai lable seems to be set to false if there is no piped data
            BUT Surprise! I can't tell if it DOES detect piped data because when the
            console is in the graphics mode, any piped data will cause an exception!

            I can read from command line from within the program if there is no piped data.!

            -> gmcs peek_stdin-2.cs
            -> mono peek_stdin-2.exe
            -> echo -n "dude" | mono peek_stdin-2.exe

            Unhandled Exception: System.IO.IOExc eption: Not a tty.
            at System.TermInfo Driver.Init () [0x00000]
            at System.TermInfo Driver.Clear () [0x00000]
            at System.ConsoleD river.Clear () [0x00000]
            at System.Console. Clear () [0x00000]
            at MyProg.Main (System.String[] args) [0x00000]

            Here is what I've been testing with:
            Code:
            using System;
            
            class MyProg
            {
              static void Main(string[] args)
              {
                char c;
            
                /* So here we start with some graphics mode commands: */
                Console.Clear();
                Console.SetCursorPosition( 0, 0);
                Console.Write("-----test-----\n");
            
                if( Console.KeyAvailable)
                {
                  Console.WriteLine("got stdin");
                }
                else
                {
                  Console.WriteLine("Don't got stdin");
                  while( true ).                         
                  {
                    c = (char)Console.Read();
                    Console.Write("{0} ", c);
                    if(c == '\n') break;
                  }
                }
                */
                //c = (char)Console.Read();    // hold window open to see output 
              }
            }
            even a single Console.Clear() will cause the exception!
            Oh well. maybe I'm missing something.
            Thanks for the sugestion though.

            Comment

            • Plater
              Recognized Expert Expert
              • Apr 2007
              • 7872

              #7
              Console.OpenSta ndardInput().Le ngth should be 0 unless there is data to be read from the standard input.

              Comment

              • HowardL
                New Member
                • Oct 2009
                • 6

                #8
                That works for you?

                #### If I try either this:
                int x = (int)Console.Op enStandardInput ().Length ;

                #### or this
                Console.WriteLi ne("Console.Ope nStandardInput( ).Length= {0} ",
                Console.OpenSta ndardInput().Le ngth );

                ### and run with either this:
                -> mono peek_stdin-2.exe

                #### or this:
                -> echo "Hello" | mono peek_stdin-2.exe

                #### I get this each time:
                Unhandled Exception: System.NotSuppo rtedException: The stream does not support seeking

                -----
                I am using mono on linux and compiling with either:

                mcs progname.cs
                or
                gmcs progname.cs

                Both build the code with no questions warnings or errors.
                Maybe mono is the problem?
                Or am I missing something as far as how to use Console.OpenSta ndardInput().Le ngth?

                Comment

                • Plater
                  Recognized Expert Expert
                  • Apr 2007
                  • 7872

                  #9
                  You are correct, seems the stdin doesn't support the length.
                  Console.KeyAvai lable worked for me though.

                  Comment

                  • HowardL
                    New Member
                    • Oct 2009
                    • 6

                    #10
                    > You are correct, seems the stdin doesn't support the length.
                    Good, then mono is not the problem.

                    > Console.KeyAvai lable worked for me though.
                    hmm, and you can pipe data to that without getting an exception?
                    Are you using Windows?

                    Comment

                    • Plater
                      Recognized Expert Expert
                      • Apr 2007
                      • 7872

                      #11
                      Yes I am in windows. I would have thought there would be no difference on this matter in mono.
                      KeyAvailable seems to be similar to C's kbhit()

                      Comment

                      • HowardL
                        New Member
                        • Oct 2009
                        • 6

                        #12
                        KeyAvailable seems to be similar to C's kbhit()
                        I guess they haven't written it yet...
                        Oh well, I'll just give that quest up and have the user indicate if data is in stdin or file thruough a command line arg:
                        Code:
                         using System;
                        
                        class myprog
                        {
                          static void Main(string[] args)
                          {
                            string input;
                        
                            if(args.Length == 0)
                            {
                              Console.WriteLine("\n     ***** Error: no arguments supplied *****\n"+
                                "Usage:  {0}  filin  \n\n" +
                                "...where \"filin\" is an input file name \n"+
                                "or '-' if input is to be from keyboard or pipe (|) or redirect (<).",
                                Environment.GetCommandLineArgs() );
                        
                               return;
                            }
                        
                            if(args[0] == "-")
                            {
                              Console.WriteLine("\nReading data from stdin: ");
                              input = Console.ReadLine();
                              Console.WriteLine(input);
                            }
                            else
                            {
                              Console.WriteLine("sorry , haven't written code for file input yet");
                            }
                          }
                        }
                        /*
                        
                        csprogs>  mcs pipe_detect.cs
                        
                        csprogs>  mono pipe_detect.exe
                        
                             ***** Error: no arguments supplied *****
                        Usage:  /mnt/e/csprogs/pipe_detect.exe  filin  
                        
                        ...where "filin" is an input file name 
                        or '-' if input is to be from keyboard or pipe (|) or redirect (<).
                        
                        -----
                        
                        csprogs>  echo -n "123.5 543.2 456.7 987.4" | mono pipe_detect.exe -
                        
                        Reading data from stdin: 
                        123.5 543.2 456.7 987.4
                        
                        -----
                        
                        csprogs>  cat > xfile
                        123.5 543.2 456.7 987.4
                        
                        csprogs>   mono pipe_detect.exe - <  xfile
                        
                        Reading data from stdin: 
                        123.5 543.2 456.7 987.4
                        
                        -----
                        
                        csprogs>   mono pipe_detect.exe xfile
                        sorry , haven't written code for file input yet
                        
                        -----:)
                        */
                        Thanks for your help.

                        Comment

                        Working...