C# Console 全面详解:从基础到高级的控制台应用开发
控制台应用程序是 C# 开发中最基础也最常用的应用类型之一,它不需要图形界面,通过命令行与用户交互,广泛用于工具类程序、后台服务、自动化脚本等场景。本文将全面介绍 C# Console 的各种功能和使用方法,从基础的输入输出到高级的控制台控制,帮助开发者掌握控制台应用开发的精髓。
一、控制台应用基础
1. 控制台应用的创建与结构
在 Visual Studio 中创建控制台应用程序后,会自动生成以下基础结构:
using System;
namespace ConsoleAppDemo
{
class Program
{
// 程序入口点
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
关键组成部分:
Main
方法:程序的入口点,必须是静态方法string[] args
:用于接收命令行参数Console
类:提供控制台输入输出功能的核心类,位于System
命名空间
2. 程序的生命周期
控制台应用的生命周期简单直接:
- 启动程序,执行
Main
方法 - 执行
Main
方法中的代码 Main
方法执行完毕,程序退出
可以通过Environment.Exit(code)
手动控制程序退出,其中code
为退出码(0 表示正常退出,非 0 表示异常):
static void Main(string[] args)
{
Console.WriteLine("程序即将退出");
Environment.Exit(0); // 正常退出
// 以下代码不会执行
Console.WriteLine("这段文字不会显示");
}
二、控制台输出方法
Console
类提供了多种输出方法,满足不同场景的需求。
1. 基本输出方法
// 输出内容后不换行
Console.Write("Hello ");
// 输出内容后自动换行
Console.WriteLine("World!");
// 输出结果:Hello World!
2. 格式化输出
// 使用占位符
string name = "张三";
int age = 25;
Console.WriteLine("姓名:{0},年龄:{1}", name, age);
// C# 6.0及以上支持的字符串插值
Console.WriteLine($"姓名:{name},年龄:{age}");
// 格式化数字和日期
double pi = Math.PI;
DateTime today = DateTime.Now;
Console.WriteLine("π的值:{0:F4}", pi); // 保留4位小数
Console.WriteLine("今天:{0:yyyy年MM月dd日}", today);
3. 输出到错误流
使用Console.Error
将错误信息输出到标准错误流(与标准输出流可分离处理):
try
{
int result = 10 / 0;
}
catch (Exception ex)
{
// 输出到错误流
Console.Error.WriteLine($"发生错误:{ex.Message}");
}
在命令行中可以将错误流重定向到文件:
ConsoleAppDemo.exe 2 > error.log
三、控制台输入方法
控制台应用通过多种方式接收用户输入,需要根据实际需求选择合适的方法。
1. 读取一行输入
Console.Write("请输入您的姓名:");
// 读取用户输入的一行文本(直到按下Enter键)
string name = Console.ReadLine();
if (string.IsNullOrEmpty(name))
{
Console.WriteLine("您没有输入任何内容");
}
else
{
Console.WriteLine($"您好,{name}!");
}
注意:
ReadLine
在用户按下 Enter 键前会一直阻塞程序执行,返回
null
表示用户按下了 Ctrl+Z(文件结束符)
2. 读取单个字符
Console.Write("请按任意键继续...");
// 读取一个字符(不等待Enter键)
char key = Console.ReadKey().KeyChar;
Console.WriteLine($"n您按下的字符是:{key}");
// 不显示输入的字符(例如输入密码时)
Console.Write("请输入密码:");
char passwordChar = Console.ReadKey(true).KeyChar; // 参数true表示不显示输入
Console.WriteLine("n您输入了一个字符");
3. 读取数值类型输入
用户输入的内容默认是字符串类型,需要转换为相应的数值类型:
// 方法1:使用Parse(转换失败会抛出异常)
Console.Write("请输入一个整数:");
string input = Console.ReadLine();
try
{
int num = int.Parse(input);
Console.WriteLine($"您输入的整数是:{num}");
}
catch (FormatException)
{
Console.WriteLine("输入格式不正确");
}
catch (OverflowException)
{
Console.WriteLine("输入的数值超出范围");
}
// 方法2:使用TryParse(转换失败返回false,不抛出异常)
Console.Write("请输入一个浮点数:");
if (double.TryParse(Console.ReadLine(), out double number))
{
Console.WriteLine($"您输入的浮点数是:{number}");
}
else
{
Console.WriteLine("转换失败");
}
三、控制台输入输出的高级控制
1. 控制输出颜色
// 保存当前颜色设置,以便后续恢复
ConsoleColor originalForeground = Console.ForegroundColor;
ConsoleColor originalBackground = Console.BackgroundColor;
// 设置前景色(文字颜色)
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("这段文字是红色的");
// 设置背景色
Console.BackgroundColor = ConsoleColor.Yellow;
Console.WriteLine("这段文字的背景是黄色的");
// 同时设置前景色和背景色
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine("白色文字蓝色背景");
// 恢复原始颜色设置
Console.ForegroundColor = originalForeground;
Console.BackgroundColor = originalBackground;
Console.WriteLine("恢复默认颜色的文字");
2. 光标控制
// 获取当前光标位置
int currentLeft = Console.CursorLeft;
int currentTop = Console.CursorTop;
Console.WriteLine($"当前光标位置:({currentLeft}, {currentTop})");
// 设置光标位置
Console.SetCursorPosition(5, 10);
Console.WriteLine("这里是(5,10)位置");
// 隐藏光标
Console.CursorVisible = false;
Console.WriteLine("光标已隐藏");
Console.ReadKey();
// 显示光标
Console.CursorVisible = true;
Console.WriteLine("光标已显示");
3. 窗口和缓冲区大小控制
// 获取窗口大小
int windowWidth = Console.WindowWidth;
int windowHeight = Console.WindowHeight;
Console.WriteLine($"窗口宽度:{windowWidth},窗口高度:{windowHeight}");
// 设置窗口大小(可能受系统限制)
try
{
Console.SetWindowSize(80, 30);
Console.WriteLine("窗口大小已设置为80x30");
}
catch (ArgumentOutOfRangeException)
{
Console.WriteLine("窗口大小超出范围");
}
// 获取缓冲区大小
int bufferWidth = Console.BufferWidth;
int bufferHeight = Console.BufferHeight;
Console.WriteLine($"缓冲区宽度:{bufferWidth},缓冲区高度:{bufferHeight}");
// 设置缓冲区大小
Console.SetBufferSize(120, 1000);
Console.WriteLine("缓冲区大小已设置为120x1000");
4. 清除屏幕和滚动
Console.WriteLine("3秒后清屏...");
System.Threading.Thread.Sleep(3000);
// 清除整个屏幕
Console.Clear();
Console.WriteLine("屏幕已清除");
// 滚动屏幕(向上滚动1行)
Console.WriteLine("第一行");
Console.WriteLine("第二行");
Console.WriteLine("第三行");
Console.ReadKey();
Console.SetWindowPosition(0, Console.WindowTop + 1); // 向上滚动1行
四、命令行参数处理
控制台应用通常通过命令行参数接收配置信息,这些参数会被传递给Main
方法的args
数组。
1. 基本参数处理
static void Main(string[] args)
{
Console.WriteLine($"命令行参数数量:{args.Length}");
// 遍历所有参数
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($"参数 {i}:{args[i]}");
}
// 检查特定参数
if (args.Length > 0 && args[0] == "-help")
{
Console.WriteLine("显示帮助信息...");
}
}
在命令行中运行程序并传递参数:
ConsoleAppDemo.exe -mode full -output result.txt
2. 使用参数解析库
对于复杂的命令行参数,手动解析会比较繁琐,可以使用第三方库如CommandLineParser
(NuGet 包):
// 安装:Install-Package CommandLineParser
using CommandLine;
// 定义参数选项
public class Options
{
[Option('m', "mode", Required = true, HelpText = "运行模式")]
public string Mode { get; set; }
[Option('o', "output", HelpText = "输出文件路径")]
public string OutputFile { get; set; }
[Option('v', "verbose", Default = false, HelpText = "是否显示详细信息")]
public bool Verbose { get; set; }
}
static void Main(string[] args)
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed<Options>(options =>
{
// 解析成功,处理参数
Console.WriteLine($"运行模式:{options.Mode}");
if (!string.IsNullOrEmpty(options.OutputFile))
{
Console.WriteLine($"输出文件:{options.OutputFile}");
}
if (options.Verbose)
{
Console.WriteLine("详细信息模式已开启");
}
})
.WithNotParsed(errors =>
{
// 解析失败,处理错误
Console.WriteLine("参数解析失败");
});
}
使用方法:
ConsoleAppDemo.exe -m process -o result.txt -v
五、控制台应用的交互设计
1. 菜单系统
static void Main(string[] args)
{
bool exit = false;
while (!exit)
{
// 显示菜单
Console.Clear();
Console.WriteLine("===== 菜单 =====");
Console.WriteLine("1. 显示欢迎信息");
Console.WriteLine("2. 计算两数之和");
Console.WriteLine("3. 退出程序");
Console.WriteLine("================");
Console.Write("请选择操作(1-3):");
// 处理用户选择
switch (Console.ReadLine())
{
case "1":
ShowWelcomeMessage();
break;
case "2":
CalculateSum();
break;
case "3":
exit = true;
break;
default:
Console.WriteLine("无效的选择");
break;
}
if (!exit)
{
Console.WriteLine("按任意键继续...");
Console.ReadKey();
}
}
Console.WriteLine("程序已退出");
}
static void ShowWelcomeMessage()
{
Console.WriteLine("欢迎使用本程序!");
}
static void CalculateSum()
{
Console.Write("请输入第一个数:");
if (double.TryParse(Console.ReadLine(), out double a))
{
Console.Write("请输入第二个数:");
if (double.TryParse(Console.ReadLine(), out double b))
{
Console.WriteLine($"{a} + {b} = {a + b}");
}
else
{
Console.WriteLine("第二个数输入错误");
}
}
else
{
Console.WriteLine("第一个数输入错误");
}
}
2. 进度显示
static void Main(string[] args)
{
Console.WriteLine("任务执行中...");
for (int i = 0; i <= 100; i++)
{
// 显示进度百分比
Console.Write($"r进度:{i}%");
// 模拟任务执行
System.Threading.Thread.Sleep(50);
}
Console.WriteLine("n任务完成!");
}
更复杂的进度条:
static void ShowProgressBar(int progress, int total)
{
// 进度条长度
int barLength = 50;
double percentage = (double)progress / total;
int filledLength = (int)(percentage * barLength);
// 构建进度条
string bar = new string('=', filledLength) + new string(' ', barLength - filledLength);
// 移动光标到行首,重写进度条
Console.Write($"r[{bar}] {progress}/{total} ({percentage:P0})");
// 完成时换行
if (progress == total)
{
Console.WriteLine();
}
}
static void Main(string[] args)
{
int totalSteps = 30;
for (int i = 1; i <= totalSteps; i++)
{
ShowProgressBar(i, totalSteps);
// 模拟任务执行
System.Threading.Thread.Sleep(200);
}
Console.WriteLine("任务完成!");
}
六、控制台的特殊操作
1. 处理键盘事件
static void Main(string[] args)
{
Console.WriteLine("按任意键(按Esc退出)");
while (true)
{
// 检查是否有按键按下
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey(true); // 不显示按键
Console.WriteLine($"按下了:{key.Key}");
// 按Esc键退出
if (key.Key == ConsoleKey.Escape)
{
break;
}
// 处理功能键
if (key.Key == ConsoleKey.F1)
{
Console.WriteLine("F1键被按下,显示帮助信息");
}
// 处理组合键
if (key.Modifiers == ConsoleModifiers.Control && key.Key == ConsoleKey.C)
{
Console.WriteLine("Ctrl+C被按下");
}
}
// 做一些其他工作
System.Threading.Thread.Sleep(100);
}
}
2. 控制台输入输出重定向
控制台应用的输入输出可以重定向到文件或其他流:
static void Main(string[] args)
{
// 检查是否重定向了输入
if (Console.IsInputRedirected)
{
Console.WriteLine("输入已重定向");
string input = Console.In.ReadToEnd(); // 从重定向的输入流读取所有内容
Console.WriteLine($"读取到的内容:{input}");
}
// 检查是否重定向了输出
if (Console.IsOutputRedirected)
{
Console.WriteLine("输出已重定向");
}
// 检查是否重定向了错误输出
if (Console.IsErrorRedirected)
{
Console.Error.WriteLine("错误输出已重定向");
}
}
在命令行中使用重定向:
# 将文件内容作为输入,输出保存到文件
ConsoleAppDemo.exe < input.txt > output.txt 2> error.log
3. 控制台编码设置
处理中文等非 ASCII 字符时,可能需要设置控制台编码:
// 设置输出编码为UTF-8
Console.OutputEncoding = System.Text.Encoding.UTF8;
// 设置输入编码为UTF-8
Console.InputEncoding = System.Text.Encoding.UTF8;
Console.WriteLine("支持中文显示");
七、异步控制台应用
在 C# 7.1 及以上版本中,Main
方法可以是异步的,方便处理异步操作:
// 需要在项目属性中设置语言版本为7.1或更高
static async Task Main(string[] args)
{
Console.WriteLine("开始异步操作...");
// 异步延迟2秒
await Task.Delay(2000);
// 异步读取文件
string content = await ReadFileAsync("data.txt");
Console.WriteLine($"文件内容:{content}");
Console.WriteLine("异步操作完成");
}
static async Task<string> ReadFileAsync(string path)
{
if (File.Exists(path))
{
return await File.ReadAllTextAsync(path);
}
return "文件不存在";
}
八、控制台应用的调试与部署
1. 调试技巧
// 条件编译指令,仅在调试模式下执行
#if DEBUG
Console.WriteLine("调试信息:开始处理数据");
#endif
// 断言,用于调试时检查条件
System.Diagnostics.Debug.Assert(args.Length > 0, "必须提供命令行参数");
// 输出调试信息(仅在调试模式显示)
System.Diagnostics.Debug.WriteLine("这是调试信息");
// 输出跟踪信息(在调试和发布模式都能显示)
System.Diagnostics.Trace.WriteLine("这是跟踪信息");
2. 部署控制台应用
自包含部署:包含.NET 运行时,无需目标机器安装.NET
dotnet publish -c Release -r win-x64 --self-contained true
框架依赖部署:需要目标机器安装.NET 运行时
dotnet publish -c Release -r win-x64 --self-contained false
单文件部署(.NET 5 + 支持):将所有文件打包为单个可执行文件
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true
九、跨平台控制台应用注意事项
.NET Core/.NET 5 +
的控制台应用支持跨平台运行,在开发时需要注意:
路径处理:使用
Path
类处理路径,避免硬编码``或/
string filePath = Path.Combine("data", "logs", "app.log");
行尾符:不同操作系统的行尾符不同,使用
Environment.NewLine
Console.Write($"第一行{Environment.NewLine}第二行");
控制台功能差异:某些控制台功能在不同操作系统上表现不同
// 检查操作系统 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Windows特定代码 Console.WriteLine("运行在Windows上"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // Linux特定代码 Console.WriteLine("运行在Linux上"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // macOS特定代码 Console.WriteLine("运行在macOS上"); }
权限问题:在 Linux/macOS 上需要注意文件和目录的权限
十、总结
控制台应用程序是 C# 开发中的基础类型,虽然没有图形界面,但具有轻量、高效、跨平台等优势,广泛应用于各种场景:
- 系统工具和脚本
- 后台服务和任务
- 开发和调试辅助工具
- 自动化测试和部署脚本
本文介绍了控制台应用的各种功能和使用方法,包括:
- 基础输入输出
- 颜色和光标控制
- 命令行参数处理
- 交互设计(菜单、进度条)
- 异步操作
- 跨平台开发注意事项
掌握这些知识,可以帮助你开发出功能完善、用户体验良好的控制台应用程序。控制台应用虽然简单,但却是每个 C# 开发者必须掌握的基础技能,也是深入学习.NET
开发的起点。