迷梦小筑—让灵魂在代码中无限升华
我幸运,并不是所有的猫都可以拥有大脑!

 

 注意:这绝不是网上散播的只能使用拼音首字符进行汉字查找的方案,这是一个真正的输入完整拼音得到相应汉字的解决办法。

 大部分程序员眼中只有变量、函数……他们忽略生活中的一切,他们并不理解真正的优雅的程序解决方案往往来自生活!

 今天群内有兄弟提问怎样使用一个完整的拼音查找到相应的汉字。这显然是网上散播的只能使用拼音首字符进行汉字查找的方案无法解决的,他们在拼命地寻找微软的API,网上现成的函数,但他们忽略了一点,其实所有的一切,都因为他们缺少一个(汉字,拼音)这样的格式的数据库。
 其实取得这样一个数据库很简单。在很久以前我初学电脑,很久很久以前的事了,我那时只会玩各种不同的游戏8-)由于我不会用win98,所以我常常用鼠标点击我可以点击到的一切东西,其中适好包括一个叫“输入法生成器”的程序。更奏巧的是我当时也适好发现这个输入法生成器可以将输入法的数据库转为一个可读的TXT文件。只要取得全拼输入法的数据文件,一切都解决了。

 1、首先需要一个win98 ,你们可能没有了吧,因为你们不玩游戏8(,用VMware虚拟安装啦。输入法生成器是可选安装的,如果在附件中没看到<输入法生成器> ,就使用win98 的安装程序安装它。
 打开输入法生成器,选逆转换 ,打开文件c:\windows\system\winpy.mb(这是全拼输入法的数据文件),在码表原文件中写上c:\windows\desktop\winpy.txt 按逆转换 
 
 很高兴,我们得到了拼音字符的数据库文件winpy.txt。
 用编辑软件打开这个文件,看到这样的格式:
 Description]
 Name=全拼
 MaxCodes=12
 MaxElement=1
 UsedCodes=abcdefghijklmnopqrstuvwxyz
 WildChar=?
 NumRules=3
 [Rule]
 ca4=p10+p20+p30+p40
 ce2=p10+p20
 ce3=p10+p20+p30
 [Text]
 啊a
 阿a
 一个汉字对一个拼音,回车换行符分开各项,将这种格式的字符串分为汉字和拼音是很容易的,拼音是字母,在unicode中不会超过255,汉字在unicode中大于255,根据这个判断来分割就行了
 
 2、将文件的头几行说明删除后,我们得到这样格式的拼音与汉字的键对(呵a he),应为需要用拼音找汉字,我再用一个C#代码将这个文件格式变为(a he呵)拼音在前,汉字在后这样的格式以方便查找。
 示例程序效果如下,两个textbox,上面一个输拼音,下面一个会显示这个拼音对应的汉字,这一刻起我才发现中华汉字是那样的博大精深,一个读音居然有这么多的同音字:


 
 完整的C#代码/Files/DreamlikeAttic/Pinyintest.rar如下,由于是示例,我并没有使用二分查分之类的方法优化,我只是简单将数据文件以字符串的方式读到内存,并使用indexof来确定拼音的位置后取得对应的文字。并且对数据文件也进行了处理,去掉了所有的词组,在debug中可以看到PYCompact.txt这个不再包含词组拼音的数据文件。其实得到了这个数据库,你要怎么玩拼音都可以,不会数据搜索技术就自己再学习一下大学的教科书吧!

   public partial class Form1 : Form
  {
    string m_strPinyinLib;//保存数据文件中所有的拼音及汉字
    public Form1()
    {
      InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
      StreamReader tobjTextReader;
      StreamWriter tobjTextWriter;
      BinaryWriter tobjBinaryWriter;
      FileStream tobjOutPutFile;
      string tstrItemValue;
      string tstrTemp;
      tobjTextReader = new StreamReader(@"winpy.txt", true);
      tobjOutPutFile = File.Open("PYCompact.txt", FileMode.Create);
      tobjBinaryWriter = new BinaryWriter(tobjOutPutFile);
      tobjTextWriter = new StreamWriter(tobjOutPutFile, Encoding.Unicode);
      tstrItemValue = tobjTextReader.ReadLine();
      while (tstrItemValue != null)
      {
        //只保留单字不再要库中的词组
        if (tstrItemValue.ToCharArray()[1] < 255)
        {
          //将拼音放在前面
          tstrTemp = tstrItemValue.Substring(1) + tstrItemValue.Substring(0, 1);
          tobjTextWriter.WriteLine(tstrTemp);
        }//end if
        //tobjBinaryWriter.Write(
        tstrItemValue = tobjTextReader.ReadLine();
      }//end while
      tobjTextWriter.Close();
      tobjBinaryWriter.Close();
      tobjOutPutFile.Close();
      tobjTextReader.Close();
      //将拼音库的内容读到一个字符串中待用
      tobjTextReader = new StreamReader(@"PYCompact.txt", true);
      m_strPinyinLib = tobjTextReader.ReadToEnd();
      tobjTextReader.Close();
    }
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
      string tstrChineseList = "";
      if (textBox1.Text != "")
        tstrChineseList = findChinese(textBox1.Text);
      textBox2.Text = tstrChineseList;
    }//end sub
    string findChinese(string ni_strPinyin)
    {
      int tintFirstFind;
      string tstrReturn = "";
      string tstrTemp = "";
      int tintloop;
      tintFirstFind = m_strPinyinLib.IndexOf(ni_strPinyin);
      while (tintFirstFind >= 0)
      {

        for (tintloop = tintFirstFind; tintloop < m_strPinyinLib.Length - 1; tintloop++)
        {
          if ((tintFirstFind - 1) > 0)
          {
            if (m_strPinyinLib.Substring(tintFirstFind - 1, 1).ToCharArray()[0] < 255
                && m_strPinyinLib.Substring(tintFirstFind - 1, 1).ToCharArray()[0] != ' ')
            {
              break; //由于找到的这个拼音前面还有英文字符且不为空格,说明这个拼音可是是u查找到gu这种情况,不予理会
            }//end if
          }//end if
          if ((tintFirstFind + ni_strPinyin.Length) <( m_strPinyinLib.Length - 1))
          {
            if (m_strPinyinLib.Substring(tintFirstFind + ni_strPinyin.Length, 1).ToCharArray()[0] < 255
              && m_strPinyinLib.Substring(tintFirstFind + ni_strPinyin.Length, 1).ToCharArray()[0] != ' ')
            {
              break; //由于找到的这个拼音后面还有英文字符且不为空格,说明这个拼音可是是gu查找到guang这种情况,不予理会
            }//end if
          }//endif
          tstrTemp = m_strPinyinLib.Substring(tintloop, 1);
          if (tstrTemp.ToCharArray()[0] > 255)
          { //找到对应的汉字,退出
            break;
          }//end if
        }//next
        tstrReturn += tstrTemp;
        tintFirstFind = m_strPinyinLib.IndexOf(ni_strPinyin, tintloop + 1);

      }//end while
      return (tstrReturn);
    }//end function
  }//end class
本blog文档,未经作者许可,谢绝转载!
posted on 2006-06-30 23:23  拍拍猫脑  阅读(5210)  评论(14编辑  收藏  举报