.NET CORE 怎么样从控制台中读取输入流

从Console.ReadList/Read 的源码中,可学习到.NET CORE 是怎么样来读取输入流。

也可以学习到是如何使用P/Invoke来调用系统API

Console.ReadList 的源码为

		[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static string ReadLine()
{
return In.ReadLine();
}

其中In为。


internal static T EnsureInitialized<T>(ref T field, Func<T> initializer) where T : class =>
LazyInitializer.EnsureInitialized(ref field, ref InternalSyncObject, initializer); public static TextReader In => EnsureInitialized(ref s_in, () => ConsolePal.GetOrCreateReader());

可以看到他是个TextRead

接下来,我们看看ConsolePal.GetOrCreateReader()方法中,是怎么样获取到一个Reader的。

转到ConsolePal.Windows.cs 的源码,可以看到,

internal static TextReader GetOrCreateReader()
{
Stream inputStream = OpenStandardInput();
return SyncTextReader.GetSynchronizedTextReader(inputStream == Stream.Null ?
StreamReader.Null :
new StreamReader(
stream: inputStream,
encoding: new ConsoleEncoding(Console.InputEncoding),
detectEncodingFromByteOrderMarks: false,
bufferSize: Console.ReadBufferSize,
leaveOpen: true));
}

继续跳转,查看方法OpenStandardInput


public static Stream OpenStandardInput()
{
return GetStandardFile(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE, FileAccess.Read);
}

继续看方法


private static Stream GetStandardFile(int handleType, FileAccess access)
{
IntPtr handle = Interop.Kernel32.GetStdHandle(handleType);
// 此处源码一坨注释被我删掉了。^_^
if (handle == IntPtr.Zero || handle == InvalidHandleValue ||
(access != FileAccess.Read && !ConsoleHandleIsWritable(handle)))
{
return Stream.Null;
} return new WindowsConsoleStream(handle, access, GetUseFileAPIs(handleType));
}

哈哈,终于要看到了Interop.Kernel32.GetStdHandle 这个方法就是调用系统API接口函数的方法。

Interop.GetStdHandle.cs 中调用GetStdHandle 的系统API

System.Console.csproj 的项目文件中。

可以看到,在项目文件中,使用条件编译,将不同的文件包含进来,调用不同系统的API

<!-- Windows -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<Compile Include="$(CommonPath)\CoreLib\Interop\Windows\Kernel32\Interop.GetStdHandle.cs">
<Link>Common\CoreLib\Interop\Windows\Interop.GetStdHandle.cs</Link>
</Compile>
</ItemGroup>
<!-- Unix -->
<ItemGroup Condition=" '$(TargetsUnix)' == 'true'">
</ItemGroup>

回到GetStandardFile 中看到返回一个WindowsConsoleStream

其中Read方法,调用了系统API。


private static unsafe int ReadFileNative(IntPtr hFile, byte[] bytes, int offset, int count, bool isPipe, out int bytesRead, bool useFileAPIs)
{
if (bytes.Length - offset < count)
throw new IndexOutOfRangeException(SR.IndexOutOfRange_IORaceCondition); // You can't use the fixed statement on an array of length 0.
if (bytes.Length == 0)
{
bytesRead = 0;
return Interop.Errors.ERROR_SUCCESS;
} bool readSuccess;
fixed (byte* p = &bytes[0])
{
if (useFileAPIs)
{
readSuccess = (0 != Interop.Kernel32.ReadFile(hFile, p + offset, count, out bytesRead, IntPtr.Zero));
}
else
{
int charsRead;
readSuccess = Interop.Kernel32.ReadConsole(hFile, p + offset, count / BytesPerWChar, out charsRead, IntPtr.Zero);
bytesRead = charsRead * BytesPerWChar;
}
}
if (readSuccess)
return Interop.Errors.ERROR_SUCCESS; int errorCode = Marshal.GetLastWin32Error();
if (errorCode == Interop.Errors.ERROR_NO_DATA || errorCode == Interop.Errors.ERROR_BROKEN_PIPE)
return Interop.Errors.ERROR_SUCCESS;
return errorCode;
}

useFileAPIs 参数,决定是使用操作系统 ReadFile还是 ReadConsole API。

这2个API。都是可以读取到控制台的输入流。


对于.NET CORE 源码中有很多 XXXX.Unix.cs,XXXX.Windows.cs

类名都是XXXX.例如 ConsolePal 这个内部类。

使用条件条件编译。达到不同平台使用对应的 OS API来调用。

.NET CORE 怎么样从控制台中读取输入流的更多相关文章

  1. 在.NET Core控制台中使用依赖注入

    本文介绍如何在控制台应用程序中使用微软提供的依赖注入功能,掌握控制台中的用法后,可以扩展到构建windows服务中. 创建控制台应用程序 添加DependencyInjection的引用 Instal ...

  2. .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中

    目录 .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中 前言 笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在 ...

  3. Azure Service Bus(二)在NET Core 控制台中如何操作 Service Bus Queue

    一,引言 上一篇讲到关于 Azure ServiceBus 的一些概念,讲到 Azure Service Bus(服务总线),其实也叫 "云消息服务",是微软在Azure 上提供的 ...

  4. .NET Core的文件系统[1]:读取并监控文件的变化

    ASP.NET Core 具有很多针对文件读取的应用.比如我们倾向于采用JSON文件来定义配置,所以应用就会涉及针对配置文件读取.如果用户发送一个针对物理文件的HTTP请求,应用会根据指定的路径读取目 ...

  5. 【转载】chrome控制台中看见的cookie属性详解

    在chrome控制台中的resources选项卡中可以看到cookie的信息. 一个域名下面可能存在着很多个cookie对象. name字段为一个cookie的名称. value字段为一个cookie ...

  6. java读取输入流

    java读取输入流两种 private static byte[] readStream(InputStream in){ if(in==null){ return null; } byte[] bu ...

  7. C# 计算字符串在控制台中的显示长度

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  8. 利用跨域请求来隐藏firbug控制台中的Ajax请求

    本文链接:http://www.orlion.ml/63/ 普通jquery的Ajax请求在控制台中是可见的,如下: 而在利用jsonp(json with padding)进行Ajax跨域时,发现A ...

  9. 解决ftp连接出现 无法从控制 Socket 读取。Socket 错误 = #10054。

    ftp连接会显示以下错误信息 无法从控制 Socket 读取.Socket 错误 = #10054 或者是这样的信息 Opening data channel for directory list.T ...

随机推荐

  1. Django REST Framework(DRF)_第一篇

    认识RESTful REST是设计风格而不是标准,简单来讲REST规定url是用来唯一定位资源,而http请求方式则用来区分用户行为. REST接口设计规范 HTTP常用动词 GET /books:列 ...

  2. python课堂整理13---函数的作用域及匿名函数

    name = 'alex' def foo(): name = 'jinling' def bar(): print(name) return bar a = foo() print(a) 阅读上述代 ...

  3. python找质数对

    python找质数对 编写python脚本,输入一个正整数,输出有几对质数的和等于这个正整数. 例如输入一个正整数10,可以找出有“3+7=10”.“5+5=10”两个质数对的和为10. 要实现这个功 ...

  4. golang 任意类型之间相互转换

    在处理一些参数的时候,可能需要将参数转换为各种类型,这里实现一个通用的转换函数,实现各种类型之间的相互转换. 当然,如果源数据格式和目标数据类型不一致,是会返回错误的.例如将字符串“一二三”转换为数值 ...

  5. django第三次(转自刘江)

    所有的模型字段都可以接收一定数量的参数,比如CharField至少需要一个max_length参数.下面的这些参数是所有字段都可以使用的,并且是可选的. null 该值为True时,Django在数据 ...

  6. thymeleaf介绍

    作者:纯洁的微笑出处:http://www.ityouknow.com/  增加了一小部分内容 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完 ...

  7. Golang高效实践之泛谈篇

    前言 我博客之前的Golang高效实践系列博客中已经系统的介绍了Golang的一些高效实践建议,例如: <Golang高效实践之interface.reflection.json实践>&l ...

  8. 我的ubuntu kylin中mentohust的使用历程

    1首先下载mentohus 最新版下载(包括源码):http://code.google.com/p/mentohust/downloads/list 2打开终端(Ctrl+Alt+T) 输入sudo ...

  9. 深入理解JVM-类加载器深入解析(2)

    深入理解JVM-类加载器深入解析(2) 加载:就是把二进制形式的java类型读入java虚拟机中 连接: 验证: 准备:为类变量分配内存,设置默认值.但是在到达初始化之前,类变量都没有初始化为真正的初 ...

  10. JavaFX Metro UI 和 开发库

    目录 [隐藏] 1 Metro UI For JavaFX! 1.1 例子 1.2 Switch 1.3 Button 1.4 案例: 2 ConsrolsFX 3 Notification 的使用 ...