又见离职

趁着Android SDK正在更新的时候,写点东西。今天偶尔听到领导要离职了,其实之前已经知晓他提交辞呈了,不过由于公司办离职手续一向效率非常的低(我舍友之前离职就花了整一个月的时间),一直以为至少也得等到这个月末吧,殊不知同事今天就提出了请一周假的请求了。也许是之前找工作中发现目前自己所掌握的技能在外面的公司并不是那么的通用吧(我们是做JNI开发的,主要工作是负责封装C++类库),他说前面有几个面试,有些比较顺利,但是自己并不是非常想去,有一个自己比较向往的,但是面试并不顺利。也许是认识到了找工作需要认真对待,花些时间再充下电吧,也许从明天开始我就再也见不到这个几乎每天都在指导我的领导了。说来有些伤感,不过世事无常,谁又能说自己不会走呢?谁又能说自己什么时候走呢?

入职至今,已经历经了4位同事的离职了,两位曾是我的指导人,或者说三位,一位是我的大学舍友(迄今依然是舍友)。同事的离职俨然已经不再是一件新鲜事了,可是为何还是心中稍有不爽呢。细细想来,这些人都曾经在我的职业发展路上给了我很多的帮助,他们都曾是我学习的对象,如今已经三三两两地离开了,心中难免有些不快。不过最后回到大家离职的根源上来说,可能对自己的触动会更大一些。也许有的人离职仅仅就是想离开,譬如我的舍友,离开就是为了离开,待遇并不是首要的,主要是对GIS这个行业了无兴趣,全然没有投身伟大的国产GIS软件行业,为之奉献终身的热情。但是回到最通常的原因上,我想最大的原因还是薪资待遇的问题。

  • 最早离开的同事,是我江西老乡。曾经在我实习的时候,多次跟我沟通,如果能找到更好的公司不要来这里,这里的饭并不好吃而且很有可能让你饿着。离职去了一个GIS开发商企业。
  • 然后离开的同事,是我的直接领导和指导人。工作三年,随着一个产品和团队一起成长,最终调派到一个新产品中任主力开发之职。结婚半年,考虑到孩子将来的奶粉钱,离职去了一个游戏公司。
  • 刚刚离开的舍友,是我的挚友兼多年室友。工作半年,遂觉此处留不了爷,爷奔游戏去也,离职去了一个游戏公司。
  • 即将离开的同事,是我的直接领导和间接指导人,工作两年。顿感工作无趣,实在有种有力无处使之感,即将离职去一个我希望能让他开心的公司。

我尊重这些同事,我喜欢这些同事,不仅仅是因为他们曾经多或多或少地帮助过我,更多的是我坚信他们有自己的梦。他们能开心一些地去公司上班,每天生活能轻松一些,身体能健康一点,那就是我最高兴的事情了。我跟他们中的大部分人都非亲非故,也许他们离开了之后,我惟一能记住的就是他们的名字和手机中的联系方式(除了我那该死的舍友),工作之余偶尔的闲聊中会谈起他们,在这个偌大的城市中,偶遇的机会并不多。我惟一能做的就是祝福所有已经离开的和即将离开同事们,希望你们每天都能开开心心上班来,健健康康回家去,加班不常有,而加薪常有。

再论GIS和云计算

本周一,有幸因为团队小组领导即将离职,所以获得了一次不错的机会,可以近距离地听取一次由IBM中国云计算研究中心的三位工程师带来的关于云计算的培训式讲座。鄙人抱着很高的期望前去,和我怀着同样心态前去的人也不少,当时讲座场地是公司总部的一个会议室,不大,能容下30个人不到吧,坐满了。

开篇由一位技术工程师给我们做了一个入门级别的云计算介绍,主要集中在IBM云计算硬件和相关的虚拟化的软件。其中有介绍到云计算的一些优点,主要有以下几点吧(记录得并不是很全面)

  • 给用户提供一个一体化的体验
  • 成本的节约
  • 效率的提高
  • 安全性的提高

我们都知道云计算服务提供商一般可以为中小型企业提供非常廉价但是高性能的硬件和软件环境,企业产品的构建和部署均可以在云端进行,这在很大程度上解决了企业维护硬件和运营的成本,机房的能耗和故障往往会成为小型企业产品研发和运营中的鸡肋,而云计算服务提供商给了我们一个非常完美的Solution。IBM这样的企业又能为我们提供什么呢?IBM面向的一般都是企业级用户,也就是政府和企事业单位,这些组织机构对硬件和软件的要求一般情况下都是很大的,例如IBM在无锡给某个软件园建设的云计算平台,就是软硬件结合,进驻软件园的企业并不需要自己采购大量的服务器产品和相关的软件,而只需使用软件园中的账户登录软件园的云计算平台,根据企业项目的需求申请获取相应的硬件资源,定制操作系统和相关构建的软件等等。这极大地增强了企业的灵活性,节约了众多的维护和运维的成本,企业在项目紧张的时候可以申请更多的资源,而较为闲暇之时使用的资源大大减少,而不像传统软件企业依然需要耗费大量的人力去维护相关的软硬件资源。既然云计算能为我们这些企业级用户带来这么大的优势,为企业大大节约成本,那么云计算在GIS产业中将如何体现其价值呢?

因为目前服务式GIS还主要集中在地图出图和简单的分析上,而地图出图渲染和分析这种功能需求往往有非常强的时刻型需求,也就是说,我们可以会有需求每个小时出一次全国地区的气象云图等等,并做相关的分析得出结果。那么在这个时刻点上,系统所需要的资源就会非常之多,系统的负载就非常大,而其余的时间系统大部分资源都是闲置的。那么我们能通过云计算来解决这个问题吗?我们都知道云计算的主要优势在于海量存储与高计算能力,然而在图形显示上并没有太多的优势。而GIS出图对于系统GDI资源的消耗非常大,而系统的GDI资源往往是非常有限的,那么怎么来解决这个问题呢?IBM的小型机跑的一般都是AIX系统,显卡的性能也很一般,那么这个问题如何解决呢?当然我们可以借鉴一些电信计费和结算系统的原理来进行一个高峰时期错开的处理,由于日常生活中人们的电话通信一般时间在白天,那么白天的计费系统肯定负载非常之大,而晚上计费系统负载相对就会小很多,这个时候就可以将大部分资源调度给结算系统来进行结算。其实我们GIS的这个问题也可以这么解决,假设我们现在的系统中有非常强大的计算能力,图形渲染能力相对较差,那么我们在系统并不需要进行出图的时候,充分利用系统的计算能力生成大量的地图缓存,而在需要出图的时刻调度所有的GDI资源来进行渲染,地图缓存很显然会极大提供地图显示和出图的速度的。

那么应用点仅仅停留在此吗?恐怕不止。目前我们国家的诸多政府部门都在构建自己的系统,而这些系统中都多多少少的能看到GIS的影子,但是这些部门又不像国土局和测绘局对GIS有如此强烈的需求,他们只是在一些特殊的时候需要使用到GIS。例如卫生局,当管辖区域出现传染疾病灾情时,就非常需要依托地图数据和疾病传染的一些模型来计算出可以传染的区域,并及时对这些区域进行处理。那么卫生局愿意每一年向测绘局等等其他的组织机构购买相关数据吗?这些数据可以每年都会发生更新的哦,每年都买吗?我想很多部门是不愿意的,在需要的时候又希望能迅速获取数据,在平日里并不愿意也不需要支付高额的费用,是很多组织机构的共同需求。那么云计算就完全可以插一脚了,政府或者企业通过建立一个大型的平台,包含软硬件资源,数据生产部门可以通过提交数据来获取利润,而消费部门完全可以节省大量的软硬件维护费用,按需索取即可。当然这是一个抛开了所有体制的设想,至于市场的可能性,who knows?

你看好GIS Cloud吗?我不看好。路漫漫其修远兮,吾将上下而求索。

《读库0906》观感

年前一直盼着《读库》大礼包能及时赶到,到时候上火车的时候就背着一大包的书回南方的家,我喜欢旅行途中阅读的感觉,火车是一个选择出游旅行的绝佳交通工具,以前我非常喜欢坐大巴,而且也总是坐大巴,因为当时大学离家里比较近,大巴的交通便利性远远高于火车。当我第三次乘坐长途火车的时候(此处指超过12小时),我发现其实乘坐火车出行,快乐非常简单。我不是一个能跟火车上坐在相邻的旅客轻易聊上的人,我比较寡言,被动发言居多。乘坐火车的痛苦在于我一般在行进的列车硬座席上无法入睡,即使深夜依然如此,幸运的是我总是有非常不错的书能陪伴着我的旅程。记得一次下杭州时,带了《读库0903》在车上一路相随,当列车上诸多人开始聊天的时候,我完全沉浸在书本的世界中,当大家安静地入睡时,我开始能有时间静静地回味书中的些许精彩。

那么此次春运期间返乡过年是否也能幸运地再次背着《读库》一同前行呢?等得心中实在是搔痒难耐,给小六短信,询问了关于订单的事情,小六的答复是等年后吧。

返京后的当天就收到了读库礼包,《读库0906》作为2009年的收宫之作自然是排在了阅读的前列。时至今日,差《沿着西湖看历史》一章,已经通读一遍了。开篇姬炤华老师关于儿童图画书的讲述和见解,让我这山里娃彻底地开眼了,原来艺术真的是这么无私的,儿童也应该得到尊重。《老师》中流露出来的年代味道以及对老师的敬爱,着实让刚刚离开学校的我有了一股莫名的忧伤,曾经在求学路上陪伴我们十余年的诸位老师,你们近来好吗?碰到的学生还跟当前的我们一样顽皮捣蛋,让您们头疼吗?张铁志先生延续之前歌手系列的讲述,又一次给我这个美国音乐盲着实扫盲了一把。此期读库,最让我着迷的一部分当属瓦当的《穿越而来》,通篇从尼古拉·特斯拉的童年一直到老去,讲述了特斯拉一生中的传奇事迹,从一个无名的电话公司员工,到交流电之父,直至孤独地终老于纽约人旅馆。特斯拉用了一个几近传奇的一生也我们诠释了人类可以如此出众,可以如此卓越,但是我们珍惜过这位天才吗?苗炜的《声音》是我个人比较喜欢的一种文体,仅仅采用便签式的杂记体,从平日媒体上,阅读书籍中,网路交流中等等撷取诸多精辟而不失为典型的一些言论,附加自我简短的讲述,客观而精妙地阐述了2009年。

下面是《读库0906》我个人最喜欢的两段文字:

我不明白,一名收银员怎么能因一点三欧元遭解雇,而那些丢掉数以十亿计欧元的银行高管却能保住工作。——德国一名工龄超过三十年的超市收银员因为涉嫌偷窃一点三欧元遭超市解雇,基督教社会联盟主席霍斯特·泽霍费尔说,这一事例更加剧人们对资本主义制度的怀疑。

政治不会比我现在从事的行业更肮脏。——色情演员丹尼尔斯在竞选美国路易斯安那州参议员

对于一个囚犯来说,真正的监狱是在他出监狱的这一天才开始的。——阿兰牧师

年底贺岁

己丑年的尾巴真的就要隐去了,庚寅年就要来了。

在这个不知年味的城市中,待了快一年了,终于还是要离开,回家。

祝所有的人新年快乐,希望在新的一年里,世界和平,万家灯火!

LineNumberReader和FileWriter同时使用碰到的问题

今天上班有个任务就是将之前产品中的示范代码有一些不规范的地方进行修改,使得能在多平台顺利运行,主要是文件名大小写的问题。由于之前示范代码编写者在跨平台上编码经验相对不足,所以编写者在写代码的时候并没有严格的大小写意识(主要原因还是因为Windows不区分大小写,而代码的测试均是在Windows下进行的),造成很多遗留问题。产品中有示范代码64个,大小写问题几乎无处不在,还有一个就是跨平台产品支持的数据引擎与Windows不一致,之前的Windows版本中有不少的示范代码使用了Windows平台特定的引擎类型,也需要进行修改。

修改的方法可以有很多,最为简单和直接的方法,应该是一个个程序运行,一个个文件检查,逐个进行修改。我想作为程序员的我们,肯定是不愿意做这么无聊而重复的工作的。那么搞定这个无聊而重复的工作呢?首先分析一下已有的示范代码的特征,虽然之前的代码存在诸多不规范的地方,但是在一些方面还是存在很多共性的,大小写出现错误的肯定是在设置数据路径的时候出现的,设置引擎类型的代码更是固定的,之需要使用几个非常简单的正则表达式就可以将其完全正确替换了。所以我们选择了读写文件的方法来完成这个任务。

在实现这个功能的时候,使用到了LineNumberReader和FileWriter两个类,每读取一行,使用replaceAll(String regx,String str)方法对该行进行替换,之后再使用FileWriter将替换后的文本写入文件:

File file = new File(sourcePath);

try {
lineNumberReader = new LineNumberReader(new FileReader(file));
String line = lineNumberReader.readLine();
fileWriter = new FileWriter(file);
while (line != null) {
line = line.replaceAll("\\.xxx", ".XXX");
fileWriter.write(line+"\r\n");
line = lineNumberReader.readLine();
fileWriter.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
lineNumberReader.close();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}

执行的结果是,64个示范代码中,总会有几个会出现一些很奇怪的问题,那就是修改后的文件丢失了很多文本,导致编译不通过。那么问题在哪儿呢?经过多次分析和调试,最终发现当LineNumberReader和FileWriter指向同一个文件的时候会出现该问题,如果将源文件处理后的结果写入到一个新的文件中便不会存在这样的问题。那么究竟是哪里出了问题呢?来看一张图

在这张图中我们能看到一些信息,LineNumberReader对象中有一个cb字符数组,大小为8192=1024*8.

在我整个的调试过程中,我一直关注着最后一个字符,在整个过程中,这个位置的字符一直没有发生改变,而最终写入到文件中的最后一个字符就是该字符,这难道只是一个巧合吗?

现在让我们更换一下代码将原本使用同一个File对象的代码,改成使用另一个新文件对象的代码来重新调试一下。

先执行代码,查看结果发现,文本的内容完全被写入到新文件中,并没有出现丢失文本这样的情况,那么我们再来调试一下,我们再次来监视cb[8191]处的值,这次我们可以发现在LineNumberReader对象lineNumber==319的时候,该值发生改变。

====我是分割线======

综合上面的两种情况,我们可以得出一个结论,当LineNumberReader和FileWriter同时指向一个文件的时候,系统在写入文件的时候并不是逐行逐行写入,而是先记录下来逐行的内容,并且是记录到LineNumberReader的cb字符数组中。该数组的大小固定为内存最小单位8K,也就是大小为8192的数组,该数组将保存初次初始化FileWriter对象时读取的文件内容,在之后的每次FileWriter写入操作均是改变该数组中存储的字符值。这样导致的结果就是,如果当前的读取的文件较大,就会存在丢失内容的问题(最多保存8192个字符,含空格和换行)。而使用一个新的文件来进行修改后内容的写入就不存在这样的问题,当FileWriter需要使用到flush()方法来将当前缓冲区中的所有内容写入文件之后,LineNumberReader中的cb数组内容也将发生改变,指针下移,读取下一个块大小为8192的内容,直到文件末尾。

所以在使用LineNumberReader和FileWriter的时候需要注意这一点,如果实在不愿意多生成一堆新文件的话,可以在写入完成之后,将原始文件删除,而将新文件更名一下就好了。