分类目录
文章索引模板
20070809 utf8 ef bb bf - 一月 10, 2008 by yippee

20070809 utf8 ef bb bf
http://www.yippeesoft.com

今天人家解析我生成的一个文件死活判断不了EOF
StreamWriter sw = new StreamWriter(strfilelist, false, Encoding.UTF-8);

十六进制一看,多了 EF BB BF三个字节,估计是UTF8的事情
改为ASCII就OK了

资料:
调试一个小程序发现的.
用M$的记事本新建一个文件,输入些东西,然后另存为utf8格式的文件,你就会发现它会自动在文本前面添加EF BB BF这3个字节,这应该是用来标识文件格式的.
在Ultraedit里看到的似乎有些问题 是FF FE.
往标准的txt文件里随意添加标识,这种流氓行为很容易导致兼容性问题,更科学的方法应该是根据文件的内容来判断文件的格式.
呵呵,这个是您理解错了。
unicode 文档前面附加两三个字节的识别码(学名叫BOM)不是M$ Notepad的错。这是unicode的规定。见http://www.unicode.org/faq/utf_bom.html。我试验了一下,. NET、Java、gvim和最新版本的UltraEdit和都认识BOM,会以相应方式处理。但最新版本的Python却不完全认识,它的文件I/O和正则表达式有时会因BOM而出错。

   已知   赛迪网   三个汉字用文字编辑器转成   UTF8后是乱码。然后用16进制看为   EF   BB   BF   E8   B5   9B   E8   BF   AA   E7   BD   91  
   
  问如何用php直接把这三个汉字转成   这一串16进制。并把   "EF   BB…."字符串赋值到函数 
  
  最终生成如下的结构: 
                                        $str   =   chr(0xE8).chr(0xB5).chr(0×9B).chr(0xE8).chr(0xBF).chr(0xAA).chr(0xE7).chr(0xBD).chr(0×91)

<?php 
  $s   =   "赛迪网"; 
  $u   =   iconv("GB2312","UTF-8",$s); 
  $n   =   bin2hex($u);   //e8b59be8bfaae7bd91 
  preg_match_all("/../",$n,$regs); 
  print_r($regs[0]);   //测试 
  
  echo   $p   =   "chr(0x".join(").chr(0x",$regs[0]).")";   //chr(0xe8).chr(0xb5).chr(0×9b).chr(0xe8).chr(0xbf).chr(0xaa).chr(0xe7).chr(0xbd).chr(0×91) 
  
  eval("\\$str=$p;"); 
  
  echo   $str; 
  ?>  

晚上写了个小程序测试了一下,终于弄懂了UltraEdit弄出来的UTF8格式,和微软弄出来的UTF8格式之间的区别了

比如说一个文本文件内容是“1啊”两个字符:
对于 GBK编码:31 B0 A1
对于unicode UCS-2 编码(不论记事本还是Ultaedit): ff fe 31 00 4a 55 (在Ultraedit二进制下看到的是一样的)
对于UltraEdit的“UTF8(unicode editing)” 的编码: 31 e5 95 8a (在Ultraedit下看到的是 FF FE 31 00 4A 55)
对于微软“记事本”另存为出来的UTF8的编码:  ef bb bf 31 e5 95 8a  (在Ultraedit下看到的是 FF FE FF FE 31 00 4A 55)

可以看出来,微软的UTF8编码其实是符合标准的,因为 ef bb bf 这三个字节,正好就是 FF FE 的UTF8编码。也就是说,看来是我们冤枉微软了,一直以为是Ultraedit出来的utf8标准而微软“记事本”出来的utf8不标准,其实正好相反。
参见 ultraedit forum

看来我手头的 UE9.0 是个很老的版本了。

现在就剩下一个问题:为什么svn不支持标准utf8,无法识别BOM呢?

什么是UTF8
UTF8并不算是一种电脑编码,而是一种储存和传送的格式,如前所述,每个Unicode/UCS字符都以 2或4个bytes来储存,看看以下的比较:

  以"I am Chinese"为例
   用ANSI储存:12 Bytes
   用Unicode/UCS2储存:24 Bytes + 2 Bytes(header)
   用UCS4储存:48 Bytes + 4 Bytes(header)

  以"我是中国人"为例
   用ANSI储存:10 Bytes
   用Unicode/UCS2储存:10 Bytes + 2 Bytes(header)
   用UCS4储存:20 Bytes + 4 Bytes(header)

  由此可见直接以Unicode/UCS的原始形式来储存是一种极大的浪费,而且也不利于互联网的传输(中文稍为合算一点^_^)。

  有见及此,Unicode/UCS的压缩形式--UTF8出现了,套用官方网站的首句话『UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.』,由于UTF也适用于编码UCS,故亦可称为『UCS transformation formats (UTF)』

  UTF8是以8bits即1Bytes为编码的最基本单位,当然也可以有基于16bits和32bits的形式,分别称为UTF16和UTF32,但目前用得不多,而UTF8则被广泛应用在文件储存和网络传输中。

编码原理

先看这个模板:

UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx … 10xxxxxx

编码步骤:
1) 首先确定需要多少个8bits(octets)
2) 按照上述模板填充每个octets的高位bits
3) 把字符的bits填充至x中,字符顺序:低位→高位,UTF8顺序:最后一个octet的最末位x→第一个octet最高位x
4) 解码的原理一样。

实例:(留意每个bit的颜色,粗体字为模板内容)

UCS-4 UTF-8
HEX BIN Bytes BIN HEX Bytes
0000 000A 00001010 4 00001010 0A 1
0000 0099 10011001 4 11000010 10011001 C2 99 2
0000 8D99 10001101 10011001 4 11101000 10110110 10011001 E8 B6 99 3

  不知大家看懂了没有,其实不懂也无所谓,反正又不用自己算,程式可以完全代劳。

  以UTF8格式储存的文件档首标识为EF BB BF。

效率

  从上述编码原理中得出的结论是:
   1.每个英文字母、数字所占的空间为1 Byte;
   2.泛欧语系、斯拉夫语字母占2 Bytes;
   3.汉字占3 Bytes。

  由此可见UTF8对英文来说是个非常诱人的方案,但对中文来说则不太合算,无论用ANSI还是 Unicode/UCS2来编码都只用2 Bytes,但用UTF8则需要3 Bytes。

  以下是一些统计资料,显示用UTF8来储存文件每个字符所需的平均字节:
   1.拉丁语系平均用1.1 Bytes;
   2.希腊文、俄文、阿拉伯文和希伯莱文平均用1.7 Bytes;
   3.其他大部份文字如中文、日文、韩文、Hindi(北印度语)用约3 Bytes;
   4.用超过4 Bytes的都是些非常少用的文字符号。

今天什么事情都不顺利

早上看到居委会的通告:×××还没有办二代身份证

只好跑去派出所办理

结果要求父母身份证号码,晕倒,他们在火车上了

又找警察查询了号码

然后再进去交了表,照相,一看,原来刚才我插队了,好多人

想想算了,赶快去上班吧

结果打的到公司,还是迟到了

下午去接父母,网上查一下,时间差不多

结果我还没到火车站,家里电话就打来了,已经到了

原来火车提速了

郁闷

标签:
20070730 Logging Application Block ansi utf8 - 十二月 31, 2007 by yippee

20070730 Logging Application Block ansi utf8
http://www.yippeesoft.com

[TestMethod]
        public void DoLog()
        &leftsign;
            //创建一个日志条目
            LogEntry log = new LogEntry();
            //指定该日志所属类别
            log.Categories.Add("General");
            //日志标题
            log.Title = "SHY520\’s Tests";
            log.Message = "there is log information";
            //优先级
            log.Priority = 0;

            Logger.Write(log);
        &rightsign;

用 Enterprise Library Configuration 默认是写入 WINDOWS的系统日志里面

Enterprise Library 2.0 中的 Logging Application Block 在1.0版本中是Logging and Instrumentation Application Block,因为把重点放在了日志记录上,所以改名为Logging Application Block。Logging Application Block提供了统一的日志记录功能,它支持将日志写入到多种目的地中,比如:1、数据库;2、文本文件;3、Email;4、消息队列;5、WMI event;6、事件日志;7、自定义区域(For Example:XML File)等等。
   Logging Application Block 提供了统一的接口用于将日志写入到任何指定的目的地,我们不需要在代码中指定日志信息该写到什么地方,而是在配置文件中设定我们什么情况

下写日志以及将日志信息写到什么地方,这也就意味着操作员可以和我们开发人员一样不通过修改代码来改变日志记录行为。它对于我们程序开发有以下几点好处:
1、可以使我们的应用程序中的日志记录方法保持一致;
2、正是因为它提供一致的结构模型,很大程度上方便了我们开发人员对其的学习;
3、很好的解决了应用程序中的日志问题;
4、可扩展,我们可以自定义日志信息的过滤程序以及格式化日志信息的程序

<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </configSections>
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add source="Xml2Sql" formatter="Text Formatter" log="Application"
        machineName="" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
        traceOutputOptions="None" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
        name="Formatted EventLog TraceListener" />
    </listeners>
    <formatters>
      <add template="Timestamp: &leftsign;timestamp&rightsign;&#xD;&#xA;Message: &leftsign;message&rightsign;&#xD;&#xA;Category: &leftsign;category&rightsign;&#xD;&#xA;Priority: &leftsign;priority&rightsign;&#xD;&#xA;EventId: &leftsign;eventid&rightsign;&#xD;&#xA;Severity: &leftsign;severity&rightsign;&#xD;&#xA;Title:&leftsign;title&rightsign;&#xD;&#xA;Machine: &leftsign;machine&rightsign;&#xD;&#xA;Application Domain: &leftsign;appDomain&rightsign;&#xD;&#xA;Process Id: &leftsign;processId&rightsign;&#xD;&#xA;Process Name: &leftsign;processName&rightsign;&#xD;&#xA;Win32 Thread Id: &leftsign;win32ThreadId&rightsign;&#xD;&#xA;Thread Name: &leftsign;threadName&rightsign;&#xD;&#xA;Extended Properties: &leftsign;dictionary(&leftsign;key&rightsign; – &leftsign;value&rightsign;&#xD;&#xA;)&rightsign;"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>

   StreamReader   sr   =   new   StreamReader(openFileDialog1.FileName,   Encoding.GetEncoding("gb2312")); 
              StreamWriter   sw   =   new   StreamWriter("D:\\\\转化后.txt",   false,   Encoding.UTF8); 
              Console.Write(sr.BaseStream.Length); 
              char[]   buffer   =   new   char[512]; 
              int   len; 
              while(sr.Peek()   >=0) 
              &leftsign; 
                  len   =   sr.Read(buffer,0,512); 
                  sw.Write(buffer,0,len); 
              &rightsign; 
              sr.Close(); 
              sw.Close(); 
              MessageBox.Show("转化完毕!");

       static void Main()
      &leftsign;
         string utf8String = "骞垮憡涓戦椈";

         // Create two different encodings.
         Encoding utf8= Encoding.UTF8;
         Encoding defaultCode= Encoding.Default;

         // Convert the string into a byte[].
         byte[] utf8Bytes = default.GetBytes(utf8String );

         // Perform the conversion from one encoding to the other.
         byte[] defaultBytes = Encoding.Convert(utf8, defaultCode, utf8Bytes );
          
         // Convert the new byte[] into a char[] and then into a string.
         // This is a slightly different approach to converting to illustrate
         // the use of GetCharCount/GetChars.
         char[] defaultChars = new char[defaultCode.GetCharCount(defaultBytes , 0, defaultBytes .Length)];
         defaultCode.GetChars(defaultBytes , 0, defaultBytes .Length, defaultChars , 0);
         string defaultString = new string(defaultChars );

         // Display the strings created before and after the conversion.
         Console.WriteLine("Original string: &leftsign;0&rightsign;", utf8String);
         Console.WriteLine("Ascii converted string: &leftsign;0&rightsign;", defaultString);

//或者如下:
         byte[] buffer1 = Encoding.Default.GetBytes(utf8String );
         byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);
         string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);
      &rightsign;

标签:, , ,
MYSQL UTF8 UTF-8 GB2312 LATIN 乱码 - 十一月 23, 2005 by yippee

MYSQL UTF8 UTF-8 GB2312 LATIN 乱码

MYSQL数据库中需要创建一些初始值,结果直接在MYSQL里面INSERT失败,最后觉得反正是用MYSQL导入SQL脚本方式运行,所以不如直接把SQL脚本存为UTF-8格式,导入后再页面显示正常。 www.yippeesoft.com

mysql -V www.yippeesoft.com
mysql  Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686)

MySQL 4.1x之後的問題, www.yippeesoft.com
找了很久,才發現解決方法為
在mysql_connect的語法後加一句:
mysql_query("set NAMES \’utf8\’"); 或
mysql_query("set NAMES \’big5\’"); (Depends on 你的encoding)

CREATE TABLE `companys` ( www.yippeesoft.com
  `companyid` smallint(4) NOT NULL auto_increment,
  `companyname` varchar(40) character set utf8 collate utf8_unicode_ci NOT NULL default \’\',
  PRIMARY KEY  (`companyid`),
  UNIQUE KEY `companyname` (`companyname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=28 ;

UTF8页面正常 是
MYSQL不正常: www.yippeesoft.com
+———–+————-+
&line; companyid &line; companyname &line;
+———–+————-+
&line;        28 &line; 鏄?        &line;
+———–+————-+

insert into companys(companyname) values(\’行政部\’);
mysql 正常      29 &line; 行政部
页面 А???

insert into companys(companyname) values(convert(\’行是部\’ using utf8 ));
mysql   30 &line; 行是部 www.yippeesoft.com
А???

insert into companys(companyname) values(convert(\’行部\’ using gb2312));
 31 &line; ????      ????

 /*公司机构表*/
CREATE TABLE companys(
  companyid  SMALLINT(4)  NOT NULL auto_increment,
  companyname varchar(40) NOT NULL,
  PRIMARY KEY  (companyid),
  UNIQUE KEY companyname(companyname)
)TYPE=MyISAM; www.yippeesoft.com

select convert(* using utf8) from companys;

在mysql中使用utf8编码,进行like查询时。如namelike\’%c%\’会将一些中文也搜索出来,虽然中文在里面显示时为乱码。这样会造成查询不精确。后查询mysql文档发现binary关键字。在like后加入binary即可实现精确的模糊查询。likebinary\’%c%\’
注:目前发现在like时使用c,e,a时会出现以上问题。因为mysql是用c语言写的。可能是utf8后编码的问题才会出现上述情况。还好解决了。希望能给有过同样问题的朋友一些帮助 MOONTOUCHER\’S BLOG

标签:, , , , ,