您的位置:首页 > 编程语言 > C#

六一儿童节的礼物:基于GB18030-2000汉字拼音类库(C#)

2011-05-24 20:36 489 查看
开发工具:

Visual Studio v2010

.NET Framework 4 Client Profile

版本历史:

V1.1 2011年5月29日

代码优化。

V1.0 2011年5月24日

实现GB18030-2000汉字拼音模块。

功能描述:

通过汉字获取拼音(基于频率排序)。可查询的汉字编码范围为0x3400~0x9FA5 0xF900~0xFAD9。

获取指定字符集的同音字列表(基于频率排序)。

数字标调音节和字符标调音节之间的互相转换。

音节排序(基于新华字典序)。

将兼容码字符转换为标准字符。

下载地址:

HYPY_Mandarin_CSharp.zip

源代码:

Pinyin.cs

/* ----------------------------------------------------------
文件名称:Pinyin.cs

作者:秦建辉

MSN:splashcn@msn.com

版本历史:
V1.1    2011年5月29日
代码优化。

V1.0	2011年5月24日
实现GB18030-2000汉字拼音模块。

功能描述:
1.通过汉字获取拼音(基于频率排序)。可查询的汉字编码范围为0x3400~0x9FA5 0xF900~0xFAD9。
2.获取指定字符集的同音字列表(基于频率排序)。
3.数字标调音节和字符标调音节之间的互相转换。
4.音节排序(基于新华字典序)。
5.将兼容码字符转换为标准字符。
------------------------------------------------------------ */

using System;
using System.Text;

namespace Splash
{
/// <summary>
/// GB18030-2000汉语拼音类库
/// 静态类库,运行时无需实例化
/// </summary>
public static partial class Pinyin
{
/// <summary>
/// 音节总类数 1402
/// </summary>
public const Int32 SYLLABLE_NUM = 1402;

/// <summary>
/// 标准码区间起始编码 0x3400
/// </summary>
public const Int32 NormZoneBegin = 0x3400;

/// <summary>
/// 标准码区间结束编码 0x9FA5
/// </summary>
public const Int32 NormZoneEnd = 0x9FA5;

/// <summary>
/// 兼容码区间起始编码 0xF900
/// </summary>
public const Int32 CompatibilityZoneBegin = 0xF900;

/// <summary>
/// 兼容码区间结束编码 0xFAFF
/// </summary>
public const Int32 CompatibilityZoneEnd = 0xFAFF;

/// <summary>
/// 位标志枚举类型,字符集分类
/// </summary>
[Flags]
public enum CharSet
{
/// <summary>
/// 未知字符集 0x00
/// </summary>
UNKNOWN = 0x00,

/// <summary>
/// GB 2312-1980字符集 0x01
/// </summary>
GB2312 = 0x01,

/// <summary>
/// GB 13000.1-1993字符集 0x02
/// </summary>
GBK = 0x02,

/// <summary>
/// GB 18030-2000字符集 0x04
/// </summary>
GB18030 = 0x04
}

/// <summary>
/// 通过UCS4编码获取汉字拼音音节索引集
/// </summary>
/// <param name="UCS4">汉字UCS4编码</param>
/// <returns>拼音音节索引集</returns>
public static UInt16[] Pronunciation(Int32 UCS4)
{
// 将兼容码字符转换到标准码字符
UCS4 = Compatibility2Norm(UCS4);

// 有效区间0x3400~0x9FA5,共计27484个有效汉字
if (UCS4 >= NormZoneBegin && UCS4 <= NormZoneEnd)
{
UInt16 Index = CharToSyllableTable[UCS4 - NormZoneBegin];
if (Index != 0xFFFF)
{
if (Index < (NormZoneEnd - NormZoneBegin + 1))
{   // 单音字
return new UInt16[] { Index };
}
else
{   // 多音字,二次定位
UInt16 Count = CharToSyllableTable[Index]; // 读音数
UInt16[] SyllableMap = new UInt16[Count];
for (Int32 i = 0; i < Count; i++)
{
SyllableMap[i] = CharToSyllableTable[Index + i + 1];
}

return SyllableMap;
}
}
}

// 读音未知
return null;
}

/// <summary>
/// 通过UCS2编码获取汉字拼音音节索引集
/// </summary>
/// <param name="UCS2">Unicode字符</param>
/// <returns>拼音音节索引集</returns>
public static UInt16[] Pronunciation(Char UCS2)
{
return Pronunciation(Convert.ToInt32(UCS2));
}

/// <summary>
/// 获取字符串指定索引位置字符的拼音音节索引集
/// </summary>
/// <param name="s">字符所在的字符串</param>
/// <param name="index">字符在字符串中的索引位置</param>
/// <returns>拼音音节索引集</returns>
public static UInt16[] Pronunciation(String s, Int32 index)
{
return Pronunciation(Char.ConvertToUtf32(s, index));
}

/// <summary>
/// 获取索引对应的拼音音节
/// </summary>
/// <param name="index">拼音音节索引号</param>
/// <param name="isDigitTone">输出方式。true:字符标调 false:数字标调</param>
/// <param name="isUppercase">输出方式。true:大写字母形式 false:小写字母形式</param>
/// <returns>拼音音节</returns>
public static String Syllable(Int32 index, Boolean isDigitTone = true, Boolean isUppercase = true)
{
if (index >= 0 && index < SYLLABLE_NUM)
{
// 开始索引位置
UInt16 BeginIndex;
if (index == 0)
BeginIndex = 0;
else
BeginIndex = SyllableEndIndex[index - 1];

// 结束索引位置
UInt16 EndIndex = SyllableEndIndex[index];

// 获取拼音音节(小写字母、字符标调)
String Syllable = Encoding.UTF8.GetString(SyllableMap, BeginIndex, EndIndex - BeginIndex);
if (isDigitTone)
{   // 转换为数字标掉
return CharTone2DigitTone(Syllable, isUppercase);
}
else
{   // 字符标调
if (isUppercase)
return Syllable.ToUpper();
else
return Syllable;
}
}

// 错误的索引号
return null;
}

/// <summary>
/// 获取音节索引号对应的同音字集合
/// </summary>
/// <param name="index">拼音音节索引号</param>
/// <param name="cs">字符集:GB2312、GBK、GB18030</param>
/// <returns>同音字集合</returns>
public static String Homophone(Int32 index, CharSet cs = CharSet.GB2312)
{
if ((index >= 0) && (index < SYLLABLE_NUM) && (cs != CharSet.UNKNOWN))
{
// 开始索引位置
UInt16 BeginIndex;
if (index == 0)
BeginIndex = 0;
else
BeginIndex = HomophoneEndIndex[index - 1];

// 结束索引位置
UInt16 EndIndex = HomophoneEndIndex[index];
if (BeginIndex < EndIndex)
{
StringBuilder sb = new StringBuilder(EndIndex - BeginIndex);
for (UInt16 i = BeginIndex; i < EndIndex; i++)
{
Int32 UCS4 = HomophoneMap[i];   // 字符编码
if ((cs & CharSet.GB18030) != 0)
{
sb.Append(Convert.ToChar(UCS4));
}
else
{
if ((CharSetClass(UCS4) & cs) != 0)
{
sb.Append(Convert.ToChar(UCS4));
}
}
}

if (sb.Length != 0) return sb.ToString();
}
}

// 同音字不存在
return null;
}

/// <summary>
/// 将拼音从字符标调转换成数字标调(支持多音节)
/// </summary>
/// <param name="Syllable">字符标调的拼音音节</param>
/// <param name="isUppercase">输出方式。true:大写字母形式 false:小写字母形式</param>
/// <returns>数字标调的拼音音节</returns>
public static String CharTone2DigitTone(String Syllable, Boolean isUppercase = true)
{
if (String.IsNullOrEmpty(Syllable))
{
return null;
}

StringBuilder sb = new StringBuilder(Syllable.Length + 2);

Int32 CharToneNum = CharTone2DigitToneTable.GetLength(0);  // 获取数组行数

Char Tone = '5';    // 初始化数字声调
foreach(Char UCS2 in Syllable)
{
if (UCS2 == '-')
{   // 连接符
sb.Append(Tone);
sb.Append('-');
Tone = '5';    // 初始化数字声调
}
else
{
Int32 i;
for (i = 0; i < CharToneNum; i++)
{
if (UCS2 == CharTone2DigitToneTable[i, 0])
{   // 带调字符
Tone = CharTone2DigitToneTable[i, 2];   // 声调
if (CharTone2DigitToneTable[i, 1] != 0)
{
sb.Append(CharTone2DigitToneTable[i, 1]);   // 基本字符
}

break;
}
}

if (i == CharToneNum)
{   // 非带调字符
sb.Append(UCS2);
}
}
}

sb.Append(Tone);

if (isUppercase)
{   // 大写字母形式
return sb.ToString().ToUpper();
}
else
{   // 小写字母形式
return sb.ToString().ToLower();
}
}

/// <summary>
/// 多音节版本:将数字标调转换成字符标调
/// </summary>
/// <param name="Syllable">数字标调的拼音音节</param>
/// <param name="isUppercase">输出方式。true:大写字母形式 false:小写字母形式</param>
/// <returns>字符标调的拼音音节</returns>
public static String DigitTone2CharTone(String Syllable, Boolean isUppercase = false)
{
if (String.IsNullOrEmpty(Syllable))
{
return null;
}

// 可标调字符集
String ToneCharSet = "aoeiu/u00FC/u00EAnm"; // 关键:字符顺序
String CombiningCharSet = "/u0304/u0301/u030C/u0300";   // 阴平、阳平、上声、去声

StringBuilder sb = new StringBuilder(Syllable.Length);
Int32 BeginIndex = 0;
Int32 EndIndex = Syllable.Length;
while (BeginIndex < EndIndex)
{
Int32 Count;
Int32 HyphenIndex = Syllable.IndexOf('-', BeginIndex);
if (HyphenIndex == -1)
{   // 单音节
Count = EndIndex - BeginIndex - 1;
}
else
{   // 多音节
Count = HyphenIndex - BeginIndex - 1;
}

if (Count < 1) return null; // 音节错误

Char Tone = Syllable[BeginIndex + Count];
if (Tone >= '1' && Tone <= '4')
{
Boolean isNotFind = true;
foreach (Char ToneChar in ToneCharSet)
{   // 查找小写
Int32 Index = Syllable.IndexOf(ToneChar, BeginIndex, Count);
if (Index == -1)
{   // 查找大写
Index = Syllable.IndexOf(Char.ToUpper(ToneChar), BeginIndex, Count);
}

if (Index != -1)
{
Index++;    // 声调字符插入位置
if (Char.ToLower(ToneChar) == 'i')
{
if ((Index < BeginIndex + Count) && Char.ToLower(Syllable[Index]) == 'u')
{
Index++;
}
}

sb.Append(Syllable, BeginIndex, Index - BeginIndex);
sb.Append(CombiningCharSet[Tone - '1']);    // 声调
sb.Append(Syllable, Index, BeginIndex + Count - Index);

isNotFind = false;
break;
}
}

if (isNotFind) return null; // 音节错误,无带调字符
}
else if (Tone == '5')
{
sb.Append(Syllable, BeginIndex, Count);
}
else
{
return null;    // 音节错误
}

if (HyphenIndex == -1)
{
break;
}
else
{
sb.Append('-');
BeginIndex = HyphenIndex + 1;
}
}

if (isUppercase)
{   // 大写字母形式
return sb.ToString().ToUpper();
}
else
{   // 小写字母形式
return sb.ToString().ToLower();
}
}

/// <summary>
/// 基于数字标调的汉语拼音串比较函数(新华字典序)
/// </summary>
/// <param name="x">数字标调的拼音串</param>
/// <param name="y">数字标调的拼音串</param>
/// <returns>-1:x排在y前面 0:x与y顺序相等 1:x排在y后面</returns>
public static Int32 PinyinCompare(String x, String y)
{
if (String.IsNullOrEmpty(x))
{
if (String.IsNullOrEmpty(y))
{
return 0;
}
else
{
return -1;
}
}
else if (String.IsNullOrEmpty(y))
{
return 1;
}

// 统一到大写状态
String u = x.ToUpper();
String v = y.ToUpper();

// 多音节处理
Int32 HyphenPosX = u.IndexOf('-');
Int32 HyphenPosY = v.IndexOf('-');
if (HyphenPosX != -1)
{
if (HyphenPosY != -1)
{
// 比较第一个音节
Int32 RetVal = PinyinCompare(u.Substring(0, HyphenPosX), v.Substring(0, HyphenPosY));
if (RetVal == 0)
{   // 继续比较其余音节
return PinyinCompare(u.Substring(HyphenPosX + 1), v.Substring(HyphenPosY + 1));
}
else
{
return RetVal;
}
}
else
{
Int32 RetVal = PinyinCompare(u.Substring(0, HyphenPosX), v);
if (RetVal == 0)
{
return 1;
}
else
{
return RetVal;
}
}
}
else if (HyphenPosY != -1)
{   // 比较第一个音节
Int32 RetVal = PinyinCompare(u, v.Substring(0, HyphenPosY));
if (RetVal == 0)
{
return -1;
}
else
{
return RetVal;
}
}

if (u.IndexOf('/u00CA') != -1)
{
if (v.IndexOf('/u00CA') != -1)
{
return PinyinCompare(u.Replace('/u00CA', 'E'), v.Replace('/u00CA', 'E'));
}
else
{   // 关键:去掉声调后再比较
Int32 RetVal = PinyinCompare(u.Replace('/u00CA', 'E').Substring(0, u.Length - 1), v.Substring(0, v.Length - 1));
if (RetVal == 0)
{
return 1;
}
else
{
return RetVal;
}
}
}
else if (v.IndexOf('/u00CA') != -1)
{   // 关键:去掉声调后再比较
Int32 RetVal = PinyinCompare(u.Substring(0, u.Length - 1), v.Replace('/u00CA', 'E').Substring(0, v.Length - 1));
if (RetVal == 0)
{
return -1;
}
else
{
return RetVal;
}
}

if (u.IndexOf('/u00DC') != -1)
{
if (v.IndexOf('/u00DC') != -1)
{
return PinyinCompare(u.Replace('/u00DC', 'U'), v.Replace('/u00DC', 'U'));
}
else
{   // 去掉声调后再比较
Int32 RetVal = PinyinCompare(u.Replace('/u00DC', 'U').Substring(0, u.Length - 1), v.Substring(0, v.Length - 1));
if (RetVal == 0)
{
return 1;
}
else
{
return RetVal;
}
}
}
else if (v.IndexOf('/u00DC') != -1)
{   // 去掉声调后再比较
Int32 RetVal = PinyinCompare(u.Substring(0, u.Length - 1), v.Replace('/u00DC', 'U').Substring(0, v.Length - 1));
if (RetVal == 0)
{
return -1;
}
else
{
return RetVal;
}
}

// 普通字符串比较
return u.CompareTo(v);
}

/// <summary>
/// 获取汉字所属的字符集组合
/// </summary>
/// <param name="UCS4">汉字UCS4编码</param>
/// <returns>该汉字所属的字符集组合</returns>
/// <remarks>位标志枚举,支持值的任意组合</remarks>
public static CharSet CharSetClass(Int32 UCS4)
{
if (UCS4 >= NormZoneBegin && UCS4 <= NormZoneEnd)
{
Int32 Class;

Int32 Span = UCS4 - NormZoneBegin;
Int32 Index = Span >> 1;
if (Span % 2 == 0)
{   // 字节低4Bit
Class = HZClass[Index] & 0x0F;
}
else
{   // 字节高4Bit
Class = HZClass[Index] >> 4;
}

return (CharSet)Class;  // 位标志枚举,支持值的任意组合
}

return CharSet.UNKNOWN;
}

/// <summary>
/// 将兼容码字符转换为标准字符
/// </summary>
/// <param name="UCS4">要转换的兼容码</param>
/// <returns>返回标准码</returns>
public static Int32 Compatibility2Norm(Int32 UCS4)
{   // 兼容码区间
if (UCS4 >= CompatibilityZoneBegin && UCS4 <= CompatibilityZoneEnd)
{   // 折半查找
Int32 BeginIndex = 0;
Int32 EndIndex = Compatibility2NormTable.GetLength(0) - 1;
while (BeginIndex <= EndIndex)
{
Int32 Middle = (BeginIndex + EndIndex) >> 1;
Int32 Code = Compatibility2NormTable[Middle, 0];
if (UCS4 > Code)
{
BeginIndex = Middle + 1;
}
else if (UCS4 < Code)
{
EndIndex = Middle - 1;
}
else
{   // 返回标准码
return Compatibility2NormTable[Middle, 1];
}
}
}

// 返回原始码
return UCS4;
}

/// <summary>
/// 将兼容码字符转换为标准字符
/// </summary>
/// <param name="UCS2">UCS2编码字符</param>
/// <returns>兼容码对应的标准码字符</returns>
/// <remarks>调用时注意异常处理:OverflowException</remarks>
public static Char Compatibility2Norm(Char UCS2)
{
return Convert.ToChar(Compatibility2Norm(Convert.ToInt32(UCS2)));
}

/// <summary>
/// 将兼容码字符转换为标准字符
/// </summary>
/// <param name="s">字符所在的字符串</param>
/// <param name="index">字符在字符串中的索引位置</param>
/// <returns>兼容码对应的标准码字符串</returns>
/// <remarks>调用时注意异常处理:ArgumentNullException、ArgumentOutOfRangeException、ArgumentException</remarks>
public static String Compatibility2Norm(String s, Int32 index)
{
return Char.ConvertFromUtf32(Compatibility2Norm(Char.ConvertToUtf32(s, index)));
}
}
}
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐