usb接口

如果palm和手机有一个usb接口,并且有一个mass storage的驱动,那就帅呆了。

这样,我就可以用palm连一个U盘,想放多大的电影就放多大的。如果再加一个带电源的移动硬盘,那绝对是一台小电脑了。

不知道palm和那些手机厂商想到了没有,如果没有想到的话,我就去申请专利去:)

基于Ajax模式的Blog Browser

只所以说成是Ajax,其实是我写成的代码,一不小心发现这就使传说中的Ajax模式。原来什么先进的东西,原来是这么平民化。

先说一下应用吧,背景是这样的:我有很多xml文件,作为单个xml文件,可以通过xml+xsl的形式进行浏览。例如,可以在浏览器中输入”http://marvel.hit.edu.cn:8080/weblogs/2004_8_23.xml”l来查看2004年8月23号的blog。问题是缺少我不知道我在哪些日子大发感慨,何况在浏览器中直接输入地址是一件很麻烦的事情。

于是,我需要做的事情是:

  1. 了解我写了哪些日记
  2. 获取这些日记

显然,第一件事情需要在服务器端完成,第二件事情是客户端浏览器完成的。

于是我先写了一个C程序,获得所有日志的信息,整合到一个xml文件中。(xml格式有利于客户端解析),代码在此 。执行之后生成的文件为list.xml

之后,我在浏览器中就需要获得list.xml的信息,并且需要解析该文件。普通的方法不行,我需要使用XMLHttp请求(在Firefox中称之为XMLHttpRequest,而在ie中,这是一个ActiveX控件,叫做Microsoft.XMLHTTP)。

下载函数主要代码如下,详见源文件:

[coolcode lang=”javascript”]
function loadXMLDoc(url)
{
// code for Mozilla, etc.
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
// code for IE
else if (window.ActiveXObject)
{
xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}

if (xmlhttp)
{
xmlhttp.onreadystatechange=xmlhttpChange;
xmlhttp.open(“GET”,url,true);
xmlhttp.send(null);
}
}
function xmlhttpChange()
{
if (xmlhttp.readyState!=4)
return;
// if “OK”
if (xmlhttp.status==200 || xmlhttp.status==0)
{
//Code Goes here…
}
else
{
document.getElementById(“content”).innerHTML = “Problem retrieving XML data”;
}
}
[/coolcode]

  1. xmlhttp.readyState是指xmlhttp请求的状态,0为未初始化,1为正在装载,2为装载完毕,3为交互中,4为完成。当状态发生变化的时候,浏览器会回调xmlhttp.onreadystatechange函数,即xmlhttpChange。(请使用回调函数这种形式,不要使用while的无穷循环来判断是否完成,这种方式会大量消耗处理器资源,并且不能显示页面)
    xmlhttp.status是指返回的状态,Web正常返回为200 ,本地调试正常返回为0。
  2. 处理代码略去,如果想了解更多,可以参考http://marvel.hit.edu.cn:8080/weblogs/view_xml_blog.html。
  3. loadXMLDoc需要被调用两次,第一次获得list.xml,第二次获得某一天的日志文件

返回的xml文件解析

当我们获得了xml文件,自然需要对文件进行解析。 解析日志文件的代码如下(解析list.xml的代码类似,详见文件):

[coolcode lang=”javascript”]
var title=xmlhttp.responseXML.getElementsByTagName(“Title”);
document.getElementById(“content”).innerHTML += (title[0].firstChild.data+”
“);
var posttime=xmlhttp.responseXML.getElementsByTagName(“PostTime”);
var post;
if(posttime[0] == null)
{
var year=xmlhttp.responseXML.getElementsByTagName(“Year”)[0].firstChild.data;
var month=xmlhttp.responseXML.getElementsByTagName(“Month”)[0].firstChild.data;
var day=xmlhttp.responseXML.getElementsByTagName(“Day”)[0].firstChild.data;
post= year+” – “+month+” – “+day;
}
else
{
post = posttime[0].firstChild.data;
}
document.getElementById(“content”).innerHTML += (post+”
“);

var content=xmlhttp.responseXML.getElementsByTagName(“Content”);
document.getElementById(“content”).innerHTML += (content[0].firstChild.data);

[/coolcode]

这次,全部搞定.分析一下

  1. 服务器端使用了C程序生成xml格式的文件,这可以看过Ajax的服务器端程序生成xml格式的结果供浏览器使用
  2. 浏览器客户端使用了xmlhttp的请求,异步获得了服务器端的xml结果,此期间没有刷新,只是出现了“Loading”的提示。解析完毕后即可显示内容。可以看出,Ajax的三大特征“异步交互、JavaScript脚本和XML封装数据的三大特征”完全得到了发挥

结论是:这次遵循了分析问题、解决问题的一般思路,搞定之后居然发现使用的模式就是现在相当热的技术。从而可见,做技术,应该是从实践需要出发,而不是单纯的去追求新的技术、新的框架。即使是最新的技术和框架,它们的出现必定有它们的道理,不需要刻意去学习。相反,实践才是最重要的,从实际中发现问题,解决问题,也许就能找到一种新的方法。如果我这个页面早做几年,也许我就是Ajax的创造者,你说呢?
附:Ajax,异步JavaScript与XML,是使用客户端脚本与Web服务器交换数据的Web应用开发方法。这样,Web页面不用打断交互流程进行重新 加裁,就可以动态地更新。使用Ajax,你可以创建接近本地桌面应用的,直接的、高可用的、更丰富的、更动态的Web用户接口界面。

FF支持xsl了

今天看看msn的聊天记录,它们是用xml+xsl实现的.我将xml用firefox浏览,意外地发现竟然能够正常显示.
不知道Firefox什么时候开始支持的,估计是1.5的时候吧.

以前我的blog是用了xml+xsl方式,但是发现ff不支持。于是是用了xml+css的方式,但是总觉得这种方式不太好,既然是用了xml这种形式,就应该严格一些,优美一些,但是单纯通过css文件就破坏了这种和谐。

现在好了, 我可以重写我的xsl文件了。呵呵

将word文档转化为其他格式

以前看到google能搜索office文档,心里想,对于google来说,其中的难点在于doc到文本格式的转化,这是是怎么完成的呢?

其实这一步在Office提供的COM 中就可以解决了.以C#为例,我们来看看如何将word文档转化为其他的各种格式.

首先,我们需要添加引用(Solution Explorer中右击选择Add Reference… ),选择COM中的Microsoft Word 11.0 Object Library。

然后,添加代码:

[coolcode lang=”java”]
object objFileName = ((object)”sampleWordFile.doc”);
Word.Application Word_App = null;
Word.Document Word_doc = null;
Word_App = new Word.Application();
Word_doc = new Word.Document();
Word.Documents Docs = Word_App.Documents;
Word_App.Visible = false;
//Open File
Word_doc = Docs.Open(ref objFileName, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,ref missing,
ref missing, ref missing, ref missing);
object format = null;
object tempfile = null;

format = Word.WdSaveFormat.wdFormatText;
tempfile = “c:/temp.txt”;
Word_App.ActiveDocument.SaveAs(ref tempfile, ref format, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing);
Word_doc.Close(ref missing, ref missing, ref missing);
[/coolcode]

这样就将 sampleWordFile.doc转化为c:/temp.txt。同样的,我们可以设置
[coolcode lang=”java”]
format = Word.WdSaveFormat.wdFormatRTF;
[/coolcode]
这样,可以转化为rtf格式,甚至是html、xml格式,等等。
word.jpg

BTW,CoolCode 没有专门的CSharp语法,所以只能用java代用了,效果还不错。两者语法真的好像,汗……

Debian的字体

有时候心血来潮什么事情都可能做。好好的系统,说重装就重装了。原因我也说不清。可能是因为最近心情比较放松,也比较无聊吧。
但是事实证明我是错的,Debian的testing真的没有stable好用。反复装了三次,系统终于搞定了。

当然今天也不全是令人沮丧的事,至少我把Debian的字体搞定了。我在没有预装任何中文字体的前提下,安装Windows的字体。具体参照: 如何使用xp带的字体来进行中文美化?
BTW,Ubuntu的中文化这个页面十分值得一看。毕竟他和Debian同出一家,有很多都互通的。http://www.ubuntu.org.cn/support/documentation/zhfaq

看看我的Debian,效果怎么样?

Debian Chineselization

PHP的编码转换的问题

今天准备将IP Search添加到Blog中,结果发现一个问题:纯真数据库使用了gb2312编码,而wordpress用的是utf-8编码。页面显示的是乱码,所以需要找到一个办法在PHP中实现两种编码的互转。

看看PHP Manual,似乎PHP没有像.Net那样专门提供一个Encoding的类,所以只能用其他方法了。网上的方法有两种:

第一种是使用iconv 函数。例如, 下面的例子是利用php将”全”这中编码转换为gb2312.:

[coolcode lang=”php”]
$str = “TTL全天候自动聚焦”;
$str = preg_replace(“|&#([0-9]{1,5});|”, “”.u2utf82gb(\1).””, $str);
$str = “$str=”$str”;”;

eval($str);
echo $str;

function u2utf82gb($c){
$str=””;
if ($c < 0x80) {
$str.=$c;
} else if ($c < 0x800) {
$str.=chr(0xC0 | $c>>6);
$str.=chr(0x80 | $c & 0x3F);
} else if ($c < 0x10000) {
$str.=chr(0xE0 | $c>>12);
$str.=chr(0x80 | $c>>6 & 0x3F);
$str.=chr(0x80 | $c & 0x3F);
} else if ($c < 0x200000) {
$str.=chr(0xF0 | $c>>18);
$str.=chr(0x80 | $c>>12 & 0x3F);
$str.=chr(0x80 | $c>>6 & 0x3F);
$str.=chr(0x80 | $c & 0x3F);
}
return iconv(‘UTF-8’, ‘GB2312’, $str);
}
?>
[/coolcode]
第二种是使用JavaScript实现的,例如:

[coolcode lang=”javascript”]
string utfinfo = “document.write(“alert(‘aa你好么??’);”);”;
string gb2312info = string.Empty;
Encoding utf8 = Encoding.UTF8;
Encoding gb2312 = Encoding.GetEncoding(“gb2312”);
// Convert the string into a byte[].
byte[] unicodeBytes = utf8.GetBytes(utfinfo);
// Perform the conversion from one encoding to the other.
byte[] asciiBytes = Encoding.Convert(utf8, gb2312, unicodeBytes);
// 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[] asciiChars = new char[gb2312.GetCharCount(asciiBytes, 0, asciiBytes.Length)];
gb2312.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0);
gb2312info = new string(asciiChars);
[/coolcode]

但是上面两种方法的缺点就是太繁了, 其实我们可以使用autogb来完成转化的工作。由于它是对于文件进行操作的,所以我们需要两个临时文件。代码如下:
[coolcode lang=”php”]
$fd=fopen(“/tmp/.marvel01″,”w”);
fwrite($fd, $gbstring);
fclose($fd);
`autogb -i gb -o utf8 /tmp/.marvel02`;
$fd=fopen(“/tmp/.marvel02″,”r”);
echo fgets($fd, 1024);
fclose($fd);
[/coolcode]

这样,我们就能将一个gb2312的字符串转化为utf-8的字符串。这里最需要注意的是程序的安全性,不要给别人任何bug可以利用的。当然 ,你还需要下载autogb这个工具。

Compile Linux Module

在学习内核的时候总是有一种在学习理论的感觉。应该很多东西都实验不了。比如说内核的寄存器、全局变量等等。像内核空间的地址在正常的用户空间就根本接触不到。

但是当我看到了Linux的模块的时候,我发现这个问题解决了!我们完全可以通过插入一个自定义的模块来了解内核态的情况。

于是,今天依样画葫芦写了一个helloworld的模块。代码如下:

hello.c

[coolcode lang=”cpp”]
#include “linux/init.h”
#include “linux/module.h”
MODULE_LICENSE(“GPL”);
static int hello_init(void)
{
printk(“Hello,world!n”);
return 0;
}
static void hello_exit(void)
{
printk(“Good Bye!Exit!n”);
}
module_init(hello_init);
module_exit(hello_exit);
[/coolcode]

Makefile:
[coolcode]
obj-m += hello.o
default:
make -C /usr/src/linux SUBDIRS=$(PWD) modules
clean:
rm -f .*.cmd *.mod.c *.o *.ko -r .tmp*
[/coolcode]
很奇怪的Makefile,不是吗?当然,这个是2.6内核专用的。
更奇怪的是,我make的时候出了好多错:

make -C /lib/modules/2.6.8-2-686-smp/build/ SUBDIRS=/home/marvel/programming/module modules
make[1]: Entering directory `/usr/src/kernel-source-2.6.8′
CC [M] /home/marvel/programming/module/hello.o
In file included from include/linux/init.h:4,
from /home/marvel/programming/module/hello.c:1:
include/linux/config.h:4:28: error: linux/autoconf.h: 没有那个文件或目录
In file included from include/linux/module.h:10,
from /home/marvel/programming/module/hello.c:2:

没有找到autoconf.h,这个可是源码包,怎么会少文件呢?郁闷……

尝试直接gcc -c hello.c,错误更多:

In file included from /usr/include/linux/sched.h:12,
from /usr/include/linux/module.h:10,
from hello.c:2:
/usr/include/linux/jiffies.h:84: error: syntax error before ‘jiffies_64’
/usr/include/linux/jiffies.h:88: error: syntax error before ‘get_jiffies_64’
/usr/include/linux/jiffies.h: In function ‘timespec_to_jiffies’:
/usr/include/linux/jiffies.h:320: error: called object ‘u64’ is not a function
/usr/include/linux/jiffies.h:320: error: called object ‘u64’ is not a function
/usr/include/linux/jiffies.h:320: error: ‘NSEC_PER_SEC’ undeclared (first use in this function)
/usr/include/linux/jiffies.h:320: error: (Each undeclared identifier is reported only once
/usr/include/linux/jiffies.h:320: error: for each function it appears in.)
/usr/include/linux/jiffies.h:321: error: called object ‘u64’ is not a function
/usr/include/linux/jiffies.h:321: error: called object ‘u64’ is not a function

Linuxsir上寻找帮助无果,只能自己动手。先从/usr/include/linux/下复制一个autoconf.h文件过来,然后将asm-i386建立一个asm的链接(其实那一堆错误还有没有找到asm/下的文件)。这样似乎大体可以了,但是最后说什么缺少script/basic/下的一个可执行文件。很明显了,这个文件需要在编译内核的时候生成。

不管怎么样,先重新编译一个内核试一试。没想到编译到一半,make居然成功了。 :)

后来分析了一下 ,我认为原因是这样的。#include的init.h文件就在/usr/src/linux/include/linux目录下,但是这个目录开始的时候没有autoconf.h这个文件,它应该是在编译之前自动生成的,而asm也是自动建立的。至于那个可执行文件,当然是编译中间生成的啦。

事实上,这些文件是在make  [menu|x]config 的时候生成的。理论上内核2.6有结构树,所以不需要编译整个内核,当然你可以试一试编译内核,之后make-kpkg clean就可以了。

vi的自动补足

世界上能说出vi好处的人很多,但是能说出vi全部好处的人,除了vi的作者,我想会很少很少。

以前,开始用vi的时候,总觉得不习惯。一个绝大多数时间内只能用键盘完成所有操作的工具,在现在眼花缭乱的IDE中的确很不起眼。用vi好像被一下子打到了石器时代,用起了dos的edit。

渐渐的,我不这样想了。就像不认为shell脚本是dos的bat一样。我很努力的看完了vi的manual。收获真的很大。渐渐的,vi成了我的默认editor,以至现在我还不会用emacs,有点对不起RMS了:(

终于,我认为vi已经了解得差不多了。就在前几天,我才知道我是多么的肤浅。vi绝对不是editor这么简单(即便是editor,它至少也是很强的),用过vi的latex插件,你就知道,原来vi还能作为compilier!

当然今天有点扯远了,来说说vi的自动补足功能吧。以前在用dw、dot net的IDE时,十分羡慕它们的自动补足功能,可以说这一项节约了程序员很多的开发时间,提高了效率。但是我却不知道,vi也有这项功能。

拿一个简单的hello.c来说:

[coolcode lang=”cpp”] #include “stdio.h”
int main(void)
{
printf(“Hello world!n”);
….
}
[/coolcode]

就在这里,如果你输入了printf这句话之后,在第二行开始的时候输入“p”,紧接着,键入Ctrl+P 。这时会出现什么?

是的,vi帮你自动补全了printf。再试一试H ,Ctrl+P,出来了Hello!试一试输入sca,在按Ctrl+P,会不会出现scanf呢? 很有可能。那么vi是如何实现自动补足的功能的呢?事实上,vi搜索一些文件,匹配你的词语。他的搜索顺序是:

1 本文件
2 其他窗口的文件
3 上传缓冲区中的文件
4 当前tag表
5 当前文件中所有的include文件

这样vi就实现了自动匹配的功能。

无心插柳

突然发现我的windows客户端也可以支持所有的wordpress.只不过刚才我写的只是支持每天一帖.本来就是嘛,谁没事不停地写呢?

但是俱乐部就不同了,可能不少人一起写,一天会有很多文章,所以需要实现这个功能.只不过”一个”变成”一组”实现起来有点麻烦.我想了半天,最好的方式就是使用链表的方式全部串起来.终于搞定!

呵呵. 俱乐部的sandbox现在我这里能正常显示了,一个页面可以显示好多blog了.