.NET CORE 怎么样从控制台中读取输入流
.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 怎么样从控制台中读取输入流的更多相关文章
- 在.NET Core控制台中使用依赖注入
本文介绍如何在控制台应用程序中使用微软提供的依赖注入功能,掌握控制台中的用法后,可以扩展到构建windows服务中. 创建控制台应用程序 添加DependencyInjection的引用 Instal ...
- .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中
目录 .NET Core实用技巧(一)如何将EF Core生成的SQL语句显示在控制台中 前言 笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在 ...
- Azure Service Bus(二)在NET Core 控制台中如何操作 Service Bus Queue
一,引言 上一篇讲到关于 Azure ServiceBus 的一些概念,讲到 Azure Service Bus(服务总线),其实也叫 "云消息服务",是微软在Azure 上提供的 ...
- .NET Core的文件系统[1]:读取并监控文件的变化
ASP.NET Core 具有很多针对文件读取的应用.比如我们倾向于采用JSON文件来定义配置,所以应用就会涉及针对配置文件读取.如果用户发送一个针对物理文件的HTTP请求,应用会根据指定的路径读取目 ...
- 【转载】chrome控制台中看见的cookie属性详解
在chrome控制台中的resources选项卡中可以看到cookie的信息. 一个域名下面可能存在着很多个cookie对象. name字段为一个cookie的名称. value字段为一个cookie ...
- java读取输入流
java读取输入流两种 private static byte[] readStream(InputStream in){ if(in==null){ return null; } byte[] bu ...
- C# 计算字符串在控制台中的显示长度
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 利用跨域请求来隐藏firbug控制台中的Ajax请求
本文链接:http://www.orlion.ml/63/ 普通jquery的Ajax请求在控制台中是可见的,如下: 而在利用jsonp(json with padding)进行Ajax跨域时,发现A ...
- 解决ftp连接出现 无法从控制 Socket 读取。Socket 错误 = #10054。
ftp连接会显示以下错误信息 无法从控制 Socket 读取.Socket 错误 = #10054 或者是这样的信息 Opening data channel for directory list.T ...
随机推荐
- Flutter学习笔记(10)--容器组件、图片组件
如需转载,请注明出处:Flutter学习笔记(10)--容器组件.图片组件 上一篇Flutter学习笔记(9)--组件Widget我们说到了在Flutter中一个非常重要的理念"一切皆为组件 ...
- 在Ubuntu中安装Docker和docker的使用
1.在Ubuntu中安装Docker 更新ubuntu的apt源索引 sudo apt-get update 安装包允许apt通过HTTPS使用仓库 sudo apt-get install \ ap ...
- eclipse(java windows)
百度云:链接:http://pan.baidu.com/s/1i4Zjv97 密码:u0qh 官方下载网址:http://www.eclipse.org/downloads/eclipse-pa ...
- 最全的Vue组件通信方式总结
1.一图认清组件关系名词 父子关系:A与B.A与C.B与D.C与E 兄弟关系:B与C 隔代关系:A与D.A与E 非直系亲属:D与E 总结为三大类: 父子组件之间通信 兄弟组件之间通信 跨级通信 2.8 ...
- jQuery中的事件与动画 笔记整理
一. jQuery中的事件 jQuery事件是对javaScript事件的封装. 1.基础事件 在javaScript中,常用的基础事件有鼠标事件.键盘事件.window事件.表单事件.事件的绑定和处 ...
- 【iOS】UITableViewDelegate 方法没有调用
可能原因:没有调用 reloadData 方法. [self.tableView reloadData];
- 【译】Hello Kubernetes快速交互实验手册
原文:https://kubernetes.io/docs/tutorials 翻译:Edison Zhou 一.基本介绍 此交互实验可以让你不用搭建K8S环境就可以轻松地尝试管理一个简单的容器化应用 ...
- KD-tree 专题「Hide and Seek · 巧克力王国」
Lockey的瞎理解 抄了一遍板子又水了俩题,感觉对KD-tree 稍稍理解了一点儿,唠叨一下(二维的KD-tree),如有错误请指出(Lockey 洗脸恭听) 普通平衡树维护的是一维的序列,但对于二 ...
- 微服务SpringCloud之Spring Cloud Config配置中心Git
微服务以单个接口为颗粒度,一个接口可能就是一个项目,如果每个项目都包含一个配置文件,一个系统可能有几十或上百个小项目组成,那配置文件也会有好多,对后续修改维护也是比较麻烦,就和前面的服务注册一样,服务 ...
- 0x03 前缀和与差分
前缀和 [例题]BZOJ1218 激光炸弹 计算二位前缀和,再利用容斥原理计算出答案即可. #include <iostream> #include <cstdio> #inc ...