C#读取文件或者字符流的最后几行,类似linux的tail命令-OK
C#读取文件或者字符流的最后几行,类似linux的tail命令
更多
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
}
}