前言

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

字符(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. Windows台cocos2d-x 3.2下载一个新的项目,创造的过程

    首先,左右cocos2d-x于windows下一个Android建筑环境, 引用一个网友这个博客<cocos2d-x 3.0rc开发指南:Windows下Android环境搭建>. 这里简 ...

  2. Hadoop Java Hdfs API

    1. 在本地文件系统生成一个文本文件,,读入文件,将其第101-120字节的内容写入HDFS成为一个新文件2. 在HDFS中生成文本文件,读入这个文件,将其第101-120字节的内容写入本地文件系统成 ...

  3. Android读取JSON格式数据

    Android读取JSON格式数据 1. 何为JSON? JSON,全称为JavaScript Object Notation,意为JavaScript对象表示法. JSON 是轻量级的文本数据交换格 ...

  4. 随笔 - Internet缓存文件

    Internet缓存文件 本文地址: http://blog.csdn.net/caroline_wendy 互联网上全部的使用记录, 图片, 音乐, 视频, 都会缓存在本地. 1. 位置: IE-& ...

  5. Json.NET提供依赖注

    Json.NET提供依赖注 [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection) 前言 在一些小型项目的开发情景里,系统不需要大型DI Framework所提 ...

  6. MAC OSX在视图port哪个程序占用,杀死进程的方法

    sudo lsof -i :9000 COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME java    6 ...

  7. SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数

    原文:SQL Server中的CLR编程--用.NET为SQL Server编写存储过程和函数 很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程.触发器和存储过程的,不过之 ...

  8. java_Eclipse主题颜色配置+全屏

    http://www.eclipsecolorthemes.org/ 这个是主题的网站. 在Eclipse里, File->Import->General->Preferences- ...

  9. Arcgis For Android之GPS定位实现

    翻开曾经做的东西,看了看,非常多从逻辑上比較乱,对之做了改动,完毕后实现的效果为: MapActivity源码例如以下: package com.lzugis.map; import java.io. ...

  10. 【高德地图API】从零开始学高德JS API(二)地图控件与插件——测距、圆形编辑器、鼠标工具、地图类型切换、鹰眼鱼骨

    原文:[高德地图API]从零开始学高德JS API(二)地图控件与插件——测距.圆形编辑器.鼠标工具.地图类型切换.鹰眼鱼骨 摘要:无论是控件还是插件,都是在一级API接口的基础上,进行二次开发,封装 ...