前言

这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享

字符(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#字符串及文本的更多相关文章

  1. CLR via C#字符串和文本处理

    一.字符   在.NET Framewole中,字符总是表示成16位Unicode代码值,这简化了国际化应用程序的开发.   每个字符都表示成System.Char结构(一个值类型) 的一个实例.Sy ...

  2. 读书笔记—CLR via C#异常和状态管理

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  3. 读书笔记—CLR via C#反射

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  4. 读书笔记—CLR via C#章节3

    这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深 ...

  5. 读书笔记—CLR via C#同步构造28-29章节

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  6. python3-cookbook笔记:第二章 字符串和文本

    python3-cookbook中每个小节以问题.解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构.函数.类等特性在某类问题上如何更好地使 ...

  7. 读书笔记—CLR via C#委托和attribute

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  8. 读书笔记—CLR via C#章节11-13

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  9. 读书笔记—CLR via C#章节8-10

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

随机推荐

  1. Simditor图片上传

    上一篇文章(Simditor用法)仅仅是简单的默认配置,我们可自己定义工具栏button使其更丰富和实现上传图片功能 初始化编辑器 <script type="text/javascr ...

  2. 比ORA-24777: 我不使用不可移植数据库链接更郁闷的事情达成一致

    现场有一个同步误差,内容如下面:    java.sql.BatchUpdateException: ORA-24777: 不同意使用不可移植的数据库链路    at oracle.jdbc.driv ...

  3. JS匿名函数&闭包

    <html> <head> <title> test </title> </head> <body> <script ty ...

  4. java 中间String分类

    String a = "aaa"; 用这样的方式的时候java首先在内存中寻找"aaa"字符串.假设有.就把aaa的地址给它 假设没有则创建 String a ...

  5. Oracle 数据库 有用的sql语句

    ; SELECT to_date('2014-12-01', 'yyyy-mm-dd') + numtodsinterval(rownum , 'day') FROM DUAL CONNECT BY ...

  6. 如何定义自己的ViewGroup

    在发展中,有时会遇到一些要求.布局和控制系统不仅提供使用,以满足我们的发展,所以这一次就行,通常是你自己的自定义布局(ViewGroup)并控制(View)该.我在这里,我们将用一个简单的例子,当他们 ...

  7. SSIS从理论到实战,再到应用

    原文:SSIS从理论到实战,再到应用 一,是什么(What?) 1.SSIS是Microsoft SQL Server Integration Services的简称,是生成高性能数据集成解决方案(包 ...

  8. MySQL Scale Out

    原文:MySQL Scale Out 简介 MySQL复制中较常见的复制架构有“一主一从”.“一主多从”.“双主”.“多级复制”和“多主环形机构”等,见下图: 最常用,也最灵活的就要数“一主多从”复制 ...

  9. AJAX 怎样在一个UpDatePanel中刷新另一个updatePanel

    原文:AJAX 怎样在一个UpDatePanel中刷新另一个updatePanel 在页面上(.aspx)<asp:UpdatePanel ID="MyID1" runat= ...

  10. CUMCM--总结

    有些事情经历一次就好,一次的经历足以成长. 其实,对于数模真的没什么要说的,也没什么好写的.从9月11日,8点见到赛题,到今天早上8点的提交,短短的三天,度过寂静的黑夜,见到微曦的黎明.三天三夜,9个 ...