Archive for the ‘Programming’ Category

根据EXIF日期信息整理照片
Sunday, September 28th, 2008

一般相机拍下来的照片都是JPEG格式,文件头部有一块专门用来存储EXIF信息,包括光圈、快门、焦距等,还有拍摄照片时的日期。

用ruby写一个这样的程序非常简单:

require 'exifr'
require 'ftools'

unorganized_dir = 'e:\\flickr-photo\\unorganized\\'
root_dir = 'e:\\flickr-photo\\'
Dir.chdir(unorganized_dir)
Dir.glob('*.jpg') { |filename|
	exif_info = EXIFR::JPEG.new(filename)
	date_time = exif_info.date_time
	unless date_time.nil?
		target_dir = File.join(root_dir, date_time.year.to_s, "%02d" % date_time.month)
		File.makedirs(target_dir)
		File.move(filename, target_dir)
	end
}

我在E盘的flickr-photo目录下存放组织有序的照片,第一层子目录是年,2006,2007,2008……第二层子目录是月,01,02,03……把未组织的照片放在unorganized目录里,在命令行里执行ruby organize.rb,就把这些照片各自移动到合适的月份目录下了,不存在的目录会自动创建。

当然你需要修改这个程序,把unorganized_dir和root_dir设置成你自己的目录。另外需要先执行gem install exifr命令来安装exifr这个library.

也有个别的照片(或者图片)是没有携带exif信息的,程序不会对它们进行处理,执行完后,这些照片留在原地不动。我把它们移动到一个叫”no-exif”的文件夹中。

差点忘记,首先,请把你的相机时间设置正确! :)

这是我的第一个ruby程序……虽然简单,但很实用,帮我把从flickr备份回来的图片分好了目录。

自己做个花生壳(动态IP解析)
Sunday, September 21st, 2008

花生壳动态域名解析曾经风靡一时,把域名指向某台随时改变IP的机器。我从来没用过花生壳,不过大致也明白它的基本道理,自己也时常遇到需要访问某动态IP机器的问题,其实可以用很简单的方式来实现类似的功能。

现在有许多专门做查询IP的网站,一个基本功能就是你一上去马上就可以看到自己的IP. 嗯,一般情况下你访问网站时对方就会获知你的IP地址。

实现这个功能,只要在外网有一个固定IP的服务器(或者共享空间)就可以了。比如说,我的网站有个子目录叫”ip”. 第一步,我想在访问http://qingbo.org/ip/的时候,显示出我家计算机的IP地址。

  1. 在ip子目录里放一个ip.php文件,内容如下:

    <?php
            $file = fopen("index.html",'w');
            fwrite($file, $_SERVER["REMOTE_ADDR"]);
            fclose($file);
    ?>
    

  2. 在家里的计算机上访问http://qingbo.org/ip/ip.php
  3. 不论我在哪里,打开地址”http://qingbo.org/ip/”都可以看到家里的IP了。因为访问ip.php的时候,它把IP写入了index.html文件。

这样有几个问题存在。首先,家里用的是ADSL(其它的网络提供商大部分也都如此),IP地址是不定期变化的,总不能家里老是放个人不停上网吧 :) 其次,如果别人在别的地方访问ip.php,这不是捣乱吗?这个捣蛋鬼的IP会被记录下来,而家里的IP则不见了。最后,我们想访问http://qingbo.org/ip/的时候,直接转到家里的服务器去浏览网页(这是一台不太正规的web server)。

第一个可以用cron来解决,让它定期自动执行。执行命令”crontab -e”,然后加入这一行:

0 * * * * wget -q -O /dev/null http://qingbo.org/ip/ip.php

Windows应该可以用计划任务,不过我没有试过。

第二个,应该加个认证码(相当于密码)。只要在ip.php里记录IP的时候加一个判断:

if ($_POST["code"] === "strongauthenticationcode") {
   ...
}
?>

这样,只有提供了正确的认证码,IP才会被记录下来,防止别人瞎捣乱。(这是cron task的最终版本

0 * * * * wget -q -O /dev/null –post-data ‘code=strongauthenticationcode’ http://qingbo.org/ip/ip.php

第三个问题,只要把写入index.html的内容改一下,让它作自动转向就可以了(最终版本):

<?php
if ($_POST["quqi"] === "_-5QzdkhxNnI5EOM6ucW") {
        $file = fopen("index.html",'w');
        fwrite($file, '<html><head><title>Redirecting...</title><meta http-equiv="refresh" content="1;url=http://'
. $_SERVER["REMOTE_ADDR"]
. '/"></head><body>You have crossed the oceans of time, to find me.</body></html>');
        fclose($file);
}
?>

现在一般的家庭网络都是由一台路由器自动拨号,这样的话,内网有一台机器不停访问外网服务器的IP记录程序就可以了,不一定非得是要做服务器的那台机器。当然了,路由器上要设置好NAT,好让外部可以访问到内部的服务器。

写该文的时候手头没有合适的测试环境,所以文中可能有些错误 :) 希望能帮助大家,也希望给我指出错误。

为什么要懂他妈的英文
Friday, August 15th, 2008

这种话题应该在许多地方争论过。从我个人认为,中文确实适合风花雪月,赋诗作词,但在表达技术方面,却非常繁琐,并有太多歧义。

前阵子招人,出笔试题。我没有经验,公司的大姐给了我点题做参考。我看了一下,似乎是SCJP那种弱智又变态的题,就是给你拐弯抹角设陷阱,捉弄你。题目是英文的,于是我一想,为什么不能呢?顺便考察一下英文水平。

题目只从中取了一两个,其余的题目都是自己弄出来一些超级简单,只要能看懂的计算机本科毕业生就会做的,甚至用到的一些API都会列一个表格在那里。招聘启事里写着计算机相关专业本科以上,后来甚至标明了笔试题为英文。

结果来的大部分人都觉得英文很吃力。有一天一个家伙看了看题目就走了,临走愤愤地说,“我觉得这样的题目测试不出优秀的程序员”。老兄,我们不需要优秀的,你能看懂他妈的英文就可以了。

这英文绝对没有GRE那么变态的单词,也没有英语文学的修辞方法。仅仅是一些计算机的术语而已,计算机专业的本科生啊!

虽然没有准确的数据,但我相信绝大部分的计算机技术在第一时间是以英文表达出来的。之后不知道要过多长时间,才会出现中文的翻译。

这个时间差实际上并不重要。最要命的是,你能看得懂那些翻译吗?没错,中文翻译,看不懂。不知道多少经典书籍被一群垃圾给糟蹋了,这些垃圾包括一些所谓的大学教授。他们自己不去翻译,或者可能也没有能力翻译,所以让手下的廉价劳动力去做。这种人可耻,一方面因为剥削可怜的劳动力来制造利润,另一方面不考虑质量,不尊重学术。翻译的第一要素应该是“信”,但是译者自己都看不懂原著,怎么可能做到“信”呢?翻译技术文献不是翻译文学作品,译者需要相当深厚的专业背景。当然不能全盘否定,还是有一批优秀的译著的。

除了翻译一些国内急需的名著,中国人还很热衷于为开源软件进行翻译。所以中国的开发者对于开源社区的最大贡献就是翻译。当然我没有做过贡献,没有资格批评。

除了那些蹩脚的翻译,中文的网络资源质量也很让人郁闷。不到万不得已,我从不使用百度解决技术问题。不出意外的话,百度搜索会给出连续几页完全相同的结果,你甚至不知道哪个才是“原创”,所谓“天下文章一大抄”。而且大部分的资料缺乏权威性,我更希望得到官方的文档或教程。有时候你用了几年的一种技术最后发现是错的,就觉得被欺骗的太狠了。使用Google,把浏览器首选语言设置为英文,一般会找到最权威的解答。当然,要学会选择关键字。

如果程序设计语言是中文,如果技术文献在国际上主要以中文表达,我不会去学他妈的英文。别提什么易语言,汉语编程。汉语编程纯粹是个骗局,欺骗那些愚昧无知的弱智。

计算机英语之外,如果你能读懂更多,就去看看BBC之类媒体。有些人不分青红皂白,是中国的就全盘否定,是外国的就大肆追捧。你多去看看国外的以这些媒体为首的反华(反华,anti-Chinese)势力是多么变态,看看中国人在国外是什么待遇,看看外国人在中国又是他妈的什么待遇。

用pinyin4j将汉字转化为拼音
Friday, July 25th, 2008

在合肥的时候,靠骗钱维生的电脑学校很多,而且确实骗到了许多钱,于是形成了良性循环,在电视上打广告,骗更多的钱。有个广告的末尾就是一憨厚的老大爷高兴地说:只有正规,才有机会啊!

某些情况下这句话很对。那些在网上被到处转贴的代码片段,我就不敢信赖,而且格式很乱也看不清楚。在找汉字转拼音程序的时候,我还是选择了pinyin4j,Source Forge上的项目,相对值得信赖。哦对了,这是Java的library.

一个简单的实例方法,使用pinyin4j转换字符串中的汉字为拼音:

public static String toPinyin(String input) {
	StringBuilder sb = new StringBuilder();
	for (int i = 0; i < input.length(); i++) {
		char c = input.charAt(i);
		if (c <= 255) {
			sb.append(c);
		} else {
			String pinyin = null;
			try {
				String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, PINYIN_FORMAT);
				pinyin = pinyinArray[0];
			} catch (BadHanyuPinyinOutputFormatCombination e) {
				logger.error(e.getMessage(), e);
			} catch (NullPointerException e) {
				// 如果是日文,可能抛出该异常
			}
			if (pinyin != null) {
				sb.append(pinyin);
			}
		}
	}
	return sb.toString();
}

其中用到的常量PINYIN_FORMAT是这样初始化的(输出时去除声调标记,发音“驴”的那个韵母用v表示):

PINYIN_FORMAT = new HanyuPinyinOutputFormat();
PINYIN_FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
PINYIN_FORMAT.setVCharType(HanyuPinyinVCharType.WITH_V);

因为汉字有多音字,所以PinyinHelper.toHanyuPinyinStringArray返回一个数组。这个方法图省事,就直接选择了第一个读音。如果可能的话,可以将遇到这种多音字的地方提出来,人工进行处理。

为什么用Eclipse而不是NetBeans
Wednesday, July 23rd, 2008

在当下这个项目开始的时候,我们尝试使用NetBeans作为开发工具。也许是由于之前一直在用Eclipse,先入为主了,我总是发现NetBeans在一些地方似乎有先天的不足。于是在一周后,项目移到了Eclipse中进行开发,到现在依然在为没有太晚做这个决定而庆幸。

先从表面现象来比较。Eclipse的图形界面是SWT,而NetBeans作为Sun的产品,当然不好意思不用Swing了,于是给人第一印象就不好。某些系统上,dockable的窗口标题字体与标题栏高度明显不符,很不协调。输入中文时,候选窗也不能跟随光标移动——现在的Web开发一般都使用大屏幕显示器,你需要不时地看看屏幕的角落。别人可能会觉得奇怪——你有什么急事吧?要不然怎么不停地看时间呢?

在Eclipse中我习惯打开一个资源管理器窗口,从中复制一些文件,然后切换到Eclipse窗口直接粘贴到Package Explorer合适的目录。这一习惯在NetBeans里行不通,只能在IDE内部复制、粘贴。

然后透过现象看看本质。在NetBeans选中一个文件,按F2,你就发现,文件后缀是不能修改的!如果你想把一个.jspf改为.jsp,只能在资源管理器中做。看来NetBeans的理念就是傻瓜——比Windows还要傻瓜。

SVN集成。NetBeans默认集成了SVN,乍一听很让人兴奋。确实,当我看到单个文件中都有图形化的svn diff的时候,兴奋地跑到隔壁去找人倾诉。不过等到commit的时候我就开始沮丧了,完全没有subclipse方便、直观(subclipse 1.4不好,到现在我仍然在用1.2)。

最让人郁闷的是,J2EE项目中,在资源管理器里新加一个文件,在NetBeans刷新出来,部署时仍然会被忽略掉!仔细想想才明白,原来是要执行svn add才可以……合理乎?不合理乎?这svn集成,用一个词来形容就是“天衣无缝”。Web application部署都考虑到svn了,真是周到,佩服,佩服。

NetBeans的项目配置文件太过复杂,不适合作代码管理。nbproject下一堆文件,大部分是ant build file. 如果有library引用,肯定是绝对路径。在Eclipse里,即使有定制classpath,只要手动改成相对目录就一劳永逸了,svn co到任何地方都直接打开没有任何问题。NetBeans可不一般,改成相对目录可以,只要再新加入一个jar包,已改为相对目录的还会变成原来的绝对路径。

这不由得让人怀疑,NetBeans傻瓜吗?不,它很强大,很灵活,要不然配置文件怎么会一大坨。那这么复杂的配置文件,svn怎么管理啊?哦……svn集成很完美——web app部署都会考虑到代码管理。

x坐标一端是傻瓜,一端是灵活;y坐标一端是天衣无缝的svn集成,一端是复杂到天衣无缝的svn集成都无能为力的配置文件。天才的NetBeans在这个二维空间里找到了那个独一无二的完美的点,就像宇宙中只有一个地球一样。我错了,我是火星人。

Refactoring. Refactor - Encapsulate field,没有全选、取消全选的按钮。同时已有getter/setter的方法没有体现出来,但是你硬要选上的话,它又会抛出exception.

Refactor - Rename,没有同时重命名getter/setter的选项。

从某种程度上说,NetBeans很像MS的产品——大部分用户做傻瓜,小部分人是精英,为傻瓜们解决不应该是问题的问题。我做不了精英,却不想做傻瓜,于是还有一条路——我逃了。

嘿嘿,有许多人推崇NetBeans。确实,NetBeans某些方面比Eclipse做得好,比如上面提到的文件内svn diff,还有对于web开发很重要的——更好的JavaScript编辑器、HTML编辑器。还有其它的我还没来得及发现就放弃了。本文也就是发发牢骚,顺带给想比较这二者的同仁们抛砖引玉。

org.apache.commons.lang.StringUtils 字符串处理
Saturday, June 28th, 2008

许多开发人员在做项目时都习惯把一些实用方法做成通用的静态方法,放在一起使用,例如对字符串的处理。有些实际编码中十分常用的方法却没有在Java的String类中提供。实际上Apache的commons子项目的lang包就是帮我们解决这个问题的,比如org.apache.commons.lang.StringUtils这个字符串处理的类。

在发现它之前我自己已经有了一个StringUtil类,而粗略看了几眼它的文档,我的所有方法都在org.apache.commons.lang.StringUtils类中都有,并且考虑得更加周全。

例如split方法,在Java中,用逗号分隔一个字符串”a,,b,c,”,结果是一个长度为5的数组:

["a", "", "b", "c", ""]

而大部分情况下,那些空字符串是不想要的,于是在循环中我们就需要一一判断字符串是不是空的。StringUtils.split方法就帮我们按照这种思路来分割字符串。

许多开发人员抱怨Java没有提供一个join方法,StringUtils.join解决了这个问题。

你怎么判断用户的输入是不是空?如果做完整的验证,应该是:

if (input != null && input.trim().length > 0) {…}

StringUtils.isBlank方法为我们做这样的判断,它会正确处理null和全部空格的情况。

StringUtils类还有许多其它的实用方法,可以适应我们日常编程中的大部分字符串处理。另外commons-lang还提供了一个StringEscapeUtils类,可以帮助你防止SQL injection,在HTML中正常输出用户输入的尖括号等。

虽然我没有仔细看过源代码,不过作为通用的方法,commons-lang对性能的考虑应该比较周到,这一点可以放心。

J2EE vs. ASP.NET
Saturday, May 17th, 2008

Perhaps the worst thing Sun has done in the history of the J2EE is produce the Java Pet Store and advance it as an example of best practices for J2EE. The Pet Store is bloated, inefficient and has given Microsoft a perfect target to attack J2EE.

Rod Johnson是这样说的。

文中接下来就是讲他对.NET(主要是ASP.NET)的看法,相信大多数程序员都会认可。其中包括MS“跨语言”的天才构想。他也认为束缚在MS的平台上是个大问题。

C#也好,ASP.NET也好,很大程度上都是把JAVA的那一套弄过来,改几个名字,更换或强加几个概念。然后通过Windows的广大盗版市场推广出去,得到××电脑学校及其学员的追捧,成为炙手可热的主流技术。当然了,C#/ASP.NET还是有些创新或优点的,使用它们的程序员也有一部分很优秀(圣人也有错嘛)。

JavaScript
Wednesday, December 26th, 2007

“用”了这么久的JavaScript,却始终对这个语言有一种很陌生的感觉。Prototypescript.aculo.us一直在用,可是它们的源代码,说实在的,我看不大懂。JavaScript非常灵活,也使得它比较难以掌握。另外由于各种浏览器实现之间的差异,使得它显得更加混乱,所以在最开始接触JavaScript的时候,我就困惑,在哪里找到一个比较权威的reference呢?

如今JavaScript的代码写了应该有上万行了,不过大部分都是借助于Prototype和script.aculo.us以及其它的一些library,而且我自己感觉,事情是做成了,代码还有很大的提升空间。以后准备抽出一定时间来,把JavaScript的基础补一下,争取在面对任何JavaScript代码的时候,都像C++、Java一样,知其然,且知其所以然。比如:this到底指的是什么?

从哪里开始?当然是MDC.