C++回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。  也就是说,回调函数它首先是一个函数,然后有一个指针指向它(该指针称为函数指针),在别的代码块中,通过这个函数指针调用了这个函数,仅此而已。  下面给出一个例子,我写出了比较详细的注释。希望足够清晰。这个例子说明了,回调函数可以把调用者和被调用者分开,对于调用者来说,只需要知道自己要调用一个函数,该函数有一个string类型的参数,至于具体调用哪个,被调用的函数到底怎么执行,怎么解释该参数,是完全不用关心的。  回调函数的一个很实用的例子就是泛型算法中的max算法,具体可以参见本文末尾的第一篇参考文档, 如果你在自行写代码中发生了 error C2679: 二进制“«”: 没有找到接受“std::string”类型的右操作数的运算符(或没有可接受的转换)错误 说明你没有把string头文件导入,导入即可 个人能力有限,错误之处请留言指正,不胜感激。 参考: http://learn.akae.cn/media/ch24s05.html http://baike.baidu.com/view/414773.htm

GSM,GPRS,WCDMA,HSDPA,3G 等名词解释

今天想起这个事,发现自己其实一直对这个也分不清楚。查了下资料。总算是搞清楚了。整理了一下资料。删除了没太大意义的文字。结构也重新设计了下,总体看起来比较明了了。首先解释最热门的3G概念**_3G_**是英文The Third Generation mobile communication Systems的缩写,指第三代移动通信技术。相对第一代模拟制式手机(1G)和第二代GSM、CDMA等数字手机 (2G),第三代手机(3G)一般地讲,是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。实际上,2G时代并没有2G这个名称,2G名称的出现是在行动通讯系统出现3G之后,才将过去使用GSM网路的行动通讯时代取名为2G,然而,2G演变到3G之间的过渡时期则被称为2.5G时代。同理,1G也是这么来的。就跟咱们做题是一样的。看到答案以后来推前面的过程。在2G时代,GSM、CDMA领导市场,他们是2G通信时代的两个实现。GSM(Global System for Mobile communications)系统,中文名称为「全球数位手机系统」,它是1990年在欧洲发展出来,所以又称泛欧式行动电话系统。GSM系统是2G时代在全球最被广泛应用的行动通讯技术,至今全球GSM用户数远远超过CDMA系统用户数。CDMA(Code Division Multiple Access)中文全名又称分码多工撷取,是相对于GSM的另一种无线通讯技术,CDMA系统只在美、韩、中、澳洲等国被使用,而全球多达200多个国家地区采用GSM系统_**两者的差异:**_虽然GSM与CDMA二者都是先将语音讯号数位化,受话者接收时再将数位讯号转变回语音,但由于CDMA系统使用的800MHz频谱,讯号在空中的遗失率较GSM采用的900或1800MHz频谱来得少,所以相较于GSM系统有通话不稳定的问题,CDMA可以提供更清晰的声音品质。在网路容量方面,CDMA的容量是GSM的3倍;CDMA的网路覆盖范围最远可达200公里,而GSM的网路覆盖范围则不会超过35公里。此外,CDMA的传输速率最高可达64Kbps,远高于GSM的9.6Kbps。至于内容应用方面,GSM与CDMA都可以提供包括语音、简讯、数据、来电显示、三方通话等服务。但是由于全球采用CDMA系统的国家较少,所以CDMA系统可以漫游的国家地区也就较GSM来得少。CDMA系统只在美、韩、中、澳洲等国被使用,而全球多达200多个国家地区采用GSM系统。_**GSM向3G的发展路线**__◆GSM→GPRS→EDGE→WCDMA→HSDPA_泛欧式的WCDMA系统演变过程相当复杂。行动通讯技术从GSM迈入GPRS时,可说是2G时迈向3G时代过程的第一步,这个时期被定位为2.5G时代,在2.5G时代,手机用户虽然已经可以享受较高速的无线上网,不过,内容应用仍然只限于收发e-mail、片段视讯下载等服务。(所谓GPRS(General Packet Radio Ser-vice),全名为整合封包无线电服务,它可说是新一代的GSM技术标准,相对于GSM是采取拨接方式传送资料,GPRS则是以封包无线方式传输资料,它可以在全球的GSM系统中运行。GPRS较GSM能更有效地利用无线网路,可以特别使用于突发性、频繁的小流量资料传输,传输速率高达115Kbps。从GSM到GPRS,速度提升10倍)为了提供更多、更高品质的服务给用户,行动通讯业者与设备提供商接着又开发出EDGE技术,EDGE是英文Enhanced Data Rate for GSM Evolution 的缩写,即增强型数据速率GSM演进技术。EDGE系统大大增强了GSM、GPRS等无线技术的频宽,虽然3G时代已经来到,但是,目前EDGE系统仍在全球被广泛的应用。使用EDGE技术,传输速率最高可达384Kbps,此外EDGE并将现有的GSM/GPRS等网路整合,在取得3G服务之前,EDGE可说提供了价格低廉、传输速度又快的服务,所以它也被认定为WCDMA系统的补充技术。WCDMA(英文Wideband Code Division Multiple Access)一种宽频无线技术,又称宽频分码多工多重撷取,它可以让第三代移动通讯最佳化,传输速率最高可达2Mbps.至于HSDPA(High Speed ​​Downlink Packet Access)中文名称为高速下行链路封包接取技术,它是WCDMA系统的进阶技术。HSDPA被认为是迈向3G蜂巢式网路的重要起步,其下载速度可以达到14Mbps,而系统资料容量是WCDMA网路的3倍,这项技术被宣称为将在未来对行动电话记忆体市场格局带来重大变革。_**CDMA向3G的发展路线**__◆CDMA→CDMA2000→CDMA2000 1x→CDMA2000 1x EV-DO_至于泛美式的CDMA2000(Code Division Multiple Access 2000 是一个3G移动通讯标准,CDMA2000与另一个3G标准WCDMA不兼容。),则是CDMA的升级技术。而CDMA2000的第一阶段技术称为CDMA 2000 1X,传输数率达144Kbps,较CDMA高出两倍;至于第二阶段的CDMA2000 1x EV-DO,最高传输数率可达1.4Mbps。还在向后发展已经到了CDMA2000 3.x,不过是在不断优化了。了解即可参考:https://lex0912.wordpress.com/2010/05/21/gsmgprswcdmahsdpahttps://zh.wikipedia.org/wiki/CDMA2000https://zh.wikipedia.org/wiki/3G

windows下vim闪烁问题

今天打开我的vim才发现,界面隔几秒会闪烁。虽说貌似能够起到防止眼睛疲劳的效果,但我实在是hold不住啊。不行,搜索。。 首先有这个问题的人不多。首先找到了这篇文章,但是作者不知道怎么想的。只说了原因,没有给出解决方法。继续搜索关键字cursorcolumn,结果找到了这篇文章,按着说明来了一下 没效果。依然闪烁。 好吧。如果是插件的问题。于是我删掉了所有的插件包括写入的配置。依然不行。于是还是采用排除法,一行行删掉配置文件。最后定位到  这是设置字体的,不太明白为什么会出现这样的情况。怀疑是字体的原因,于是换个字体,依然闪烁。。好吧。就这样吧。删掉算了。

四种I/O控制方式

基本上原文照搬过来吧。主要是原文排版太乱。不利于传播。 随着计算机技术的发展,I/O控制方式也在不断地发展。I/O控制的发展经历了以下四个阶段:  一.程序I/O控制方式  在早期的计算机系统中,由于无中断机构,处理机对I/O设备的控制,采取程序I/O方式(Programmed I/O方式)。在程序I/O方式中,由于CPU的高速性和I/O设备的低速性,致使CPU 的绝大部分时间都处于等待I/O设备完成数据I/O的循环测试中,造成对CPU的极大浪费。在该方式中,CPU之所以要不断地测试I/O设备的状态,就是因为在CPU中无中断机构,使 I/O设备无法向CPU报告它已完成了一个字符的输入操作。如下图所示:  图1.![]}/images/c83bce26670bc565b0fb2eaa4984e5b7575b618a.jpg)  程序I/O方式又称忙–等待方式,即在处理机向设备控制器发出一条I/O指令启动输入设备、输出数据时,要同时把状态寄存器中的忙/闲标志busy置为1,然后便不断地循环测试busy。当busy=1时,表示输入机尚未输完一个字(符),处理机应继续对busy进行测试;直至busy=0,表明输入机已将输入数据送入控制器的数据寄存器中,于是处理机将数据寄存器中的数据取出,送入内存指定单元中,接着,再启动去读下一个数据,并置busy=1。 △ 此方式造成对CPU的极大浪费。  二.中断驱动I/O控制方式  在现代计算机系统中,对I/O设备的控制,广泛采用中断驱动(Interrupt—Driven)方式。在I/O设备输入每个数据的过程中,由于无须CPU干预,因而可使CPU与I/O设备并行工作。仅当输完一个数据时,才需CPU花费极短的时间去做些中断处理。可见,这样可使CPU和I/O设备都处于忙碌状态,从而提高了整个系统的资源利用率及吞吐量。如下图所示:  图2  当某进程要启动某个I/O设备工作时,便由CPU向相应的设备控制器发出一条I/O命令,然后立即返回继续执行原来的任务。设备控制器便按照该命令的要求去控制I/O设备。此时,CPU与I/O设备并行操作。 例如,从终端输入一个字符的时间约为 100ms , 而将字符送入终端缓冲区的时间小于 0.1ms 。 若采用程序 I/O 方式, CPU 约有 99.9ms 的 时间处于忙 — 等待中。 采用中断驱动方式后, CPU 可利用这 99.9 ms 的时间去做其它事情,而仅用 0.1 ms 的时间来处理由控制器发来的中 断请求 。 可见,中断驱动方式可以成百倍地提高 CPU 的利用率。△ 中断驱动方式可以成百倍地提高CPU的利用率。  三.直接存储器访问DMA控制方式  –>DMA控制方式的引入  虽然中断驱动I/O比程序I/O方式更有效,但它是以字(节)为单位进行I/O的,若将这种方式用于块设备的I/O,显然将会是极其低效的。为了进一步减少CPU对I/O的干预,而引入了直接存储器访问(Direct Memory Access)方式。如下图:  图3![]}/images/ee3e0c3ca8d998d2a84488f01d3ca4d6e642f217.jpg)  此方式的特点是: 数据传输的基本单位是数据块;所传输的数据是从设备直接送入内存的,或者相反;整块数据的传送是在控制器的控制下完成的;  可见,DMA方式较之中断驱动方式,又是成百倍地减少了CPU对I/O的干预,进一步提高了CPU与I/O设备的并行操作程度。  –>DMA控制器的组成  DMA控制器由三部分组成,如下图:  图4![]}/images/bbb47eca5cb44fe7cf36bea37349cf6b728e99b5.jpg)  主机与DMA控制器的接口;DMA控制器与块设备的接口;I/O控制逻辑;  为了实现控制器与主机之间成块数据的直接交换,必须在DMA控制器中设四类寄存器,如上图  命令/状态寄存器;内存地址寄存器MAR;数据寄存器DR;数据计数器DC;  –>DMA工作过程  DMA的工作过程如下图:  图5 四.I/O通道控制方式  –>I/O通道控制方式的引入  I/O通道方式是DMA方式的发展,它可进一步减少CPU的干预,即把对一个数据块的读(或写)为单位的干预,减少为对一组数据块的读(或写)及有关的控制和管理为单位的干预。同时,又可实现CPU、通道和I/O设备三者的并行工作,从而更有效的提高了整个系统的资源利用率。  –>通道程序  通道是通过执行通道程序,并与设备控制器来共同实现对I/O设备的控制的。通道程序是由一系列的通道指令(或称通道命令)所构成。通道指令与一般的机器指令不同,在它的每条指令中包含下列诸信息:  操作码—-它规定了指令所执行的操作;内存地址;计数—-表明本条指令所要读(或写)数据的字节数;通道程序结束位P;记录结束标志位R  有几种I/O控制方式?各有何特点?  答:I/O控制方式有四种:程序直接控制方式、中断控制方式、DMA方式和通道控制方式。  (1) 程序直接控制方式:优点是控制简单,不需要多少硬件支持。但CPU和外设只能串行工作,且CPU的大部分时间处于循环测试状态,使CPU的利用率大大降低,因此该方式只适用于那些CPU执行速度较慢且外设较少的系统。  (2) 中断处理方式:优点是能实现CPU与外设间的并行操作,CPU的利用率较程序直接控制方式大大提高。由于在一次数据传送过程中CPU通常以字节为单位进行干预,中断次数较多而耗去大量的CPU时间。  (3) DMA方式:与中断方式相比,DMA方式是在一批数据传送完成后中断CPU,从而大大减少CPU进行中断处理的次数,且DMA方式下的数据传送实在DMA控制下完成的。但DMA方式仍有一定的局限,如对外设的管理和某些操作仍由CPU控制,多个DMA控制器的使用也不经济。  (4) 通道控制方式:CPU只需发出I/O指令,通道完成相应的I/O操作,并在操作结束时向CPU发出中断信号;同时一个通道还能控制多台外设。但是通道价格较高,从经济角度出发不宜过多使用。 参考: http://oa.gdut.edu.cn/os/multimedia/oscai/chapter5/pages/ch52.htm

.Net三层架构

本文来源:http://www.cnblogs.com/gaoweipeng/archive/2009/01/18/1377855.html 老规矩。因为是非常不错的文章。所有有必要收藏下来备用。推荐。 **三层体系结构的概念 ** 用户界面表示层(USL) 业务逻辑层(BLL) 数据访问层(DAL) BLL将USL与DAL隔开了,并且加入了业务规则 各层的作用 2:业务逻辑层:主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。 3:表示层:主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx, 如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。 具体的区分方法 1:数据数据访问层:主要看你的数据层里面有没有包含逻辑处理,实际上他的各个函数主要完成各个对数据文件的操作。而不必管其他操作。 2:业务逻辑层:主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。 3:表示层:主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。 三层结构解释 所谓三层体系结构,是在客户端与数据库之间加入了一个中间层,也叫组件层。这里所说的三层体系,不是指物理上的三层,不是简单地放置三台机器就是三层体系结构,也不仅仅有B/S应用才是三层体系结构,三层是指逻辑上的三层,即使这三个层放置到一台机器上。 三层体系的应用程序将业务规则、数据访问、合法性校验等工作放到了中间层进行处理。通常情况下,客户端不直接与数据库进行交互,而是通过COM/DCOM通讯与中间层建立连接,再经由中间层与数据库进行交换. 开发人员可以将应用的商业逻辑放在中间层应用服务器上,把应用的业务逻辑与用户界面分开。在保证客户端功能的前提下,为用户提供一个简洁的界面。这意味着如果需要修改应用程序代码,只需要对中间层应用服务器进行修改,而不用修改成千上万的客户端应用程序。从而使开发人员可以专注于应用系统核心业务逻辑的分析、设计和开发,简化了应用系统的开发、更新和升级工作。 那么为什么要应用“中间业务层”呢?举些例子: 我们假设有一段登录代码,则可以这样处理Web程序,外观层负责接收前台页面的数据,然后传给中间层,中间层对数据进行处理,比如格式化,防SQL注入等等一些,这样的数据再传给数据访问层然后与数据库进行操作,比如与数据库的用户名和密码匹配等等一些代码。** ** 在“数据访问层”中,最好不要出现任何“业务逻辑”!也就是说,要保证“数据访问层”的中的函数功能的原子性!即最小性和不可再分。“数据访问层”只管负责存储或读取数据就可以了。 ASP.NET中的三层结构说明 完善的三层结构的要求是:**修改表现层而不用修改逻辑层,修改逻辑层而不用修改数据层。**否则你的应用是不是多层结构,或者说是层结构的划分和组织上是不是有问题就很难说.不同的应用有不同的理解,这只是一个概念的问题. 我们用三层结构主要是使项目结构更清楚,分工更明确,有利于后期的维护和升级。它未必会提升性能,因为当子程序模块未执行结束时,主程序模块只能处于等待状态。这说明将应用程序划分层次,会带来其执行速度上的一些损失。但从团队开发效率角度上来讲却可以感受到大不相同的效果。 需要说明一下,三层结构不是.NET的专利,也不是专门用在数据库上的技术。它是一种更加普适的架构设计理念。 对于表的综合查询方法是: 先对主表查询,调用主表所对应的DL。再根据主表的记录分别对每一个子表进行查询。将自表的查询结果添加的主表后,形成一个大的查询集合。 对于表的操作(增删改): 此时只对主表进行操作,调用主表对应的DL中的操作方法。 RL层是逻辑判断层,主要是对页面上传入的数据进行逻辑判断。RL层之上就是UI 如何建立一个三层体系结构解决方案 新建一个空白解决方案。然后: “添加”-“新建项目”-“其他项目”-“企业级模版项目”-“C#生成块”-“数据访问”(数据层,下简称D层) “添加”-“新建项目”-“其他项目”-“企业级模版项目”-“C#生成块”-“业务规则”(业务层,下简称C层) “添加”-“新建项目”-“其他项目”-“企业级模版项目”-“C#生成块”-“Web用户界面”(界面层,下简称U层) 右键点“解决方案”-“项目依赖项”,设置U依赖于D、C,C依赖于D。 对U添加引用D、C,对C添加引用D。 到此为止,一个三层的架子建立起来了。我上面说的很具体很“傻瓜”,知道的人觉得我废话,其实我这段时间很强烈的感觉到非常多的人其实对这个简单的过程完全不了解。虽然不反对建2个“空项目”和1个“Asp net Web应用程序项目”也可以作为3层的框架,而且相当多的人认为其实这些“企业级模板项目”其实就是个空项目,这是一个误区。没错,企业级模板项目你从解决方案资源管理器里看它是个什么也没有的,但是你可以用记事本打开项目文件,看见不同了吧??有些东西在背后,你是看不见的,不过系统已经做好了。也就是说,如果你在C层里的某个类里“using System Data SqlClineit”,或者使用一个SqlConnection对象,编译时候不会出错,但是会在“任务列表”里生成一些“策略警告”,警告你在C层里不要放应该放在D层的东西(虽然就程序来说没错,但是可读性可维护性就打了折扣)而这种功能,空项目是无法給你的。 在新TraceLWord3中,应用了“企业级模板项目”。把原来的LWordTask.cs,并放置到一个单一的项目里,项目名称为:AccessTask。解决方案中又新建了一个名称为:InterService的项目,该项目中包含一个LWordService.cs程序文件,它便是“中间业务层”程序。为了不重复命名,TraceLWord3的网站被放置到了WebUI项目中。更完整的代码,可以在CodePackage/TraceLWord3目录中找到—— **面象对象与实际的结合 ** “三层结构”的缺点 有些网友在读完这篇文章前作之后,对我提出了一些质疑,这提醒我文章至此还没有提及“三层结构”的缺点。“三层结构”这个词眼似乎一直都很热门,究其原因,或许是这种开发模式应用的比较普遍。但是“三层结构”却并不是百试百灵的“万灵药”,它也存在着缺点。下面就来说说它的缺点…… “三层结构”开发模式的一个非常明显的缺点就是其执行速度不够快。当然这个“执行速度”是相对于非分层的应用程序来说的。从文中所给出的时序图来看,也明显的暴露了这一缺点。TraceLWord1和TraceLWord2没有分层,直接调用的ADO.NET所提供的类来获取数据。但是,TraceLWord6确要经过多次调用才能获取到数据。在子程序模块程序没有返回时,主程序模块只能处于等待状态。所以在执行速度上,留言板的版本越高,排名却越靠后。“三层结构”开发模式,不适用于对执行速度要求过于苛刻的系统,例如:在线订票,在线炒股等等……它比较擅长于商业规则容易变化的系统。“三层结构”开发模式,入门难度够高,难于理解和学习。这是对于初学程序设计的人来说的。以这种模式开发出来的软件,代码量通常要稍稍多一些。这往往会令初学者淹没在茫茫的代码之中。望之生畏,对其产生反感,也是可以理解的…… 其实,无论哪一种开发模式或方法,都是有利有弊的。不会存在一种“万用法”可以解决任何问题。所以“三层结构”这个词眼也不会是个例外!是否采用这个模式进行系统开发,要作出比较、权衡之后才可以。切忌滥用! 参与资料 MainDoc.rar (《浅谈“三层结构”原理与用意》1.30M) http://www.bincess.cn/Downloads/MainDoc.rar  petshop 4.0的体系结构(只是稍微看了一下,了解一下结构) 参考了Duwamish Web Search

你会用计算器吗?

今天早上在用windows自带的计算器转换进制的时候,看到了下图所示的按钮。MS MR之类的。  这些个按钮在简单的计算器上也有。我从小时候到现在都没搞清楚。当然也没搞过。。不学总是不会的。于是,找找资料。学会了也分享一下,英文是我猜的。。不过估计差不多  首先明确的一点是这类计算器内部有一个小的记忆芯片,可以用来存储一个数,类似于内存吧。所以M的意思就是Memory,下面先给出这几个的总体说明  “MS”,英文 Memory Store,用来存储输入栏显示的数字。  “MR”,英文 Memory Read, 再次显示调用存储的数字。  “M+”,英文 Memory Plus, 存储器里的值加上输入栏的值,结果又存入存储器  “M+”,英文 Memory Minus, 存储器里的值减去输入栏的值,结果又存入存储器  “MC”,英文 Memory Clear,用于清除存储器中的数值,默认为0  “C”, 英文 Cancel,就是全部撤销;  “CE”, 英文 Cancel Error,也就是撤销错误输入。  现在来说个例子,比如我要计算1002+113因为一些计算器不支持整个式子输入。也是为了演示这些功能。我们可以这样输入,  先输入100,然后 * ,然后 2 ,按下等号,这时候输入栏变成了200,我们按下MS 或者M+,按下MS的话把200存到了存储器,而按下M+呢,因为存储器默认是0,所以就相当于0+200,存储器里就是200了。然后我们继续输入11 ,输入 +,输入3 ,按下等号,输入栏变成了33.我们按下M+,这时候输入栏并没有改变。因为M+将存储器里的200加上了33.则存储器里变成了233.我们按下MR就是读取存储器的值,这样输入栏就可以看到233了。我们就可以继续用233来运算了。MC就是清除233.恢复为0.  例如:想要9*6,如果按6按错按成5了, 按C就是从头来过, 这时就要重新按9了, 但是如果你按CE的话, 就只要输入6就行了, 不必输入前面的了。  我个人感觉M存储器就相当于一个草稿。吧计算中的一些临时值存储起来,就不用手记了。我记得我那时候有时候算值还得先把一些临时值写在纸上,后面重新输入。没文化真可怕。

图片压缩工具源码(C#)

以前在用一个破解版的图片压缩工具。今天早上想想自己也试着做一个吧。查了一些资料。参考了一些代码。总算是写出来了。其实关键代码很简单。主要还是画界面,处理边界。。 看下效果图 处理图像的关键代码是这样的: 另外一个就是空间的tip功能,vs2010中貌似已经不支持直接使用属性来设置tip了。所以用到了ToolTip类,使用方法如下,你也可以先导入库,然后简写,ToolTip对象可以给窗体的控件设置提示。主要是第二句话,第一个参数是控件名,第二个参数是提示文本,最好将这两句放入窗体的Load方法中 还有一些边界,比如只接受数字数字之类的,我在代码里给出了详细的说明。实用工具的效果自行测试。对大图片效果最好。 源码下载:图片压缩工具源码

说说邮件中的抄送和密送

一直是分不太清楚,或者说是不知道具体的应用场合,于是,今天早上查了一下资料。总算是搞清楚了  不论你是用什么邮箱服务提供商,可能是126.或是Gmail,或是Qmail。在发送邮件的时候会看到如下类似的选项  抄送的英文缩写为CC,来源于Carbon Copy,如果一份邮件需要发送给多个人阅读,只要在“抄送”或“CC”一栏填上相关人员的信箱地址即可。如果是抄送多人,同样的直接添加到抄送栏就可以了。  密送的英文缩写为BCC,来源于Blind Carbon Copy,由于某种原因或出于某种考虑,你不希望收信人知道你把这封邮件还发送给了另外的人,则可将这位幕后的人的信箱地址放在密送一栏。  具体的规则是怎么呢。如果我密送给了多个人,那么多个人会互相看到彼此吗?下面我将使用一个例子来说明  如果:A 发送邮件(To)给B1、B2,抄送(CC)给C1、C2,密送(BCC)给D1、D2。  那么:  A知道自己发送邮件给了B1、B2,并且抄送给了C1、C2,密送给了D1、D2。这相当于废话。。自己肯定知道自己给谁发了。 B1知道这封是A发送给B1、B2的邮件,并且抄送给了C1、C2、但不知道密送给了D1、D2。To的人能看到抄送,看不到密送 C1知道这封是A发送给B1、B2的邮件,并且抄送给了C1、C2,但不知道密送给了D1、D2。抄送的人看不到密送。 D1知道这封是A发送给B1、B2的邮件,并且抄送给了C1、C2,而且密送给了自己,但不知道密送给了D2。 密送的人权限比较大,可以看到最多的情况,但依然看不到密送  具体的用法呢,一句话就是:一般抄送和密送是为了备份,知会,或者监督跟踪的作用。  我先举个例子。有些个朋友过节什么的喜欢群发邮件。或是一些什么网页之类的。有这个心是好的。可是。对于收到的人来说,一看到是群发的。直接可能都删掉了。所以此时可以使用密送功能。对应于上面说的最后一种情况。具体使用时在To里写上自己的地址,这样邮件会发给自己。密送栏里写上其他人的邮件,这样就同时密送给其他人,并且每个人都会只看到发给自己。起码有看下去的心情。  邮件在工作中用的非常多,美国人总结的中国人典型特征中有一条,“即使面对面坐着,也不直接交谈而要使用邮件。”而这在很多外企之中是非常流行的文化,和总部打交道,邮件往往是最快捷和便宜的方式,”  说到抄送,简直是所有邮件灾难故事最有力的协助者。同事之间常有抄送行为,有时是为了工作方便,同事A同时将一封邮件抄送给B和C,只能说明他们之间需要互相协作完成一件事情,但如果A将邮件发送给了B,却抄送给了B的老板C,那意味就深远了,通常有可能的情况是,A和B在合作的过程中发生了一些不愉快,告知老板的目的只是为了给对方一些震慑,这一招在各大公司当中都屡试不爽,而且往往成为一件悬而不决的事情得到解决的最快速手段。  抄送更多时候只是手段,而不是最终目的。看到一个某人A与其他部门同事B合作时发生的插曲,在某次急需同事B提供某文件支持时,B不慌不忙地一直以各种借口拖延工作,A忍无可忍,发了一封紧急邮件,同时抄送了B部门的领导和自己的领导,在这样一封邮件下,B在十分钟之内就将所需文件以附件形式传了过来,并回复了原邮件中的所有人。  如果你看了觉得真麻烦。其实。最有效的交流就是面对面,但是在职场中这是最有效地证明你自己干过什么的工具,一旦出了什么问题,最容易发现在哪个环节出现了问题,该由谁承担什么样的责任。如果遇到打官司这样的严重情况,邮件甚至能够作为呈堂证供。  没事给朋友写写邮件,那天看到一句话:维系友情的方法之一,是冷冰冰地写邮件。频率少得可怜,常常春暖花开发的邮件,秋叶飘零时收到回复。 参考: http://www.eeo.com.cn/2012/0328/223658.shtml http://baike.soso.com/v3997479.htm http://dudo.org/archives/2007123120184.html

中文编码杂谈

本文来自http://www.searchtb.com/2012/04/chinese_encode.html,讲的不错。收藏分享。 编码问题的例子 在Windows自带的Notepad(记事本)程序中输入“联通”两个字,保存后再次打开,会发现“联通”不见了,代之以“��ͨ”的乱码。这是Windows平台上典型的中文编码问题。即文件保存的时候是按照ANSI编码(其实就是GB2312,后面会详细介绍)保存,打开的时候程序按照UTF-8方式对内容解释,于是就出现了乱码。避免乱码的方式很简单,在“文件”菜单中选择“打开”命令,选择保存的文件,然后选择“ANSI”编码,此时就能看到久违的“联通”两个字了。 在Linux平台上如果使用cat等命令查看文件中的中文内容时,可能出现乱码。这也是编码的问题。简单的说是文件时按照A编码保存,但是cat命令按照当前Locale设定的B编码去查看,在B和A不兼容的时候就出现了乱码。 为什么写这篇文章 中文编码由于历史原因牵扯到不少标准,在不了解的时候感觉一头雾水;但其实理解编码问题并不需要你深入了解各个编码标准,只要你明白了来龙去脉,了解了关键的知识点,就能分析和解决日常开发工作中碰到的大部分编码问题。有感于我看过的资料和文章要么不够全面,要么略显枯燥,所以通过这篇文章记录下笔者在日常工作中碰到的中文编码原理相关问题,目的主要是自我总结,如果能给读者提供一些帮助那就算是意外之喜了。由于严谨的编码标准对我来说是无趣的,枯燥的,难以记忆的,本文尝试用浅显易懂的生活语言解释中文编码相关的(也可能不相关的)一些问题,这也是为什么取名杂谈的原因。本文肯定存在不规范不全面的地方,我会在参考资料里给出官方文档的链接,也欢迎读者在评论中提出更好的表达方式&指出错误,不胜感激。 对编码问题的理解我认为分为三个层次,第一个层次:概念,知道各个编码标准的应用场景,了解之间的差异,能分析和解决常见的一些编码问题。第二个层次:标准,掌握编码的细节,如编码范围,编码转换规则,知道这些就能自行开发编码转换工具。第三个层次,使用,了解中文的编码二进制存储,在程序开发过程中选择合理的编码并处理中文。为了避免让读者陷入编码标准的黑洞无法脱身(不相信?看看unicode的规范就明白我的意思了),同时由于编码查询&转换工具等都有现成工具可以使用,本文只涉及第一个层次,不涉及第二层次,在第三层次上会做一些尝试。在本文的最后提供了相关链接供对标准细节感兴趣的同学继续学习。最后,本文不涉及具体软件的乱码问题解决,如ssh,shell,vim,screen等,这些话题留给剑豪同学专文阐述。 一切都是因为电脑不识字 电脑很聪明,可以帮我们做很多事情,最开始主要是科学计算,这也是为什么电脑别名计算机。电脑又很笨,在她的脑子里只有数字,即所有的数据在存储和运算时都要使用二进制数表示。这在最初电脑主要用来处理大量复杂的科学计算时不是什么大问题,但是当电脑逐步走入普通人的生活时,情况开始变糟了。办公自动化等领域最主要的需求就是文字处理,电脑如何来表示文字呢?这个问题当然难不倒聪明的计算机科学家们,用数字来代表字符呗。这就是“编码”。 英文的终极解决方案:ASCII 每个人都可以约定自己的一套编码,只要使用方之间了解就ok了。比如说咱俩约定0×10表示a,0×11表示b。在一开始也的确是这样的,出现了各式各样的编码。这样有两个问题:1. 各个编码的字符集不一样,有的多,有的少。2. 相同字符的编码也不一样。你这里a是0×10,他那里a可能是0×30。于是你保存的文件他就不能直接用,必须要转换编码。随着沟通范围的扩大,采用不同编码的人们互相通信就乱套了,这就是我们常说的:鸡同鸭讲。如果要避免这种混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII(American Standard Code for Information Interchange)编码,统一规定了英文常用符号用哪些二进制数来表示。ASCII是标准的单字节字符编码方案,用于基于文本的数据。 ASCII最初是美国国家标准,供不同计算机在相互通信时用作共同遵守的西文字符编码标准,已被国际标准化组织(International Organization for Standardization, ISO)定为国际标准,称为ISO 646标准。适用于所有拉丁文字字母。ASCII 码使用指定的7位或8位二进制数组合来表示128或256种可能的字符。标准ASCII 码也叫基础ASCII码,使用7位二进制数来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。而最高位为1的另128个字符(80H—FFH)被称为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其它符号。 其中:**0~31及127(共33个)****是控制字符或通信专用字符(其余为可显示字符),**32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字,65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。 现在所有使用英文的电脑终于可以用同一种编码来交流了。理解了ASCII编码,其他字母型的语言编码方案就触类旁通了。 一波三折的中文编码 第一次尝试:GB2312 ASCII这种字符编码规则显然用来处理英文没有什么问题,它的出现极大的促进了信息在西方尤其是美国的传播和交流。但是对于中文,常用汉字就有6000以上,ASCII 单字节编码显然是不够用。为了粉碎美帝国主义通过编码限制中国人民使用电脑的无耻阴谋,中国国家标准总局发布了GB2312码即中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,1981年5月1日实施,通行于大陆。GB2312字符集中除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。 EUC-CN可以理解为GB2312的别名,和GB2312完全相同。 GB2312是基于区位码设计的,在区位码的区号和位号上分别加上A0H就得到了GB2312编码。这里第一次提到了“区位码”,我就连带把下面这几个让人摸不到头脑的XX码一锅端了吧: 区位码,国标码,交换码,内码,外码 区位码:就是把中文常用的符号,数字,汉字等分门别类进行编码。区位码把编码表分为94个区,每个区对应94个位,每个位置就放一个字符(汉字,符号,数字都属于字符)。这样每个字符的区号和位号组合起来就成为该汉字的区位码。区位码一般用10进制数来表示,如4907就表示49区7位,对应的字符是“学”。区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。在网上搜索“区位码查询系统”可以很方便的找到汉字和对应区位码转换的工具。为了避免广告嫌疑和死链,这里就不举例了。 国标码: 区位码无法用于汉字通信,因为它可能与通信使用的控制码(00H~1FH)(即0~31,还记得ASCII码特殊字符的范围吗?)发生冲突。于是ISO2022规定每个汉字的区号和位号必须分别加上32(即二进制数00100000,16进制20H),得到对应的国标交换码,简称国标码,交换码,因此,“学”字的国标交换码计算为: 交换码:即国标交换码的简称,等同上面说的国标码。 内码:由于文本中通常混合使用汉字和西文字符,汉字信息如果不予以特别标识,就会与单字节的ASCII码混淆。此问题的解决方法之一是将一个汉字看成是两个扩展ASCII码,使表示GB2312汉字的两个字节的最高位都为1。即国标码加上128(即二进制数10000000,16进制80H)这种高位为1的双字节汉字编码即为GB2312汉字的机内码,简称为内码。20H+80H=A0H。这也就是常说的在区位码的区号和位号上分别加上A0H就得到了GB2312编码的由来。 外码:机外码的简称,就是汉字输入码,是为了通过键盘字符把汉字输入计算机而设计的一种编码。 英文输入时,相输入什么字符便按什么键,外码和内码一致。汉字输入时,可能要按几个键才能输入一个汉字。 汉字输入方案有成百上千个,但是这千差万别的外码输入进计算机后都会转换成统一的内码。 最后总结一下上面的概念。中国国家标准总局把中文常用字符编码为94个区,每个区对应94个位,每个字符的区号和位号组合起来就是该字符的区位码, 区位码用10进制数来表示,如4907就表示49区7位,对应的字符是“学”。 由于区位码的取值范围与通信使用的控制码(00H~1FH)(即0~31)发生冲突。每个汉字的区号和位号分别加上32(即16进制20H)得到国标码,交换码。“学”的国标码为5127H。由于文本中通常混合使用汉字和西文字符,为了让汉字信息不会与单字节的ASCII码混淆,将一个汉字看成是两个扩展ASCII码,即汉字的两个字节的最高位置为1,得到的编码为GB2312汉字的内码。“学”的内码为D1A7H。无论你使用什么输入法,通过什么样的按键组合把“学”输入计算机,“学”在使用GB2312(以及兼容GB2312)编码的计算机里的内码都是D1A7H。 第二次尝试:GBK GB2312的出现基本满足了汉字的计算机处理需要,但由于上面提到未收录繁体字和生僻字,从而不能处理人名、古汉语等方面出现的罕用字,这导致了1995年《汉字编码扩展规范》(GBK)的出现。GBK编码是GB2312编码的超集,向下完全兼容GB2312,兼容的含义是不仅字符兼容,而且相同字符的编码也相同,同时在字汇一级支持ISO/IEC10646—1和GB 13000—1的全部中、日、韩(CJK)汉字,共计20902字。GBK还收录了GB2312不包含的汉字部首符号、竖排标点符号等字符。CP936和GBK的有些许差别,绝大多数情况下可以把CP936当作GBK的别名。 第三次尝试:GB18030 GB18030编码向下兼容GBK和GB2312。GB18030收录了所有Unicode3.1中的字符,包括中国少数民族字符,GBK不支持的韩文字符等等,也可以说是世界大多民族的文字符号都被收录在内。GBK和GB2312都是双字节等宽编码,如果算上和ASCII兼容所支持的单字节,也可以理解为是单字节和双字节混合的变长编码。GB18030编码是变长编码,有单字节、双字节和四字节三种方式。 其实,这三个标准并不需要死记硬背,只需要了解是根据应用需求不断扩展编码范围即可。从GB2312到GBK再到GB18030收录的字符越来越多即可。万幸的是一直是向下兼容的,也就是说一个汉字在这三个编码标准里的编码是一模一样的。这些编码的共性是变长编码,单字节ASCII兼容,对其他字符GB2312和GBK都使用双字节等宽编码,只有GB18030还有四字节编码的方式。这些编码最大的问题是2个。1. 由于低字节的编码范围和ASCII有重合,所以不能根据一个字节的内容判断是中文的一部分还是一个独立的英文字符。2. 如果有两个汉字编码为A1A2B1B2,存在A2B1也是一个有效汉字编码的特殊情况。这样就不能直接使用标准的字符串匹配函数来判断一个字符串里是否包含某一个汉字,而需要先判断字符边界然后才能进行字符匹配判断。 最后,提一个小插曲,上面讲的都是大陆推行的汉字编码标准,使用繁体的中文社群中最常用的电脑汉字字符集标准叫大五码(Big5),共收录13,060个中文字,其中有二字为重覆编码(实在是不应该)。Big5虽普及于中国的台湾、香港与澳门等繁体中文通行区,但长期以来并非当地的国家标准,而只是业界标准。倚天中文系统、Windows等主要系统的字符集都是以Big5为基准,但厂商又各自增删,衍生成多种不同版本。2003年,Big5被收录到台湾官方标准的附录当中,取得了较正式的地位。这个最新版本被称为Big5-2003。 天下归一Unicode 看了上面的多个中文编码是不是有点头晕了呢?如果把这个问题放到全世界n多个国家n多语种呢?各国和各地区自己的文字编码规则互相冲突的情况全球信息交换带来了很大的麻烦。 要真正彻底解决这个问题,上面介绍的那些通过扩展ASCII修修补补的方式已经走不通了,而必须有一个全新的编码系统,这个系统要可以将中文、日文、法文、德文……等等所有的文字统一起来考虑,为每一个文字都分配一个单独的编码。于是,Unicode诞生了。Unicode(统一码、万国码、单一码)为地球上(以后会包括火星,金星,喵星等)每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。在Unicode里,所有的字符被一视同仁,汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”来表示,也就是说,所有的文字都按一个字符来处理,它们都有一个唯一的Unicode码。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位(码位就是可以分配给字符的数字)。 提到Unicode不能不提UCS(通用字符集Universal Character Set)。UCS是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。UCS-2用两个字节编码,UCS-4用4个字节编码。Unicode是由unicode.org制定的编码机制,ISO与unicode.org是两个不同的组织, 虽然最初制定了不同的标准; 但目标是一致的。所以自从Unicode 2.0开始, Unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值, 使得两者保持一致。大家简单认为UCS等同于Unicode就可以了。 在Unicode中:汉字“字”对应的数字是23383。在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是: 下面介绍UTF-8、UTF-16、UTF-32、BOM。 UTF-8 UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下: 例1:“汉”字的Unicode编码是0x6C49。0x6C49在0×0800-0xFFFF之间,使用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。 例2:Unicode编码0x20C30在0×010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。 UTF-16 UTF-16编码以16位无符号整数为单位。我们把Unicode编码记作U。编码规则如下:如果U<0×10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。中文范围 4E00-9FBF,所以在UTF-16编码里中文2个字节编码。如果U≥0×10000,我们先计算U’=U-0×10000,然后将U’写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。 UTF-32 UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无符号整数。 字节序 根据字节序(对字节序不太了解的同学请参考http://en.wikipedia.org/wiki/Endianness)的不同,UTF-16可以被实现为UTF-16LE(Little Endian)或UTF-16BE(Big Endian),UTF-32可以被实现为UTF-32LE或UTF-32BE。例如: 中文二进制存储 介绍了这么多的编码知识,真正的文件内容是什么样子的呢?下面我们就通过实验看看在笔者Linux机器上 “中文”这两个字在不同的编码下保存的文件内容。下面是我的实验过程,有兴趣的同学可以在自己的机器上重做一下。Window平台上的情况类似这里就不赘述了。 实验需要需要使用2个工具: od 查看文件内容:http://www.gnu.org/software/coreutils/manual/html_node/od-invocation.html iconv 编码转换工具:http://www.gnu.org/software/libiconv/ OS: Red Hat Enterprise Linux AS release 4 CPU: Intel(R) Xeon(R) CPU

C# 温故而知新:Stream篇

 如果你在学习C#,那么对流的操作是非常基础重要的一步,而JimmyZheng的Stream系列文章估计是流操作最好的文章了。直接转过来,做一个收藏。也希望能够对学习的朋友有所帮助,本文可能会持续更新。 C# 温故而知新:Stream篇(—)Stream简单介绍 C# 温故而知新:Stream篇(二)TextReader 和StreamReader C# 温故而知新:Stream篇(三)TextWriter 和 StreamWriter C# 温故而知新:Stream篇(四)FileStream C# 温故而知新:Stream篇(五)MemoryStream C# 温故而知新:Stream篇(六)BufferedStream C# 温故而知新:Stream篇(七)NetworkStream