C#读取文件或者字符流的最后几行,类似linux的tail命令-OK

C#读取文件或者字符流的最后几行,类似linux的tail命令

更多

tail

读取文件

C#

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace RobvanderWoude
{
    class Tail
    {
        static int Main( string[] args )
        {
            try
            {
                int numlines = 1;
                string[] lines;

                #region Command Line Parsing

                string filename = string.Empty;
                bool redirected;
                bool set_l = false;
                bool set_input = false;

                foreach ( string arg in args )
                {
                    if ( arg[0] == '/' )
                    {
                        if ( arg.Length > 3 )
                        {
                            if ( arg.ToUpper( )[1] == 'L' )
                            {
                                if ( arg[2] != ':' )
                                {
                                    return WriteError( "Invalid argument: " + arg );
                                }
                                try
                                {
                                    if ( set_l )
                                    {
                                        return WriteError( "Duplicate /L argument" );
                                    }
                                    else
                                    {
                                        numlines = Convert.ToInt32( arg.Substring( 3 ) );
                                        if ( numlines < 1 )
                                        {
                                            return WriteError( "Number of lines must be 1 or greater" );
                                        }
                                        set_l = true;
                                    }
                                }
                                catch ( FormatException e )
                                {
                                    return WriteError( "Invalid number of lines: " + arg );
                                }
                            }
                        }
                        else
                        {
                            if ( arg == "/?" )
                            {
                                return WriteError( );
                            }
                            else
                            {
                                return WriteError( "Invalid argument: " + arg );
                            }
                        }
                    }
                    else
                    {
                        if ( set_input )
                        {
                            return WriteError( "Duplicate file argument" );
                        }
                        else
                        {
                            if ( File.Exists( arg ) )
                            {
                                filename = arg;
                            }
                            else
                            {
                                return WriteError( "Invalid filename: " + arg );
                            }
                            set_input = true;
                        }
                    }
                }

                if ( ConsoleEx.InputRedirected )
                {
                    if ( set_input )
                    {
                        return WriteError( "Use either file name or redirection, not both" );
                    }
                    else
                    {
                        set_input = true;
                        redirected = true;
                    }
                }
                else
                {
                    if ( args.Length == 0 )
                    {
                        return WriteError( );
                    }
                    redirected = false;
                }

                #endregion Command Line Parsing

                if ( redirected )
                {
                    // Read standard input and store the lines in a list
                    List<string> alllines = new List<string>( );
                    int peek = 0;
                    string line;
                    do
                    {
                        line = Console.In.ReadLine( );
                        alllines.Add( line );
                        peek = Console.In.Peek( );
                    } while ( peek != -1 );
                    // Convert the list to an array
                    lines = alllines.ToArray( );
                }
                else
                {
                    // Read the file and store the lines in an array
                    lines = File.ReadAllLines( filename );
                }
                // Display the last lines from the array
                int startline = lines.Length - numlines;
                if ( startline < 0 )
                {
                    startline = 0;
                }
                for ( int i = startline; i < lines.Length; i++ )
                {
                    Console.WriteLine( lines[i] );
                }
                return 0;
            }
            catch ( Exception e )
            {
                return WriteError( e.Message );
            }
        }

        #region Redirection Detection

        // Code to detect redirection by Hans Passant on StackOverflow.com
        // http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
        public static class ConsoleEx
        {
            public static bool OutputRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdout ) );
                }
            }

            public static bool InputRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdin ) );
                }
            }

            public static bool ErrorRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stderr ) );
                }
            }

            // P/Invoke:
            private enum FileType { Unknown, Disk, Char, Pipe };
            private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };

            [DllImport( "kernel32.dll" )]
            private static extern FileType GetFileType( IntPtr hdl );

            [DllImport( "kernel32.dll" )]
            private static extern IntPtr GetStdHandle( StdHandle std );
        }

        #endregion Redirection Detection

        #region Error Handling

        public static int WriteError( Exception e = null )
        {
            return WriteError( e == null ? null : e.Message );
        }

        public static int WriteError( string errorMessage )
        {
            if ( string.IsNullOrEmpty( errorMessage ) == false )
            {
                Console.Error.WriteLine( );
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Error.Write( "ERROR: " );
                Console.ForegroundColor = ConsoleColor.White;
                Console.Error.WriteLine( errorMessage );
                Console.ResetColor( );
            }

            /*
            Tail,  Version 1.00
            Return the specified number of lines from the end of the specified file

            Usage:   TAIL  filename  [ option ]
               or:   TAIL  [ option ]  <  filename
               or:   command  |  TAIL  [ option ]

            Where:   filename   is the optional file to be read
                     command    is the optional command whose output is to be read
                     /L:n       read the last n Lines (default: 1 line)

            Examples:
            TAIL  filename                 read the last line (default)
            TAIL  /L:2  <  filename        read the last 2 lines
            command  | TAIL  /L:5          read the last 5 lines

            Check for redirection by Hans Passant on StackOverflow.com
            /questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected

            Written by Rob van der Woude
            http://www.robvanderwoude.com
            */

            Console.Error.WriteLine( );
            Console.Error.WriteLine( "Tail,  Version 1.00" );
            Console.Error.WriteLine( "Return the specified number of lines from the end of the specified file" );
            Console.Error.WriteLine( );
            Console.Error.Write( "Usage:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( "TAIL  filename  [ option ]" );
            Console.ResetColor( );
            Console.Error.Write( "   or:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( "TAIL  [ option ]  <  filename" );
            Console.ResetColor( );
            Console.Error.Write( "   or:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( "command  |  TAIL  [ option ]" );
            Console.ResetColor( );
            Console.Error.WriteLine( );
            Console.Error.Write( "Where:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "filename" );
            Console.ResetColor( );
            Console.Error.WriteLine( "   is the optional file to be read" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         command" );
            Console.ResetColor( );
            Console.Error.WriteLine( "    is the optional command whose output is to be read" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         /L:n" );
            Console.ResetColor( );
            Console.Error.Write( "       read the last " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "n L" );
            Console.ResetColor( );
            Console.Error.WriteLine( "ines (default: 1 line)" );
            Console.Error.WriteLine( );
            Console.Error.WriteLine( "Examples:" );
            Console.Error.WriteLine( "TAIL  filename                 read the last line (default)" );
            Console.Error.WriteLine( "TAIL  /L:2  <  filename        read the last 2 lines" );
            Console.Error.WriteLine( "command  | TAIL  /L:5          read the last 5 lines" );
            Console.Error.WriteLine( );
            Console.Error.Write( "Check for redirection by Hans Passant on " );
            Console.ForegroundColor = ConsoleColor.DarkGray;
            Console.Error.WriteLine( "StackOverflow.com" );
            Console.Error.WriteLine( "/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected" );
            Console.ResetColor( );
            Console.Error.WriteLine( );
            Console.Error.WriteLine( "Written by Rob van der Woude" );
            Console.Error.WriteLine( "http://www.robvanderwoude.com" );
            return 1;
        }

        #endregion Error Handling
    }
}
posted @ 2019-06-09 09:40  grj001  阅读(304)  评论(0编辑  收藏  举报