niyue

Archive for the ‘programming’ Category

编码问题释疑

In otherprogramming on 9月 23, 2006 at 9:08 下午

生活在中国的程序员恐怕没有不会碰到这个问题的–编码问题. unicode, utf-8, GBK, charset, encoding, code page这么一大堆术语加缩写,让人一看到就头晕,根本搞不清哪个是哪个. 各种各样的地方都会出现编码问题–数据库, JSP, mp3标签等等等等,不一而足. 我自己就花了不少时间解决编码的问题(还曾经写了一个很粗糙的Firefox的扩展来修正网页的编码),但面对这么多的术语,再加上平时解决问题时间有限,一般都是找了个方法摆脱了乱码问题之后就再也不想去看这个玩意了。今天本来是想比较一下python和ruby两个语言的,结果从ruby对unicode的支持问题开始,又回到了编码问题上来,终于决定把这些东西搞个清楚。

不过相关术语是在太多了,我建议大家先去看Unicode的词汇表,有什么疑问的词就可以在这个表里面search一下,一般可以立即得到一个清晰准确的解释,我主要结合wikipedia上对unicode的注释(unaccessible for some well-known reason)和unicode的这个词汇表讲几个最常碰到的词语和几个最大的疑惑。
confusing question:
Q: 编码到底是怎么一回事(-_-超级大问题,就解决这一个了决定)?
A: 历史上,编码问题最初是不存在的或者说不是什么大问题(很明显的,计算机发展初期只有英文使用者),字符集和字符编码是不区分的,统一用charset这个词来表示,同时兼了这两个词的含义.到了现代,编码这个问题被解耦成为几个部分:

1. what characters are available
2. their numbering
3. how those numbers are encoded as a series of “code units”
4. how those units are encoded as a stream of octets (bytes)

部分1指的就是字符集,表示可用的所有的字符,包括数字,字母,标点,汉字等等.
部分2指的是编码字符集(这里用英文可能更准确一些coded character set,被编码了的字符集),也即部分1中的每个字符会映射到一个或多个数字或者其他符号,由这些符号来代表部分1中的字符.
部分3和4指的是如何将2中映射得到的数字最终表示为计算机可以识别的二进制串(3,4拆分为两步的主要原因于计算机对字节流的解释有关big-endian or little-endian,不考虑的话应该可以合并).
从这四个部分可以看出,解决编码问题需要定义字符集,定义映射方案,定义编码方案这几个重要步骤.

Q: Unicode又是怎么一回事,它和utf-8有什么关系?
A: Unicode和另外一个与之并列的标准ISO 10646共同组成了一个上面提到的解决编码问题的解决方案,它不是四个部分中的任何一个,而是这四个部分各自解决方案的一个组合.其中字符集是由ISO 10646定义的,numbering应该在Unicode的标准中有(?^_^我也没看过,不确定).utf-8是Unicode提供的用于解决编码子问题的方案之一,同时还有utf-16和utf-32等等编码方案.

Q: code page呢?
A: code page就是coded character set,最初是IBM使用的一个术语,后来微软也大量使用.

这就是我的demystifying encoding problem, 如有不当请指教.
http://www.niyue.com

参考文献:
[1] Glossary of Unicode Terms http://www.unicode.org/glossary/
[2] Unicode in Wikipedia http://en.wikipedia.org/wiki/Unicode
[3] Character encoding in Wikipedia http://en.wikipedia.org/wiki/Character_encoding

static关键字的含义

In programming on 9月 23, 2006 at 3:23 下午

在许多编程语言里面都可以见到static这个关键字,虽然很常见,但是对于它的具体含义我却一直不是很了解,为什么这个要叫做static而不是其他?比如在C,C++,Java,C#里面都有这个关键字,说明这个关键字的字面意思应该是能够表明它的含义的(否则不会这么巧大家都用这个关键字),但是这个关键字的含义又不是那么简单可以望文生义,今天自己花了一些时间看了看,有了个相对清晰的了解.

这个Q&A(What does the keyword ‘static’ mean?)是我最开始找到的资料,问的问题是我想问的,但是答案确不是.

The static keyword denotes that a member variable, or method, can be accessed without requiring an instantiation of the class to which it belongs.

它说明了static关键字所表示的结果含义,但是没有说明为什么代表这个含义使用了static这个关键字.而这个含义其实是有一定编程经验的人都知道的,大家都这么用,但是不知道为什么这个是叫static而不是其他的.
我又继续看了一些资料(参见下面的参考文献),自己总结了一下:

  1. static这个关键字想要表达的是变量或者方法等的生命周期,而不是访问的作用域的控制,这可以和public,private(Java等语言)这些关键字区分开来.
  2. static这个关键字的字面含义”静态”说明了由static声明的变量或者函数等的生命周期控制信息的存放地点–静态数据存储区域.

接下来我详细的解释这两点:

  1. static声明的往往是一个用做全局的变量,类实例等.这个”全局”主要说的是通过static声明,声明的变量等可以增大其生命周期到某个全局的范围,比如Java类里面声明了一个static的变量,则它的生命周期和这个类相同–贯穿程序运行的全过程.因为不会消亡,所以你在引用这一static变量的时候只会引用到同一个变量,看起来就是一个类级别的变量(从结果看起来这样理解也可以,类似与Ruby中的@@来声明变量,但这样很容易知其然而不知所以然).在c语言中并没有类的概念,因此这种说法就不大行得通.在c语言中声明了一个static的变量之后,这一变量的生命周期就可以跨越声明它的文件中的所有函数,当然,这个时候的含义可能也包括了访问控制的含义在里面,但是我理解更主要的还是生命周期的改变.
  2. 生命周期控制数据的存放地点.要理解这一点,首先要知道有哪些地方可以用来存储程序中使用的数据.对于这一点,文献[1][2]讲述的很清楚,大家可以参考,我就不重复了.主要讲一下随机存储器RAM中的三种存储方式栈,堆,静态存储(stack,heap,static storage).看到这里,大家应该都知道由static声明的话,生命周期相关的信息会存在哪里了吧,至于static这个名字是怎么来的,也不用多说了.对Java来说,
    1. 一般的不是由static声明的变量,如果是原始的数据类型,会直接保存在stack上,如果是通过new得到的对象实例,这一对象的引用会保存在堆栈上,其实际的数据会保存在heap上,如果这一变量相关的数据被pop出栈,那么这一变量的生命周期也就结束了.如果是对象的话,其在堆上的对应内存也会被释放,这以后就再也无法访问这一对象了.
    2. 如果是由static声明的变量,不是在stack上存放引用等信息,而是在静态存储区域存放,这样即使堆栈内容变化也不会影响这些变量的创建或者消亡,从而可以不实例化一个类直接通过静态存储区域找到这一变量使用.

这些就是我的一个小结,有部分是我自己的理解,可能不是很正确,请大家指教.

Update: 文献[9]是一篇写的很好的文章,我对static声明函数的含义可能有些曲解,大家可以参考文献[9]最后的static函数及其扩展分析.

参考文献:

  1. 对象保存在哪里? http://www.qsl.net/bd5hag/JavaCourse/Lesson2/2_9_1.htm
  2. c storage class http://www.phim.unibe.ch/comp_doc/c_manual/C/SYNTAX/storage_class.html#static
  3. Static Variable in Wikipedia http://en.wikipedia.org/wiki/Static_variable
  4. Local Variable in Wikipedia http://en.wikipedia.org/wiki/Local_variable
  5. Call Stack in Wikipedia http://en.wikipedia.org/wiki/Call_stack
  6. this and static keyword, Thinking in Java http://columnist.chinabyte.com/xufeng.cq/149/2183649.shtml
  7. 小议static http://www.csdn.net/develop/Article/20/20219.shtm
  8. What does the keyword ‘static’ mean? http://www.javacoffeebreak.com/faq/faq0010.html
  9. static关键字Q/A http://home.zhuonline.net/archives/2005/09/staticqa.html

标识关系与非标识关系的区别

In programming on 8月 29, 2006 at 11:54 上午

最近在用Rose画数据库的数据模型设计图,画出来的不是ER图,但是和ER图比较相近。不过里面有两个概念一直没搞懂,identifying/non-identifying relationship,仔细查了一下,有不少介绍这个知识的文章。

从结果来看的话,identifying关系中的子表必须将父表的外键作为主键,而non-identifying则不必。

Vim extremely boosts my productivity!!!

In learningprogramming on 7月 26, 2006 at 3:53 下午

使用Vim大概半年时间了,终于可以算走过了Vim最陡峭的那段学习曲线,现在越来越感觉到它的效率了.今天使用vim完成的一个工作真正体现了这一点。

这次的工作是要比较两个列表中的人名,看列表一中的人名是否在列表二中,每个人名占了一行。如果用一般的编辑器可就麻烦了,只能用鼠标选中列表一中的某一行,然后Ctrl+C,然后Ctrl+F,然后Ctrl+V,然后Enter查找是不是有相同的字符串在第二个列表中也有出现。第一个列表一共大概有80个人,都要这样来一遍可是非常痛苦的一件事情。于是Google了一下找到了一个vim approach来完成,效率和准确率都提高了不少。我是这样做的:

  1. normal mode: q a
  2. 0 v $ h y j
  3. :%s/Ctrl+R  “/&/g Enter
  4. q

以后查找每一行只要按@a就可以知道在列表二里面是不是有相同的人,如果有会高亮显示并且跳到列表二的这个人名,再按一次n又回回到列表一,没有比这个更方便的更好的效果了:-)

不过要克服前面的这个学习曲线可是很累人的一件事情,不过相信vim会给你带来回报的~

learning curve

Painting in AWT and Swing

In javaprogramming on 7月 23, 2006 at 10:24 下午

Java在desktop端好像一直没有得到过很大的应用,据说Mustang会在此做出很大的提高,不过不知道什么时候才可以正式release.最近想写一个Swing的程序,发现从server端换到desktop端写的东西还是有很大不同,尤其是Swing里面的painting实在是让人很疑惑–看不大懂那些API应该怎么组合才能正确的使用.网上search到的东西又都是很早的时候的东西(很多都是AWT的,在后来大家都发现java在desktop没前途转到server side去了).
找了一些tutorial和code eg是五花八门,在painting的时候就会用到好几个方法:

public void paint(Graphics g)
public void update(Graphics g)
public void repaint() 
protected void paintComponent(Graphics g)

到底overwrite哪些方法,其间又有什么不同呢,实在是很复杂的问题,好容易在sun的网站上面找到一篇文章,很全面的介绍了AWT和Swing中painting的机制,把这些问题都讲清楚了,可以参考一下.

使用Excel作为用户接口

In otherprogramming on 2月 14, 2006 at 5:17 上午

看到了不少使用Excel作为用户接口的例子,感觉是一个不错的方法,可以先看看Dion Almaer文章

  1. Interface Excel { @MaybeEasiest businessGuyDoit(); }
  2. Abusing the Semantic Web
  3. DDSteps
  4. Feedlists in Spreadsheet?
  5. Clean handoff, Collaboration and Pluggable Process Constructs(BPM分析中使用SpreadSheet作为用户接口,Update at 2006-7-26)

趣文两篇

In otherprogramming on 1月 26, 2006 at 4:34 下午

今天看了两篇很有意思的文章,都是用通俗易懂的文字介绍技术内容的,both worth reading~

  1. [翻译].NET委托:一个C#睡前故事
  2. Oracle是如何工作的

编写Firefox扩展

In learningprogramming on 1月 20, 2006 at 4:25 下午

最近想写一个Firefox的扩展用来自动的改变网站的编码,开始的时候想使用GreaseMonkey来做这件事情,似乎容易一些,但是稍微看了一些资料感觉可能无法实现,只能直接写一个Firefox的扩展来做这个事情了。

搜集的一些编写Firefox扩展的资料:

  1. How to write Firefox extensions using BugMeNot as an example
  2. How to create Firefox extensions中文翻译:如何创建Firefox扩展
  3. Writing an Extension for Firefox
  4. Firefox Extension Tutorial
  5. Extension development
  6. Building an Extension

碰到的最困难的Bug

In programming on 12月 28, 2005 at 2:34 下午

要是以前问我programming以来碰到的最困难的bug,我可能一下回答不出,但是今天碰到了一个bug,解决之后回想一下,发现最困难的就是这类的bug-与时间相关的数据问题。这类问题由于和数据计算的时间有联系,导致了这类问题发生的上下文往往无法重现,根本没有办法进行调试。

这次碰到的问题是企业生产系统中计算的外购数量发生错误。外购数量根据订单订购数量以及企业当时该种货物的库存计算得到的,也即与特定的时间点相关。生成的外购数量中部分正确,部分有问题,由于将所有数据恢复到当时情况进行重新计算与调试,很难有地方可以入手查找问题的根源(当然,这里也可能是因为我们的日志做的还不够好)。程序代码检查了没有发现问题,直接查数据库中的数据也没有办法得到答案,后来碰巧发现两张出错订单的制单日期均是在20日之前,于是猜想20日之前的那个版本中程序有问题,但是现在已经解决。但是这一猜想也无法证实,因为正确的版本的发布时间已经想不起来了。终于通过FTP上的文件(文件中包括了发布时间,15日和20日均发布了一个版本)以及JIRA中对于这一bug的记录(记录日期为15日,解决日期为17日),确定了正确的版本肯定是在17日之后发布的,也即20日发布,在20日之前的数据都存在问题,但是20日之后的数据均正确。

解决这一bug一共查找了系统源码,db数据,ftp发布文件,jira中bug记录等四处的信息才定位到问题原因所在。和做数学题一样,其实题目并没有超纲,只是多拐了几个弯的话做起来就很难了。而这里会需要多拐弯的原因正是在于时间信息无法重现,只能通过多个信息源共同来确定问题的可能原因。

基本上没有什么办法能够避免此类问题的发生,唯一的比较好的解决办法是在系统中进行完善的日志记录,保证能够捕获系统中大多数时间点上发生的事件情况,从而能够较好的重现bug发生时的现场使得bug能够快速定位。

xsl输出注释

In programming on 9月 1, 2005 at 1:27 下午

使用<xsl:comment/>标记可以输出注释。参见:

翻译稿:XSLT,注释和处理指令