.NET Compact Framework中解码GB2312

昨天在制作“掌上IP通”调用纯真IP数据库的时候,遇到了GB2312解码的问题。

我想,在.NET平台上本来可以用 System.Text.Encoding.GetEncoding(“GB2312”)得到GB2312的解码器的,在.NET Compact Framework中也可以使用这个方法。查阅MSDN,也确实能够支持。但十分遗憾的是,当在PDA上执行此条语句的时候,返回的却是null。如果直 接使用System.Text.Encoding.GetEncoding(“GB2312”).GetString方法的话,会抛出一个 PlatformNotSupport异常。

后查询到MSDN关于这个问题的解答(详见http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_evtuv/html/etcondeviceprojectglobalization.asp) Encoding
The .NET Compact Framework supports character encoding on all devices: Unicode (BE and LE), UTF8, UTF7, and ASCII.

There is limited support for code page encoding and only if the encoding is recognized by the operating system of the device.

The .NET Compact Framework throws a PlatformNotSupportedException if the a required encoding is not available on the device.

If the optional component Mlang.dll is on the device, the following code pages are supported: CP 51932 (EUC-JP), CP 50220 (ISO2022JP), and CP 50221 (cslSO2022JP).

也就是说GB2312不受.NET Compact Framework的支持。

很无赖,我们无法用常规的方法来解码GB2312。在此搜索有关GB2312的文章,发现原来GB2312有一个对照表,可以和Unicode进行双向的转换。后下载到一个GB2312.TXT的对照表(请见[download id=”28”]),对照词表可以将GB2312转换成Unicode然后就可以解码了。

根据GB2312.txt中所述,需要将实际的编码减去0x8080,然后再查表。

例如“南”的GB2312编码为:0xC4CF,查表的时候减去0x8080,得到0x444F,查表得到Unicode码:0x5357。此后利用System.Text.Encoding.Unicode.GetChars()就可以得到相应的字符。

虽然转了一个弯,但是还是达到了目的。

为此,我写了一个GB2312 To Unicode Conver Table 的控制台程序,以便将GB2312.TXT转换成一个索引供查询。编码好的文件下载:[download id=”29”]

代码如下:

Imports System.Text
Imports System.IO
Module Module1Module Module1

Sub Main()Sub Main()
Dim sr As New StreamReader("D:gb2312.txt")
Dim fs As New FileStream("D:gb2312.dat", FileMode.Create)
Dim sw As New BinaryWriter(fs)
For i As Integer = 1 To 70
sr.ReadLine()
Next
Do Until sr.EndOfStream
Dim ss As String() = sr.ReadLine.Split
Dim HEX As Short = CShort(Val(ss(1).Replace("0x", "&H")))
Dim offset As Integer = (CInt(Val(ss(0).Replace("0x", "&H"))) - &H2121) * 2
sw.BaseStream.Position = offset
sw.Write(HEX)
Loop
sw.Close()
End Sub

End Module

使用的时候将欲解码的GB2312编码减去0x8080,再减去0x2121(偏移),也就是说减去0xA1A1,然后将 FileStream.Position指向所得到的结果的2倍(两个字节一个码)并读取一个Int16就可以得到对应的Unicode码。下面是我在掌 心IP通中的一段代码。

public class GB2312ToUnicode
{
private FileStream fs;
private BinaryReader br;
public GB2312ToUnicode(string index)
{
fs=new FileStream(index, FileMode.Open);
br = new BinaryReader(fs);
}

public char Convert(byte[] b)
{
int index = ((b[0] << 8) + b[1] - 0xa1a1)*2;
fs.Position = index;
int tmp = (int)br.ReadInt16() & 0xFFFF;
return System.Convert.ToChar(tmp);
}

~GB2312ToUnicode()
{
br.Close();
}

}

这样就方便的得到了GB2312的解码器。

另外,如果打开GB2312.DAT文件可以看到,数据中有很多的0。本来可以通过重新计算偏移的方法来压缩数据,但是考虑到PocketPC上面的速度,尤其是要解码大量文本的时候,就只好用空间换取时间了。

升级时间变成了0小时小感

升级时间变成了0小时。腾迅公司终于做了点好事了……

想想这个事情带来的一系列问题。大家挂机了……费电了……专业挂机……收费……免费……盗 取密码……投诉……腾迅解决。腾迅的挂机给腾迅带来的好处我像还没有带给专业挂机的好处多。只要密码在手了,网站可以收集很多相关的资料,比如说你的好友 信息,进而可以得到你的关系网,一系列的问题就存在了……虽然说是免费,但是还是暗藏杀机,说不定别有用心的人会利用这些资料来卖钱,想想,什么事情人 不能干得出来……

当然,提供挂机也带来了技术上的进步。首先是考验了腾迅的服务器……当然,其间还是带来了无法登陆的诸多问题;其次是让更多的 人开始研究起QQ来。我也不例外,当时给一个朋友设计了一个挂机的平台,用的是LumaQQ,开放源代码的。听说工作得挺好,只不过还没有用的上多久,腾 迅就开始改变方式了……~

所以说什么叫先下手为强呢,呵呵……

最近写的一个开源软件——PocketSMS

这是我自己写的一个短信发送接收软件,主要是为了解决自己的HP1937和SIEMENS CXV65连接发送短信的问题。之前,我试用过Mphone等软件,都不能很好的支持这个手机。后来就自己写了一个。

这是我为我自己的需要写的一个精简版。原本打算做一个更强的版本的,但现在看来时间不足,精力也不足,也只好暂时放弃了。

现在此软件能够获取SIM卡上的通讯薄和PocketOutlook上的通讯薄,能够群发短信(可能有BUG),自动接收状态报告和新来短信,自动存储短信历史到文本文件,方便管理。

程 序使用VB.Net书写,由于用到了一个非托管的PocketOutlook.dll,而这个dll是为ARM机型写的,所以暂时只支持ARM。其他手机 我没有测试过,我看了一下AT指令,理论上SIEMENS和NOKIA的手机都能使用。只需要复制压缩包内文件到任意目录即可使用。另外建议安装.net compact framework sp3,修正了很多问题并能够明显的加快.net cf应用程序速度。

第一次运行请进入设置,然后选择端口号。一般红外连接选COM3,蓝牙可能需要配对后使用COM6(我无设备测试),连接速度115200即可。

软件为绿色,如果出现问题,删除data目录即可以重新开始。

此软件为我自己而写,如果有需要请自行修改源代码,呵呵;)

下载:
[download id=”27”]

.Net CF访问Pocket Outlook法三则

近日做的软件需要与Outlook进行交互,很不幸的是.Net CF没有提供直接的方法。上网Google了一下,总结出两个方法:

  • 最简单的方式——使用商用InTheHand Outlook组件,代价是很明显的……$49。微软的MSDN里面提供的也是适用InTheHand的东西,显然对于我们来说此法作废。……
  • 最复杂的方法——自己开发.Net下POOM(Pocket Outlook Object Model)。后来想想这需要涉及到太多的东西,不划算。
  • 再找找,绝对有免费的——功夫不负有心人——外国朋友EGILH的Blog上贴出来一篇文章——Using the POOM from .NET CF 1.0

文章中写道了用POOM C++ warapper来访问的方法。他提到了.NET Compact Framework Sample: POOM wrapper,是封装了的POOM代码,其中DEMO代码提供了一个.Net CF client,提供了一些基本的功能。正好,我需要的读取联系薄的功能就在里面:)

第一次运行代码之前记得要找到sample的安装目录并把里面的Cab包安装到PPC上,内包含了POOM C++ wrapper的dll,要不然.Net CF Client运行时会出现MissingMethod错误。
……赫赫,终于找到免费的了,用起来还不错……~

关于如何扩展.Net CF client,EGILH的文章也说得很清楚了,大家自己钻研了:)

感觉ListView设计得不好的地方

ListView有Item属性,Item又有SubItem属性。如果

Dim newItem As New ListViewItem
newItem.Text = "0"
newItem.SubItems.Add("1")
newItem.SubItems.Add("2")

这样访问newItem.SubItems(0).Text会是0

感觉SubItems既然叫SubItem,那么应该第一个,也就是0索引应该是添加到SubItem的第一个的值,这里为1。但是变成了Item.Text的值,有点莫名其妙的感觉……~

我在写程序的时候经常把这个问题搞错(粗心阿),希望大家在写ListviewItem的时候不要犯这样的毛病了:)