(转载)dotnet core 中文乱码 codepages
引子
转载自:http://www.jianshu.com/p/1c9c59c5749a
上文中我查阅了一些cli的源码, 闲来无事就继续翻代码, 冥冥之中自有天意, 在无尽的代码中, 我看到了这样一个注释
// by default, .NET Core doesn't have all code pages needed for Console apps.
// see the .NET Core Notes in https://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
dotnet core 团队的思路是好的, 提供一个比较小的程序集, 码农们按自己的需求自行添加需要的依赖, 可以生成更小的程序集, 完全同意. But, 我猜肯定有人坠坑过.

有人坠么?
随便google了一下得出以下结果

果不出我所料, 中奖的兄弟还不少, 不过也早有大神对此事进行过叙述, 并且早已在其文中给出解决方法, 大神的文章在此 难道.NET Core到R2连中文编码都不支持吗?(http://www.cnblogs.com/artech/archive/2016/05/18/5507092.html)
有人会问了, 那你还写个屁文干啥?

事还没完!
为啥没完? 因为看到大神文章的评论中一个兄弟在坑中还没爬上来. 川酷不能见死不救是不是?
据那位仁兄所说, 事情的经过是这样的.
Console.WriteLine("你好, 世界!");
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Console.WriteLine("你好, 世界!");
按大神文章所述, 注册了CodePages 编码则为UTF-8, 中文不应该乱码, 可事实是

难道大神也错了吗? 当然不会!
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
正常情况下这句代码足矣解决问题, 依cli注释所说, 对于Console程序, 并没有添加所有的code page, 而且注释中给出的微软官方解决方案也是添加codepage 的dll程序集, 并添加上面那句代码.
这个时候我又找到了另外一个大神的blog,里面有另一种解决方案
public static void Main(string[] args)
{
Console.OutputEncoding = System.Text.Encoding.UTF8;//第一种方式:指定编码
//Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//第二种方式
Console.Read();
}
既然有方案一, 川酷肯定要试一下.
Console.WriteLine("你好, 世界!");
Console.OutputEncoding=Encoding.UTF8;
//Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Console.WriteLine("你好, 世界!");
大神就是大神, 这招灵!

不过第二行的输出有一点小问题, 有兴趣的童鞋研究一下, 在此不再赘述.

让我带你飞!
依川酷的风格, 翻代码的时候到了! 既然问题出在Console中, 那就找Console的代码来看下. 有兴趣的可以在这里获取代码 . 让我们找到Console.cs这个文件, 可以看到相应的WriteLine方法的重载.
[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(String value)
{
Out.WriteLine(value);
}
再看Out是个什么鬼.
public static TextWriter Out
{
get { return Volatile.Read(ref s_out) ?? EnsureInitialized(ref s_out, () => CreateOutputWriter(OpenStandardOutput())); }
}
然后我们发现s_out就是用于输出的TextWriter.
并且在第一次调用的时候会创建一个新的.
private static TextWriter CreateOutputWriter(Stream outputStream)
{
return SyncTextWriter.GetSynchronizedTextWriter(outputStream == Stream.Null ?
StreamWriter.Null :
new StreamWriter(
stream: outputStream,
encoding: new ConsoleEncoding(OutputEncoding), // This ensures no prefix is written to the stream.
bufferSize: DefaultConsoleBufferSize,
leaveOpen: true) { AutoFlush = true });
}
这样看来TextWriter的Encoding是使用的OutputEncoding, 那我们实践下, 这个初始的OutputEncoding到底是什么.


既然是UTF-8为何还是乱码? 此事还应该从微软的那句注释说起, 人家说了, 默认是没有添加codepage的, 即使你现在是UTF-8编码, 但是程序中没有codepage, 当然没办法处理. 我们来看看OutputEncoding的源码吧.
public static Encoding OutputEncoding
{
get
{
return Volatile.Read(ref s_outputEncoding) ?? EnsureInitialized(ref s_outputEncoding, () => ConsolePal.OutputEncoding);
}
set
{
CheckNonNull(value, "value");
lock (InternalSyncObject)
{
// Set the terminal console encoding.
ConsolePal.SetConsoleOutputEncoding(value);
// Before changing the code page we need to flush the data
// if Out hasn't been redirected. Also, have the next call to
// s_out reinitialize the console code page.
if (Volatile.Read(ref s_out) != null && !s_isOutTextWriterRedirected)
{
s_out.Flush();
Volatile.Write(ref s_out, null);
}
if (Volatile.Read(ref s_error) != null && !s_isErrorTextWriterRedirected)
{
s_error.Flush();
Volatile.Write(ref s_error, null);
}
Volatile.Write(ref s_outputEncoding, (Encoding)value.Clone());
}
}
}
我猜问题就出在了ConsolePal.SetConsoleOutputEncoding(value) 这一句.
我相信大家记得, 在我显性set了OutputEncoding为UTF-8之后控制台的中文显示就正常了. 也就是说对OutputEncoding做了set动作之后, 会强制Console窗口引入codepage文件.
Summary
比较一下两种解决方式, 其实两者有本质的不同, SetConsoleOutputEncoding是为这个控制台实例做编码的设置, 而 RegisterProvider 是为当前这个程序集添加codepage.
之所以 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)不起作用是因为前面的一句Console.WriteLine("你好, 世界!")已经使该命令行窗口初始化了编码. 执行Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)并不对命令行窗口起作用, 在这里给做一个实验, 我相信大家就可以清楚中间到底发生了什么.
首先, 重复刚开始的代码.
Console.WriteLine("你好, 世界!");
// Console.OutputEncoding=Encoding.UTF8;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Console.WriteLine("你好, 世界!");
得到的结果是这样的.

然后为该命令行执行这句Console.OutputEncoding=Encoding.UTF8;. 再看下结果.

其实此时的RegisterProvider方法已经没有意义了, 因为命令行已经加载了codepage. 就是这样, 完结!

欢迎大家讨论, 如果有觉得不对或不妥的地方也希望大家可以指正, 我会努力写一些高质量的文章.
(转载)dotnet core 中文乱码 codepages的更多相关文章
- 【转载】JSP中文乱码问题
原作者http://www.cnblogs.com/xing901022/p/4354529.html 阅读目录 之前总是碰到JSP页面乱码的问题,每次都是现在网上搜,然后胡乱改,改完也不明白原因. ...
- 转载-MAC Mysql中文乱码解决方法
相关链接: http://www.siguoya.name/pc/home/article/235 如有,有问题可以留言.
- jsp中文乱码解决办法
一.JSP页面显示乱码 二.表单提交中文时出现乱码 三.数据库连接 大家在JSP的开发过程中,经常出现中文乱码的问题,可能一至困扰着您,我现在把我在JSP开发中遇到 的中文乱码的问题及解决办法写出来供 ...
- JMeter3.0(三十八)图形化HTML报告中文乱码问题处理(转载)
转载自 http://www.cnblogs.com/yangxia-test 由于个人在JMeter 3.0的实际应用中,脚本中的Test Plan/Sampler等元件命名都没有使用中文,所以在之 ...
- 【转载】JMeter3.0图形化HTML报告中文乱码问题处理
由于个人在JMeter 3.0的实际应用中,脚本中的Test Plan/Sampler等元件命名都没有使用中文,所以在之前介绍Dashboard Report特性的博客(原文戳这里))成文时,没有提到 ...
- .Net Core 控制台输出中文乱码
Net Core 控制台输出中文乱码的解决方法: public static void Main(string[] args) { Console.Output ...
- Ubuntu14.04安装中文输入法以及解决Gedit中文乱码问题[转载]
转载自:http://www.cnblogs.com/zhcncn/p/4032321.html 写在前面:解决gedit 在txt文件格式出现乱码的问题,在我自己的操作中是需要把系统设置成中文显示环 ...
- JSP中pageEncoding和charset区别,中文乱码解决方案(转载)
转载自:JSP中pageEncoding和charset区别,中文乱码解决方案 JSP指令标签中<%@ page contentType="text/html;charset=GB23 ...
- 转载:Ununtu下中文乱码解决方案
转载: 添加中文字符编码: $sudo vim /var/lib/locales/supported.d/local #添加下面的中文字符集 zh_CN.GBK GBK zh_CN.GB2312 GB ...
随机推荐
- Shell编程中while与for的区别及用法详解【转】
在shell编程中经常用到循环,常用的循环有for和while循环两种.while循环默认以行读取文件,而for循环以空格读取文件切分文件,本篇就结合现网的一些使用示例说说二者的用法和区别. 一.常用 ...
- Python3学习笔记28-HtmlTestRunner
HtmlTestRunner是unittest模块下的一个拓展,用来生成测试报告.原生的可以自己找下下载地址,原生的看着比较丑.这次使用的是经过一些大佬优化之后的.具体GitHub地址:https:/ ...
- Flask组件
组件踩坑记录 : 先注册组件在使用配置(...) flask-script Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shel ...
- Go学习笔记(只有链接)
Go学习笔记 link: https://blog.csdn.net/u011304970/article/details/69908641 仅作为记录使用.
- select下拉框插件jquery.editable-select
项目中有个需求,下拉框既可以下拉选择,也可以手动填写 html代码 <span>数据来源</span> </select> js代码 $('#noMean').ed ...
- Windows添加.NET Framework 3.0 NetFx3 失败 - 状态为:0x800f0950
原文链接:https://answers.microsoft.com/zh-hans/insider/forum/all/win10-dism%E9%94%99%E8%AF%AF-0x800f0950 ...
- 在Ubuntu 15下搭建V/P/N服务器pptpd安装和配置
在Ubuntu 15下搭建VPN服务器pptpd安装和配置 在ubuntu下配置vpn的方式有很多种,其中比较常见的是pptpd,它配置简单,但是安全性不高,不过对于一般使用来说足够了,我按照程搭建了 ...
- Confluence 6 数据库支持的驱动
数据库 驱动已捆绑? JDBC 驱动 备注 更多信息 PostgreSQL 9.4-1202 JDBC 41 driver download 我们推荐你使用 JDBC 4 的驱动. 如果你希望使用更新 ...
- Confluence 6 用户目录图例 - 连接 Jira
上面的图:Confluence 连接到 JIRA 为用户管理. https://www.cwiki.us/display/CONFLUENCEWIKI/Diagrams+of+Possible+Con ...
- js数组的实例方法sort() 排序方法的运用,不再只是.sort()
1, sort() 不传回调函数的话,默认按照字母顺序(字符编码)的顺序进行排序. 2, sort() 通过传回调函数来控制从小到大的排序还是从大到小的排序: var arr = [1,23,5,6, ...