在C#中,从控制台或标准输入流读取字符串是初学者最早接触的基础操作之一。不同场景下需要的输入方式并不相同,有的要求整行读取,有的要求不回显密码,有的则要处理大量文本。下面通过具体方法和代码来说明如何实现字符串输入。

一、使用Console.ReadLine读取整行字符串
Console.ReadLine是C#中最常用的字符串输入函数。它会从标准输入流读取下一行字符,直到用户按下回车键为止,并把回车之前的内容作为string返回。需要注意的是,该方法返回的结果已经去掉了行尾的换行符,但当用户直接按回车而没有输入任何内容时,返回的是空字符串而不是null。
在多数交互程序中,我们习惯把输入结果直接赋值给string变量。由于ReadLine本身不会返回null(除非输入流已关闭),因此一般只需判断是否为空串即可。下面是一段基础的示例,演示如何读取用户名并做简单校验。
using System;
class Program
{
static void Main()
{
Console.Write("请输入你的名字:");
string name = Console.ReadLine();
if (string.IsNullOrEmpty(name))
{
Console.WriteLine("输入为空,使用默认名称");
name = "匿名用户";
}
else
{
Console.WriteLine("你好," + name);
}
}
}
这种方式的优点是简单直观,适合大多数命令行工具。缺点是它是阻塞调用,在GUI程序或异步服务中不能直接使用,且只能按行读取,无法逐字符控制。
另外,如果控制台编码设置不正确,中文输入可能会出现乱码。可以在程序开头设置Console.InputEncoding为System.Text.Encoding.UTF8来规避此类问题。对于跨平台场景,.NET Core及以上版本通常能自动处理,但在老旧框架下仍需手动指定。
二、使用Console.ReadKey拼接实现自定义字符串输入
当我们需要实现类似密码输入不回显,或者限制只能输入特定字符时,Console.ReadLine就不再适用。此时可以用Console.ReadKey方法逐个读取按键,并自行拼接到字符串中。ReadKey返回ConsoleKeyInfo结构,包含按键字符和修饰状态。
下面示例展示如何读取用户按键,遇到回车结束,遇到退格则删除上一个字符,其他可见字符追加到StringBuilder中,从而实现基础的隐藏式字符串输入。
using System;
using System.Text;
class Program
{
static string ReadPassword()
{
StringBuilder sb = new StringBuilder();
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
break;
}
else if (key.Key == ConsoleKey.Backspace)
{
if (sb.Length > 0)
{
sb.Length--;
}
}
else if (!char.IsControl(key.KeyChar))
{
sb.Append(key.KeyChar);
}
}
return sb.ToString();
}
static void Main()
{
Console.Write("请输入密码:");
string pwd = ReadPassword();
Console.WriteLine();
Console.WriteLine("密码长度为:" + pwd.Length);
}
}
这种方法的优势在于完全掌控输入过程,可以屏蔽回显、过滤字符、限制长度。缺点是代码量比ReadLine大很多,且要自行处理光标移动和特殊键,容易在复杂终端环境下出现兼容问题。
在真实项目中,如果是桌面应用应使用TextBox的PasswordChar属性,而不是在控制台模拟。但在编写内部运维脚本或教学示例时,ReadKey拼接仍是理解输入流本质的好办法。
三、通过Console.In文本读取器批量输入
除了上述两种交互式方法,C#还把标准输入暴露为Console.In属性,它是一个TextReader。利用它可以调用ReadToEnd读取全部剩余输入,或用ReadLine在循环中批量获取多行字符串。这种方式常用于从管道或重定向文件读取数据。
例如,在Linux shell中通过命令把文件内容传给程序,程序可用ReadToEnd一次性拿到全部文本。下面代码演示统计输入的行数和字符数。
using System;
class Program
{
static void Main()
{
string all = Console.In.ReadToEnd();
string[] lines = all.Split(new char[] { 'n' }, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine("行数:" + lines.Length);
Console.WriteLine("字符数:" + all.Length);
}
}
使用TextReader的好处是能自然融入.NET的IO体系,配合StreamReader做编码转换也很方便。不过ReadToEnd会一直等待到流结束,所以在纯键盘输入时需用Ctrl+Z(Windows)或Ctrl+D(Linux)发送结束信号。
如果输入量很大,建议用Console.In.ReadLine在while循环中逐行处理,避免一次性加载占用过多内存。这也是日志分析类和批处理类工具的常见写法。
四、常见误区与注意点
很多人在使用C#输入函数时会混淆Console.Read和Console.ReadLine。Read方法返回的是输入字符的整数ASCII值,而不是字符串,若直接赋给string会得到错误结果。正确的字符串输入应优先使用ReadLine或ReadKey组合。
另一个误区是认为ReadLine在输入为空时返回null。实际上只有输入流被关闭(如管道结束)时才返回null,普通回车返回的是空字符串。因此判空要用string.IsNullOrEmpty而不是单纯的null判断,这样更健壮。
using System;
class Program
{
static void Main()
{
int c = Console.Read(); // 返回int,不是字符串
Console.WriteLine("Read返回值类型为整数:" + c);
string s = Console.ReadLine(); // 真正读取字符串
if (s == null)
{
Console.WriteLine("流已结束");
}
else if (s == string.Empty)
{
Console.WriteLine("用户直接回车");
}
}
}
最后,在多线程或异步程序中不要在主线程以外随意调用Console输入方法,它不支持并发读取。若必须做异步输入,可考虑用Task.Run包装并妥善同步上下文,或者改用更现代的System.Console高级API。
掌握这几类C#字符串输入方式后,就能根据交互需求、性能要求和运行环境灵活选型,写出既稳定又易维护的控制台程序。
C#字符串输入Console_ReadLine修改时间:2026-08-01 21:36:32