2012年12月14日 星期五

走到最後還能留在身邊的,都要珍惜

在網路看到一段 Java Code,正想要好好品味一下時,才發現身邊只剩下那台跟著我許多年的 NB,因為他太老了,跑微軟的作業系統更顯吃力,所以才變節投靠 Ubuntu ,早些年前,他身上還貼著正版的微軟 XP 序號、標籤、標語,當年的繁華光景,連「華碩品質堅若石頭」的彩帶我都還留著,如今卻落魄到同我為伍,不經讓我想起「老人與狗」這本書...

我問他,你跑得快嗎?他搖搖頭。
我再問他,你可以跑 Java 嗎?他也搖搖頭。

看到他一臉徬徨無助的眼神,讓我升起悲憫之心,於是我決定好好教他,讓他可以「跑 Java」。


於是,我在深夜裡,冒著外頭的刮風下雪,來到爪哇旗艦店,一進門,就看到親切的業務向我正面迎來,並單手向我熱情的招呼著,同時遞送上來一杯熱騰騰的咖啡。沒多久,我就在展示間看到今年最流行的第七代 Java,型號是七架。望著七架流線的造型,彷彿可以感受到風在我臉上吹拂,速度在我腳下奔馳的快感。我當下就決定買下,並轉送給我的 NB,這種感覺,就好比當年淑珍買積架送給致中的心情是一模一樣的,「天下父母心,花別人的錢最開心」。















印象中,要能夠在 Ubuntu上跑 Java,是要花蠻多功夫的,但我的業務員告訴我一個簡單的方法,叫做 PPA (Personal Package Archive)。只要三行指令,就可以辦到好。

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java7-installer

原來有一段小故事是這樣的。在 Ubuntu 的世界裡,會有一個叫做「軟體中心」,伴隨著每六個月推出新版本的檔期,都可以在裡面找到最新的套件,而這些套件都是經過 Ubuntu 團隊審核過才放上去的。問題,就在於我們所需要的軟體,是否可以慢慢等待到審核通過後才能使用呢?如果我要的七架已經問世,但又不想等待半年後才拿到,這時就可以使用 PPA  的方式來取得,但風險則是沒通過審核,所以不保證安裝完後是否會影響系統的穩定性。這跟我要買 iPhone 的道理是一樣的,在美國新版的已經問世,但台灣還沒正式開賣,所以只好透過「水貨」的管道來取得。

透過那三行指令,我終於讓我的 NB 可以跑 Java 了,但我發現一個很大的問題,他不認識中文。於是,我又開始「ㄠ」我的業務員,同樣也是得到三行簡單好用的指令來完成中文環境的開發。

# cd /usr/lib/jvm/java-6-sun/jre/lib/fonts
# mkdir fallback
# ln -s /usr/share/fonts/truetype/wqy/wqy-zenhei.ttc

看著他正在努力的奔跑著,我笑了,我睡了....



參考:
01:INSTALL ORACLE JAVA 7 IN UBUNTU VIA PPA REPOSITORY
02:解决ubuntu下java中文字体显示方框问题
03:What Is An Ubuntu PPA & Why Would I Want To Use One?
04:快速添加 Ubuntu PPA 源

2012年12月13日 星期四

與 Split 更親近一點

先前在使用 C# 對字串進行切割 (split) 動作時,常常會希望把空白的字串過濾掉,只留下字串長度不是 0 的。而這工作其實也不難,就是將  split 後所得到的字串陣列,在你要用時用迴圈一筆一筆去濾掉空白的陣列元素。

剛好今天看到 「StringSplitOptions 列舉型別」介紹了其中的「RemoveEmptyEntries」成員,可以限定傳回值不會加入包含了空字串的陣列元素,有這麼好康的事情就來試試效果如何。於是寫了一個簡單的測試程式,沒想到添加了這作法還真是簡潔啊, 而且他從 .net 2.0 就開始支援了。

class Program
{
    static void Main(string[] args)
    {
        string strTest1 = "b,a,c,,";
        char[] charSeprator = new char[] { ',' };

        string strTest2 = "BB[x]CC[x]AA[x]";
        string [] strSeprator=new string[]{"[x]"};

       //以字元來切割
        foreach (string str in strTest1.Split(charSeprator, StringSplitOptions.RemoveEmptyEntries))
            Console.WriteLine(str);

       //以字串來切割
        foreach (string str in strTest2.Split(strSeprator, StringSplitOptions.RemoveEmptyEntries))
            Console.WriteLine(str);

        Console.ReadLine();

    }
}

如果開發環境是.net 3.5以上的版本,還可以更進一步去將 split 的結果進行排序後再取出。例如:

strTest2.Split(strSeprator, StringSplitOptions.RemoveEmptyEntries).OrderBy(g=>g)

就可將陣列進行排序。


參考:
01:StringSplitOptions 列舉型別
02:Extension Methods (C# Programming Guide)

2012年12月11日 星期二

String,StringBuffer,StringBuilder 的三角關係

不管是在 Java 或是 C#,對於 String 這物件應該都不陌生。但如果考量是在字串串接的用途上時, String 的效能可真的就顯得遜色許多。

String 物件一旦在記憶體被配置之後,他就不能夠再改變了,所以他常常被說成是 immutable object。但我們卻很習慣寫成這樣:


三行程式寫完後,請求了三塊新的記憶體配置,也同時浪費了兩塊記憶體。

針對這個問題,Java 提供了 StringBuffer 物件,讓我們可以對字串加加減減,也不會另外再要一塊新的記憶體位址來存放。在這物件當中,Java 還考慮到多執行緒的問題,也就是說,不同的執行緒不會同時對同一個 StringBuffer 物件做新增或是修改的動作,例如當執行緒 A 在使用 「StringBuffer 甲」的時候,執行緒 B 必須等到執行緒 A 完成「StringBuffer 甲」的處理動作 之後才能使用,這就是我們常說的 thread-safe。

對於 Java 所提供的 StringBuffer 物件,針對字串串接的執行校能上,的確可以非常明顯地看到提昇,但一般對程式設計師來說,大部分時機其實可能都不需要考量多執行緒的問題,如果不考慮多執行緒的情況下,減少多餘的判斷處理,是否還有機會再提昇字串串接的效能呢?

果真,在 JDK 1.5. 之後,開始出現了新的物件 StringBuilder ,他與 StringBuffer 的用途幾乎如出一轍,唯一的不同是減少了多執行緒的考量。日後如果只是在寫單一執行緒的程式考量下,StringBuilder 會是較好的選擇。「StringBuffer vs. StringBuilder performance comparison」文章作者Daniel 針對 StringBuilder 與 StringBuffer 兩者間的效能寫了一段簡單的程式來比較,而我自己也透過他的程式在自己電腦上得到了下面數據:


從數據上看來, StringBuilder 已經比 StringBuffer 提昇了一倍以上的效能,當然這兩者更遠遠超過 String 的字串串接。

同樣的情況,也出現在 微軟的 C# 裡。在字串串接的情況下, StringBuilder 遠比 String 的效能提昇很多,唯一讓我不解的,是這次微軟的身上少了 StringBuffer 的味道...,我很認真的想知道這次微軟為何沒收錄 StringBuffer 這物件,但迄今依舊無解。而微軟的 StringBuilder,同樣也是不考慮多執行緒,可以在微軟的官方文件「StringBuilder Class」看到 Thread Safety 的聲明:

Any public static (Shared in Visual Basic) members of this type are thread safe.
Any instance members are not guaranteed to be thread safe.

可從上面申明中知道,C# 裡面的 StringBuilder 並不是 thread-safe。

另一個有趣的地方,是從 JDK 釋出的時程來看看,彷彿 .net 在 2003年時釋出的 .net 1.1, 已經比 Java 更早公佈 StringBuilder 物件了!


經由這一次的整理,可以知道 String 在字串串接上所面臨的效能瓶頸,並透過 Daniel 的程式在定量上可以得到支撐。此外,也可以更清楚去分別依據是否為單一執行緒來正確抉擇 StringBuilder 或 StringBuffer。

參考:
01:StringBuffer vs. StringBuilder performance comparison
02:StringBuilder Class
03:Java JDK (Java Development Kit) Releases Dates and Release Differences
04:Java SE 6全方位學習
05:StringBuilder和StringBuffer的差別及清空內容方式
06:StringBuilder vs StringBuffer
07:Why use StringBuilder? StringBuffer can work with multiple thread as well as one thread?
08:StringBuffer and StringBuilder
09:Is the C# '??' operator thread safe?
10:如何:增進 Visual C# .NET 中的字串串連效能
11:Daniel 簡單測試程式

2012年12月7日 星期五

當 SSRS 遇到 VSS 時應該知道的事

最近接收了一包  SQL Server Reporting Service (SSRS) 所開發的報表,因為這包報表程式沒有使用任何的版本管控。富有正義感且集聚勇氣於一身的我,就當仁不讓地主動請纓要做好版本管控,於是我就用了最簡單的 Visual SourceSafe(VSS) 來控管這包報表。

其實做這事情真的沒有甚麼難度,一下子就把報表全部加到 VSS 裡面去了。但當我一執行報表時,竟然出現:


拒絕存取路徑 'D:\MyCode\bin\Debug\新世代青年生命成長營.rdl'

我想,是不是 「新世代青年生命成長營.rdl」 這隻檔案被設為唯讀所造成的,於是手動去把唯讀取消,再執行一次,結果還是一樣。於是我網路上找了很一陣子,發現有一篇微軟的文章:「修正: 在組建中,清除,伺服器專案錯誤報告,或預覽中 SQL Server 2008 R2 和出價等作業」,原來 SSRS 有 hotfix 啊,於是造著說明去下載,蠻肥的,約2百多M,沒想到更新完後再重試,竟然還是一樣。

在一股不理智的衝動下,我誤刪了 \bin 資料夾。但只要重新佈署一次,這個 \bin 資料夾自己又會重新生出來,且回覆正常了。但過些時日,這問題又會再跑出來一次,我刪除 \bin 資料夾後又可以正常。

當我閱讀了「FISERV TAP - Checking it RDL Source Sets Output Folder to Read Only」,發現這問題在 SSRS 與 VSS 搭配在一起,就很容易發生。解決方法可以參考該篇文章,但我覺得自己最省力氣的,還是刪除 \bin 資料夾。

參考:
01:修正: 在組建中,清除,伺服器專案錯誤報告,或預覽中 SQL Server 2008 R2 和出價等作業
02:FISERV TAP - Checking it RDL Source Sets Output Folder to Read Only
03:Access to the Path Error in Visual Studio
04:修正: 在組建中,清除,伺服器專案錯誤報告,或預覽中 SQL Server 2008 R2 和出價等作業