读书笔记—CLR via C#字符串及文本
前言
这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享
字符(System.Char)
- 字符在.NET 中表示成16位Unicode代码值
- System.Char.MinValue = '\0' MaxValue = '\uffff'
- 实例方法GetUnicodeCategory,返回System.Globalization.UnicodeCategory枚举(包含控制字符、货币符号、小写字母、大些字母、标点符号、数学符号或者其他由Unicode定义的字符)
- 简化接口为IsDigit, IsLetter, IsUpper, IsLower, IsPunctuation, IsLetterOrDigit, IsControl, IsNumber, IsSeparator, IsSurrogate等
- 以上Is简化接口内部都调用GetUnicodeCategory,并简单返回true或false
- ToLowerInvariant或ToUpperInvariant忽略语言文化 ToLower和ToUpper则使用调用线程关联的语言文化信息
- CompareTo忽略语言文化结果,GetNumericValue返回字符的数值形式
- 与数值进行转型
- 转型(强制类型转换)效率最高,直接使用编译器IL指令。不必调用额外的方法。可指定checked或unchecked
- Convert,强制使用checked方式。如果发现数据丢失,就会抛出OverflowException
- 使用IConvertible 接口,数值类型都实现了此接口,效率最差,因为使用接口会进行装箱。对于无法转换会InvalidCastException
字符串(System.String)
- String代表不可变的顺序字符集,String代表不可变的顺序字符集
- CLR用特殊的方式构造文本常量String对象,构造函数允许使用字符指针作为参数构造
- 对于非文本常量字符串使用+操作符,连接则会在运行时进行,对于连接多个字符串,避免使用+操作符,它会在堆上创建多个字符串对象,增加GC的负载影响性能
- 字符串不可变,所以操作或访问字符串时不会发生线程同步问题
- CLR通过“字符串留用”机制让多个相同的string共享同一个string对象。节省性能
- 字符串显式留用
- Intern,获取一个String,获得它的哈希吗,并在内部哈希表中检查是否有相匹配的。如果存在一个完全相同的,返回对这个已经存在的String对象的一个引用。如果不存在,创建副本,将副本添加道内部哈希表,返回对副本的引用
- IsInterned,也获取一个String,并在内部哈希表中查找它。如果找到,返回留用对象的引用。然而如果没有,则会返回null,它不会将字符串添加到哈希表中
- 程序集加载时,CLR默认会留用程序集的元数据中描述的所有文本常量字符串
- 程序集标记 assembly attribute/flag System.Runtime.CompilerServices.CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning) 特性,指定程序集默认不进行字符串留用,一般CLR会忽略该属性
- 编译器只在模块的元数据中将文本常量字符串写入一次,引用该字符串的所有代码都会被修改,以引用元数据中的同一个字符串。这样可以减少模块和程序集的大小。其实C/C++编译器多年来也一直采用这个技术,称为字符串池。字符串池时提升字符串性能的一种有效方式
- 代理项字符串,使用System.Globalization.StringInfo类型处理。提供功能将字符串拆分为文本元素并循环访问这些文本元素
- string对象的一些接口,比如Copy和CopyTo,会创建新的字符串对象,确保引用(指针)不同,即使字符串包含相同字符内容,还有Insert,Remove,PadLeft,Replace,Split等等,都是返回一个新的字符串对象
- string.ToString() 返回对同一个对象(this)的引用
字符串构造器(System.Text.StringBuilder)
- 字符串构造器,动态构造字符串。包含由Char结构组成的数组字段,高效率缩短字符串或更改字符串中的字符,如果字符串太大,SB自动分配一个新的更大的数组,复制字符,并开始使用新数组。前一个数组会被垃圾回收。建议在可预见的情况下指定StringBuilder的容量
- 内部方法EnsureCapacity,其实List<T>等集合也有这么一个方法。负责维护容量和自动扩容
- StringBuilder的很多方法都是返回同一个引用,所以方便链式调用 sb.Append().Replace().Remove()...
字符串显示与文化
- 在ToString方法的实现中,为了使调用者能选择格式和语言文化,类型应该实现System.IFormattable接口。基元数值基本都实现了这个接口
- 格式化一个数字时,ToString会检查为formatProvider参数传递的值,如果传递的是null,ToString会通过读取Thread.CurrentThread.CurrentCulture属性判断与调用线程关联的语言文化。如果一个类型实现了该接口,就认为类型的一个实例能提供符合语言文化的格式信息,与调用线程关联的语言文化应被忽略。一般使用的实现为 CultureInfo,注意属性对象为NumberFormatInfo和DateTimeFormatInfo。针对数字和时间进行格式化。(format默认为常规格式,formatProvider默认为调用线程的语言文化信息。)
- 如果不针对具体语言文化格式化,应该调用CultureInfo.InvariantCulture, 语言中立
- FCL的IFormatProvider接口实现,1 CultureInfo 2 NumberFormatInfo 3 DateTimeFormatInfo
- 当使用自定义ICustomFormatter时,最好使用string.Format的方式构造字符串,不要用ToString,因为像字符串或日期都对Format做了限制
- 一般数值或日期的ToString中的Provider,使用CultureInfo来代替就OK,或者自己提供DateTimeFormatInfo或NumberFormatInfo,实际上前者包含了后面两者的属性定义,在GetFormat中判断调用对象的类型返回后面两者中的一个
- 自定义格式需要实现IFormatProvider和ICustomFormatter,然后把参数传递给执行自定义格式的设置操作方法,比如String.Format
字符串解析和转换
- Convert,Convert基本上是一个封装,在内部调用ToString或者Parse等方法。内部主要接口就是Number.Parse(NumberStyles)和DateTime.Parse(DateTimeStyles)等
- Parse和TryParse方法
字符编码
- UTF-16时将每个16位字符编码为2个字节,不对字符产生影响,也不会压缩,性能出色
- UTF-8将部分字符编码为1个字节,部分编码为2个字节。部分编码为3甚至4个字节,对应区间段: 0x0080/0x0080~0x07FF/0x0800/surrogate pairs
- UTF-32使用4字节来编码,每个字符都是4个字节,不需要考虑代理项的问题,通常在内部使用
- UTF-7编码,用于旧式系统。使用7位值表示,此编码方案已被Unicode协会淘汰
- ASCII编码方案将16位字符编码成ASCII字符;值小于0x0080的16位字符被转换成单字节。超过0x007F的任何字符都不能被转换,否则字符的值会丢失。由于字符串完全由ASCII范围(0x00~0x7F)内的字符构成,ASCII编码方案就能将数据压缩到原来的一般,而且速度非常快(高位字节会被直接截掉。)不过如果字符在ASCII范围之外,编码就不适合,因为字符的值会丢失
- 编码接口,System.Text.Encoding 例如:Byte[] encodedBytes = encodingUTF8.GetBytes(s); BitConverter.ToString(encodedBytes)
- Encoding.Default属性返回一个对象,它使用用户当前的代码页进行编码/解码。当前用户页编码在控制面板的“区域和语言选项”对话框中,通过“非Unicode程序中所使用的当前语言”的选项来指定,通常不鼓励开发人员使用Default属性,否则程序的行为随着机器的设置而变
- 分配字节时可以利用方法Encoding派生类的GetByteCount方法,它能统计对一组字符进行编码所产生的字节数,同时不实际进行编码
- GetCharCount()返回解码得到的字符数,同时也不实际进行编码。可以节省内存和重用数组
- 以上两个方法性能不佳,如果要性能更加,使用GetMaxByteCount和GetMaxCharCount方法,返回最坏情况下的值
- 针对文件流或者网络流,如果需要跨块处理的字节流,则需要使用Encoder(通过GetEncoder获得)和Decoder(通过GetDecoder获得),它们会维护连续调用间的状态信息,它会尽可能多的解码字节数组,如果字节数组包含的字节不足以完成一个字符,剩余的字节会保存到Decoder对象内部。下次调用时,它们会利用之前剩余的字节再加上新的字节。
- 中文的全角和半角问题,因为所有的字符在CLR中都是以Unicode-16编码的,这个问题就比较好处理了,全角和半角的值它们相差65248,除了空格相差12256。所以全角的字符若是想转换成半角除空格减12256外,其他相减65248便是相应的半角。全角空格为12288,半角空格为32。其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
- BOM,BOM全称是Byte Order Mark,即字节顺序标记,是一段二进制,用于标识一个文本是用什么编码的,比如当用Notepad打开一个文本时,如果文本里包括这一段BOM,那么它就能判断是采用哪一种编码方式,并用相应的解码方式,就会正确打开文本不会有乱码。如果没有这一段BOM,Notepad会默认以ANSI打开,这种会有乱码的可能性。可以通过Encoding的方法GetPreamble()来判断这编码有没有BOM,目前CLR中只有下面5个Encoding有BOM
- Encoding.Convert可以对字节数组执行编码转换
- 如果给定一个文本,我们不知道它的编码格式,解码时我们如何选择Encoding呢?答案是根据BOM来判断到底是哪种Unicode。UnicodeEncodings[i].GetPreamble()
- 关于编码解码的一些文章参考:http://www.cnblogs.com/criedshy/
- 字符集及编码:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html
Base64字符串编码和解码
- Base-64字符串编码解码,也是一种流行的编码方案,使用System.Convert类的静态方法。
- 具体方法包括 FromBase64String, FromBase64CharArray, ToBase64String, ToBase64CharArray
安全字符串
- 字符串对象可能包含敏感数据,如果和不安全的非托管代码交互,可能造成机密数据的泄露。
- System.Security.SecureString,构造时,在内部分配一个非托管内存块,其中包含一个字符数组,之所以要使用非托管内存块,是为了避开垃圾回收的“罗网”,这些字符串是经过加密的,能防范任何恶意的非安全非托管代码获取机密信息。提供AppendChar, InsertAt, RemoveAt, SetAt等方法。内部会解密字符串然后重新加密字符串。对性能会有影响。通过IDisposable接口可以进行销毁。其中一个字段引用SafeBuffer继承与CriticalFinalizerObject,所以字符串在垃圾回收时,字符内容会保证清零,缓冲区可以释放。而且和string不同,回收之后,加密字符串的内容将不再存在于内存中
- 解密过程,(char*)Marshal.SecureStringToTaskMemUnicode(ss),指针释放Marshal.ZeroFreeCoTaskMemUnicode(char*)
- Marshal类提供了一系列的方法永远操纵安全字符串,包含将字符串解密到缓冲区,以及清零并释放缓冲区
- 关于安全这块,还可以关注以下几块的东西
- System.Security.Cryptography.ProtectedData
- 使用System.Security.Cryptography.ProtectedMemory类
- Configuration cfg.AppSettings.SectionInformation.ProtectSection
- 未完待续。。。可以在探讨.NET安全时继续探讨
读书笔记—CLR via C#字符串及文本的更多相关文章
- CLR via C#字符串和文本处理
一.字符 在.NET Framewole中,字符总是表示成16位Unicode代码值,这简化了国际化应用程序的开发. 每个字符都表示成System.Char结构(一个值类型) 的一个实例.Sy ...
- 读书笔记—CLR via C#异常和状态管理
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
- 读书笔记—CLR via C#反射
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
- 读书笔记—CLR via C#章节3
这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深 ...
- 读书笔记—CLR via C#同步构造28-29章节
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
- python3-cookbook笔记:第二章 字符串和文本
python3-cookbook中每个小节以问题.解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构.函数.类等特性在某类问题上如何更好地使 ...
- 读书笔记—CLR via C#委托和attribute
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
- 读书笔记—CLR via C#章节11-13
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
- 读书笔记—CLR via C#章节8-10
前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...
随机推荐
- 如何使用Maven创建web工程(详细步骤)
使用eclipse插件创建一个web project 首先创建一个Maven的Project例如以下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing ...
- Codeforces 374D Inna and Sequence 二分法+树状数组
主题链接:点击打开链接 特定n一个操作,m长序列a 下列n的数量 if(co>=0)向字符串加入一个co (開始是空字符串) else 删除字符串中有a的下标的字符 直接在序列上搞.简单模拟 # ...
- SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能
原文:SSIS从理论到实战,再到应用(6)----SSIS的自带日志功能 上期回顾: SSIS从理论到实战,再到应用(5)----流程控制之Foreach循环 博主最近新负责了一个ssis大项目的架构 ...
- 多普勒失真信号采样Matlab模拟分析
多普勒失真信号采样Matlab模拟分析 方案 水声通信指的是使用声信号在水中数据传输. 相对而言.电磁信号在水中吸收严重衰减过快,光信号受水中悬浮颗粒的影响,也无法完毕远距离传输. 这两种信号的传播距 ...
- Android自己定义组件系列【8】——面膜文字动画
我们掩盖文字动画Flash中非经货共同体共同,由于Android应用程序开发人员做你想要做这个动画在应用程序中去?本文中,我们看的是如何自己的定义ImageView来实现让一张文字图片实现文字的遮罩闪 ...
- java_eclipse_设置全局编码_utf-8_编译class指定_运行jar乱码解决_不依赖环境
简述: javac时指定 编码 UTF-8 [ javac -encoding UTF-8 Test.java],运行时 java 指定编码 UTF-8 这样就不会出现乱码问题[ javac ...
- Android[安德鲁斯] 文本Air Video 远程播放电脑视频
苹果iOS下列.目前应用Air Video,能力iOS由Wifi远程直接播放电脑视频,无需看视频复制到手机.非常好用!最近使用Android打电话.展望类别似应用,找了很长一段时间没有找到.在仔细的思 ...
- 带格式分离两个RichEditControl的文本
using( RichEditControl selector = new RichEditControl() { RtfText = richTextFromHtml } ) { DocumentR ...
- div中显示某个网页
原文:div中显示某个网页 1.<iframe>方法 2.ajax方法 ajax+流实现无框架限制块刷新: 主框架index页面: js: $(function(){ $("#d ...
- tiny210——uboot移植Makefile文章分析
这东西已经写,我们没有时间发布,如今,终于有时间稍微长送记录汇总uboot学习过程.具体了.以后忘了也能够再温习回来嘛有些特殊字符显示得乱掉了 Makefile追踪技巧: 技巧1:能够先从编译目标開始 ...