一个用于读unicode文本的迭代器(iterator)

摘要:
对于ICU,QT太重了,所以我编写了一个打包的unicode_当然,迭代器也可以进一步打包。例如,一个班级被提议提供开始和结束。然而,有很多事情需要考虑。例如,有些文本是littledian格式,有些是bigdian格式。同时,有些文本可能没有一个标准的开头来表明它们是unicode格式的,用户需要指出是title还是bigdian。目前,为初始化提供了std::filebuf,每次*iter提取UTF16格式的字符时,都要定义typedefensignedshortUTF16。请注意,wchar不使用_T,因为在Windows下这是2个字节,但在Linux下GCC默认为4个字节,这是为UTF32准备的。

written by chenghuige at gmail.com

也需有更好的方法我没有想到,但是没有在linux下面找到比较方便的读取unicode文本的方法。

用ICU,QT都太重量级了,于是自己写了一个包装好的unicode_iterator,当然还可以进一步

包装比如提出一个类提供begin和end.但是还要考虑很多,比如有的是little edian格式的有的是big edian

格式的,同时有的文本可能并没有标准的开头表明它是unicode格式的,以及ittle edian 还是big edian,

需要用户自己指出。

当前初始化给定一个std::filebuf,然后每次*iter提取的是一个UTF16格式的字符,定义

typedef unsigned short UTF16

注意没有用wchar_t因为这个在windows下是2byte但是在linux下GCC默认是4byte,为UTF32准备的。

迭代器用boost iterator帮助简化书写,类似的我们也可以写出给定一个utf8或者GBK等等编码的流转换

到unicode(UTF16)的iterator,内部统一用unicode处理数据还是比较方便的,C++0X也出现了u16string.

用法示意:假设是一个标准的litle edian 的 unicode文本

一个用于读unicode文本的迭代器(iterator)第1张一个用于读unicode文本的迭代器(iterator)第2张代码
 1 
 2   using namespace std;
 3   using namespace glseg;
 4 
 5   ifstream istr(infilename.c_str());
 6   filebuf* pbuf = istr.rdbuf();
 7   
 8   unsigned char ch  = pbuf->sbumpc();
 9   unsigned char ch1 = pbuf->sbumpc();
10 
11   if (ch == encoding_type[Utf16LittleEndian][0&& ch1 == encoding_type[Utf16LittleEndian][1]) 
12     cout << "The encoding of this file is  utf16 little endian" << endl;
13   if (ch == encoding_type[Utf16BigEndian][0&& ch1 == encoding_type[Utf16BigEndian][1])
14     cout << "The encoding of this file is  utf16 big endian" << endl;
15 
16   unicode_iterator<> first(pbuf);
17   unicode_iterator<> end;
18   
19   UTF8 utf8_array[4];
20   for (;first != end; ++first) {
21     unicode2utf8(*first, utf8_array); //将utf16字符转换到utf8,这样用cout就可以显示了因为默认都是utf8
22     cout << utf8_array;
23   }
一个用于读unicode文本的迭代器(iterator)第3张一个用于读unicode文本的迭代器(iterator)第4张代码
 1 /*
 2  *  ==============================================================================
 3  * 
 4  *          \file   type.h
 5  *
 6  *        \author   chenghuige at gmail.com
 7  *          
 8  *          \date   2009-12-09 19:02:16.223408
 9  *  
10  *   Description:   differnt tyes declaraion
11  *  ==============================================================================
12  */
13 
14 #ifndef TYPE_H_
15 #define TYPE_H_
16 
17 namespace glseg {
18 
19 typedef unsigned long   UTF32;  /* at least 32 bits */
20 typedef unsigned short  UTF16;  /* at least 16 bits */
21 typedef unsigned char   UTF8;   /* typically 8 bits */
22 typedef unsigned char   Boolean; /* 0 or 1 */
23 
24 enum EncodingType {
25     Unknown,
26     Utf16LittleEndian,  // Default on Windows
27     Utf16BigEndian,
28     Utf8,
29     encoding_num
30 };
31 
32 const UTF8 encoding_type[encoding_num][3=
33 {
34     {0x000x000x00},  // Unknown
35     {0xFF0xFE0x00},  // Little endian
36   {0xFE0xFF0x00},  // Big endian
37     {0xEF0xBB0xBF}, // UTF8
38 };
39 
40 }  //----end of namespace glseg
41 
42 #endif  //----end of TYPE_H_
一个用于读unicode文本的迭代器(iterator)第5张一个用于读unicode文本的迭代器(iterator)第6张代码
  1 /*
  2  *  ==============================================================================
  3  * 
  4  *          \file   unicode_iterator.h
  5  *
  6  *        \author   chenghuige at gmail.com
  7  *          
  8  *          \date   2009-12-09 16:56:59.395999
  9  *  
 10  *   Description:   An unicode iterator for unicode encoding file
 11  *  ==============================================================================
 12  */
 13 
 14 #ifndef UNICODE_ITERATOR_H_
 15 #define UNICODE_ITERATOR_H_
 16 
 17 #include <boost/iterator/iterator_facade.hpp>
 18 #include <fstream>
 19 #include "type.h" 
 20 
 21 namespace glseg {
 22 
 23 //this is mainly for file because when we read the file
 24 //we can not read two bytes and decide the little or
 25 //big edian easy, this class will help
 26 //Perhaps name it as unicode or utf16 fstream buf itreator is better:)
 27 
 28 //the big endian case
 29 template <bool isLittleEndian>
 30 struct UTF8_2_UTF16 {
 31   static void convert(const UTF8 ch1, const UTF8 ch2, UTF16* result) {
 32     *result = ch1;   
 33     *result <<= 8;
 34     *result |= ch2;
 35   }
 36 };
 37 
 38 //the little endian case
 39 template <>
 40 struct UTF8_2_UTF16<true> {
 41   static void convert(const UTF8 ch1, const UTF8 ch2, UTF16* result) {
 42     *result = ch2;   
 43     *result <<= 8;
 44     *result |= ch1;
 45   }
 46 };
 47 
 48 
 49 template<bool isLittleEndian = true>
 50 class unicode_iterator
 51   : public boost::iterator_facade<
 52       unicode_iterator<isLittleEndian>
 53     , UTF16
 54     , boost::forward_traversal_tag
 55     , UTF16&
 56     >
 57 {
 58 public:
 59   unicode_iterator()
 60     : pbuf_(0), valid_(false) {}
 61 
 62   explicit unicode_iterator(std::filebuf* pbuf) 
 63     :pbuf_(pbuf), valid_(true) { increment(); } //need to be ready for first *iter
 64 
 65 private:
 66   friend class boost::iterator_core_access;
 67 
 68   void increment() { 
 69     if (pbuf_->sgetc()!=EOF) {
 70       ch1_ = pbuf_->sbumpc();
 71       ch2_ = pbuf_->sbumpc();
 72       UTF8_2_UTF16<isLittleEndian>::convert(ch1_, ch2_, &result_);
 73     } 
 74     else {
 75       valid_ = false;
 76     }
 77   }
 78 
 79   bool equal(unicode_iterator<isLittleEndian> const& other) const {
 80     return (other.valid_ && valid_)
 81            ?(other.pbuf_ == pbuf_)
 82           :(other.valid_ == valid_);
 83   }
 84 
 85   UTF16& dereference() const { 
 86     return result_;
 87   }
 88 
 89 private:
 90   std::filebuf* pbuf_;
 91   bool valid_;
 92 
 93   UTF8  ch1_;
 94   UTF8  ch2_;
 95   mutable UTF16 result_;
 96   //FIXME if not mutable
 97   //for 86 error: invalid initialization of reference oftype 'glseg::UTF16&' from expression of type 'const glseg::UTF16'
 98 };
 99 
100 }  //----end of namespace glseg
101 
102 #endif  //----end of UNICODE_ITERATOR_H_

免责声明:文章转载自《一个用于读unicode文本的迭代器(iterator)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇解决delphi使用sqlite时中文最后一个字是乱码的问题OFBiz进阶之环境搭建(eclipse)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

批量裁剪GIS数据(包含GDB,MDB,Shp)

#-*- coding: utf-8 -*-#made by 汪林_质检处 importos.path importarcpy importsys from arcpy importenv FCDBDir = "E:\cliptest\data"output = "E:\Result"clipshp = "E:\cliptest\clip.shp" G...

Unicode字符列表(超完整)

Unicode字符列表(超完整)Unicode, 字符, 列表代码 显示 描述U+0020  空格 U+0021 ! 叹号 U+0022 " 双引号 U+0023 # 井号 U+0024 $ 价钱/货币符号 U+0025 % 百分比符号 U+0026 & 英文“and”的简写符号 U+0027 ' 引号 U+0028 ( 开 圆括号 U+0029...

Unicode与UTF-8互转(C语言实现)

1. 基础1.1 ASCII码我们知道, 在计算机内部, 所有的信息最终都表示为一个二进制的字符串. 每一个二进制位(bit)有0和1两种状态, 因此八个二进制位就可以组合出 256种状态, 这被称为一个字节(byte). 也就是说, 一个字节一共可以用来表示256种不同的状态, 每一个状态对应一个符号, 就是256个符号, 从 0000000到11111...

Emoji表情符号兼容方案

Emoji表情符号兼容方案 一 什么是Emoji emoji就是表情符号;词义来自日语(えもじ,e-moji,moji在日语中的含义是字符)表情符号现已普遍应用于手机短信和网络聊天软件。emoji表情符号,在外国的手机短信里面已经是很流行使用的一种表情。手机上如何使用emoji:1.iphone、ipad系统:安装emoji free,再设置-通用-键盘...

RestTemplate 发送 get 请求使用误区 多个参数传值为null

RestTemplate 发送 get 请求使用误区 多个参数传值为null(转载) 首先看一下官方文档是怎么描述的,传递多个值的情况(注意例子中用到的@pathParam,一般要用@queryParam) RestTemplate 实例 @Configuration public class RestConfiguration { @...

Python学习笔记:字符编码原理和操作详解

一、电脑字符集的历史   1、电脑是如何将二进制与字符对应起来的?     我们知道,电脑底层只认识0和1的二进制数据,为了让电脑可以跟人类互动,我们使用8个二进制位(即1个字节)来对应一个更复杂的数字,     比如:使用二进制“01000001”来指代十进制“65”,也就是大写字母A     实际使用场景中,人类利用键盘打字符“A”时,实际上是打65这...