使用 OSX 10.6 有一段時間了,對於 software development 來說開始有些不方便了;像是 XCode 工具的版本限制以及 OpenJDK 7 安裝問題等。自從 Apple 公司發表新款 iPhone 5S/C 與 iPad Air 同時,突然佛心來著,OSX 10.9 提供免費升級:
當然,對個人來說簡直提天掉下來的禮物,於是開始著手安裝。
(1) 程序上總是先求保險,得準備第 2 顆硬碟進行資料備份:
(2) 設定第 2 顆硬碟開機,測試並確認資料有抄寫:
(3) 無誤後再設回原開機磁碟,重開機後開始下載安裝:
安裝完畢後,便是檢查所有常用應用程式的相容問題;多數情形下使用系統更新作業或程式換版就可以解決了。不過,最麻煩的是得下載幾個重量級的更新,例如:XCode;而且原系統中的 JDK 6 會被移除,須自行下載與安裝 Java for OS X 2013-005。
整個升級的過程最需的是體力與細心,因為備份時的資料整理與枯等,安裝後的目錄、檔案的移置、缺漏確認等,所需的時間很長不消十數小時。萬一不小心,大多資料的遺失可是會損失慘重。
而初步的使用心得,有 3 個小地方待適應:
(1) mouse / pad 的 scrolling 手勢方向與 v10.6 相反
(2) [swipe between pages] 手勢的功能,因不熟悉而常將正在瀏覧的頁面切到上一頁或下一頁
(3) 輸入法 hint 與過去的方式有點不同,尤其是標點符點的字鍵有更動,會一時之間找不到
that's it!
ps. 另外,中文字體看起怪怪、醜醜的
2013年10月27日
2013年10月15日
Multiple assignment in Groovy
在 Groovy 的說明資料中提到, 物件可以進行 multiple assignment。從其範例可看出 values 是 List 型別的: ...The syntax works for arrays as well as lists, as well as methods that return either of these...。
在 HA.KI blog 的範例 中最後一個也舉出了使用 regular expression 的技巧:
不過, 對於 List 的表述方式:
以上例來說, 只要 money 的值不是依 '數值 幣別' 呈現就會發生。 (例如 'Euro 12')
所以, 可以改善的技巧是用 inject() [參考上篇Groovy 的 inject() method 應用] 來呈現 List 物件即可:
在 HA.KI blog 的範例 中最後一個也舉出了使用 regular expression 的技巧:
def money = '12 Euro' def regexp = /(\d+) (\w+)/ def (exp, amount, currency) = (money =~ regexp)[0] assert '12' == amount assert 'Euro' == currency
不過, 對於 List 的表述方式:
listObject[index] // 或 listObject.get(index) // 保守寫法: listObject?.get(index)是存在當掉的風險的, 因為 index 有可能超過索引範圍。
以上例來說, 只要 money 的值不是依 '數值 幣別' 呈現就會發生。 (例如 'Euro 12')
所以, 可以改善的技巧是用 inject() [參考上篇Groovy 的 inject() method 應用] 來呈現 List 物件即可:
def (exp, amount, currency) = (money =~ regexp)?.inject([]) { res, itm ->
res += itm
}
ps. 參考資訊 http://rosettacode.org/wiki/Return_multiple_values
2013年10月5日
GVM 與 GroovyServ
執行 .groovy code 不外乎要設定 PATH 與 CLASSPATH,以找到 interpreter(groovy)、compiler(groovyc) 與相關的 library;它往往需要在啟動的 shell 或 user profile 來加以處理。但,以系統維運的角度來說,則需要"安裝",以便整合至 environment 之中,維持系統固定、一致版本的 interpreter 與 compiler。以 ubuntu 系統為例:
另一種安裝的選擇:GVM;它有如 linux 的 alternatives 來管理不同版本的 package 路徑一般 (alternatives 可用來安裝多版本 JDK),安裝後並指定 groovy 的版本。使得 groovy script 的第一行寫法保持一致、不受影響。
話說 language ,不免會被拿來與過去熟知的做比較;Java 也曾被"提過"很慢,但隨時代的演進這已是不再拿來作文章的話題了。近年來 JVM 上熱門的 dynamic language:Groovy ;也一樣引起話題:慢。
也就是說 script 會因功能的增加而 source code 越來越長,也造成編譯與執行的時間相對變長;這往往會造成 developer 的困擾。這種在編譯時期一樣有這"症頭"的還有 Scala;不過,人家它有 fsc;那 Groovy 呢?
還好出現了 GroovyServ。
以抓取某熱門森林遊樂區的訂房首頁的應用為例:
僅使用 groovy interpreter,執行的時間:
ps.
停用 GroovyServ 的指令:
sudo apt-add-repository ppa:groovy-dev/groovy sudo apt-get update sudo apt-get install groovy groovy -version Groovy Version: 1.8.6 JVM: ...使得 groovy script 有如 shell script 一般,只要在 script 的第一行指出 interpreter 即可:
#!/usr/bin/bash # this is a bash shell script echo "1 + 2 = $((1+2))" # ...
#!/usr/bin/env groovy
// this is a groovy script
println "1 + 2 = ${1+2}"
// ...
另一種安裝的選擇:GVM;它有如 linux 的 alternatives 來管理不同版本的 package 路徑一般 (alternatives 可用來安裝多版本 JDK),安裝後並指定 groovy 的版本。使得 groovy script 的第一行寫法保持一致、不受影響。
話說 language ,不免會被拿來與過去熟知的做比較;Java 也曾被"提過"很慢,但隨時代的演進這已是不再拿來作文章的話題了。近年來 JVM 上熱門的 dynamic language:Groovy ;也一樣引起話題:慢。
也就是說 script 會因功能的增加而 source code 越來越長,也造成編譯與執行的時間相對變長;這往往會造成 developer 的困擾。這種在編譯時期一樣有這"症頭"的還有 Scala;不過,人家它有 fsc;那 Groovy 呢?
還好出現了 GroovyServ。
以抓取某熱門森林遊樂區的訂房首頁的應用為例:
僅使用 groovy interpreter,執行的時間:
real 0m6.180s user 0m4.875s sys 0m0.271s而搭配 GroovyServ 使用,在執行一次以後則:
real 0m1.445s user 0m0.018s sys 0m0.040s看的出它的"效果"驚人!這對於 developer 的工作有相當大的幫助。並且, GVM 工具也支援安裝 GroovyServ,維護上相當方便。
ps.
停用 GroovyServ 的指令:
groovyserver -k
2013年8月19日
Upgrade subversion 至 v1.7.11
繼上篇解決 OSX 10.6 中安裝 SVN 與 Git 的 zlib 問題;為 upgrade subversion 至 v1.7.x 好讓 GGTS/Subclipse v1.8 開發工具所使用,進行下列指令的處置:
處理的方法是改安裝 v1.7.11:
隨即開啟 GGTS 設定: [Preferences/Team/SVN] 下的 [SVN interface] 至 "JavaHL (JNI) 1.7.11 (r1503888)" 即可。
cd /usr/local/Library/Formula/ brew update brew versions subversion git checkout 0060dc3 /usr/local/Library/Formula/subversion.rb卻發生無法安裝情形:
處理的方法是改安裝 v1.7.11:
brew tap homebrew/versions brew install --universal --java subversion17這樣子只要再檢查 /Library/Java/Extensions 下有沒有相關的 symbolic link:
隨即開啟 GGTS 設定: [Preferences/Team/SVN] 下的 [SVN interface] 至 "JavaHL (JNI) 1.7.11 (r1503888)" 即可。
2013年8月7日
Java 的檔案傳輸
說到網路通訊,在一般 Java 的實作上多半會兩種方式: HTTP 或 RMI (當然也可寫個 socket server / client)。無論坊間的教育中心或書籍,都會有基本的範例;而且現今的 Internet 中也有很多成熟的 sample code (只要問對谷歌大神)。
那檔案傳輸呢:
一般提到 Java I/O 時,很多的 software developer 並不會對它陌生;遇到 HTTP 的檔案傳輸可使用如 Apache HTTPClient 這樣子的 package,以 multi-part 方式 (MultipartEntity) 來傳輸。
但個人有遇過 "咬" 住的測試經驗。於是乎搬出 PipedInputStream / PipedOutputStream 再加上啟用一個 Thread 來處理,就可以解決這個問題了。以 Groovy 為例:
那 RMI 呢? (想到就頭大?)
還好有 RMIIO 這個好心的 package (是 LGPL 哦,感動吧!感謝作者)
它的優點,就是如同它的說明所描述: makes it as simple as possible to stream large amounts of data
我個人使用它的心得是,沒有 "咬" 住的情形。而且當初看上它的原因是 client code 與 server code 之間,不需要做 nofity 與 ack 這樣多餘的機制來傳檔與送回接到檔案的訊息:
A --- send ---> B
A <--- ack --- B
只要控制是否 throw RemoteException 以及 try / catch 這個 exception 即可。以 Java code 為例:
那檔案傳輸呢:
一般提到 Java I/O 時,很多的 software developer 並不會對它陌生;遇到 HTTP 的檔案傳輸可使用如 Apache HTTPClient 這樣子的 package,以 multi-part 方式 (MultipartEntity) 來傳輸。
但個人有遇過 "咬" 住的測試經驗。於是乎搬出 PipedInputStream / PipedOutputStream 再加上啟用一個 Thread 來處理,就可以解決這個問題了。以 Groovy 為例:
...
def InputStream pipeOutput(Closure write) {
def output = new PipedOutputStream()
def input = new PipedInputStream(output)
Thread.start {
try{
write(output)
output.flush()
} finally {
try { output?.close() } catch (e) {/*nothing to do*/}
}
}
return input
}
...
...
def ctn = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE)
ctn.addPart("zipFile",
new InputStreamBody(
pipeOutput { output ->
Thread.currentThread().sleep(1000)
inFile = new FileInputStream(fileName)
output << inFile
}
,'application/x-gzip'
,'test.gz'
)
)
...
...
// HttpClient的處理 <略>
...
@@ (暈了嗎?)那 RMI 呢? (想到就頭大?)
還好有 RMIIO 這個好心的 package (是 LGPL 哦,感動吧!感謝作者)
它的優點,就是如同它的說明所描述: makes it as simple as possible to stream large amounts of data
我個人使用它的心得是,沒有 "咬" 住的情形。而且當初看上它的原因是 client code 與 server code 之間,不需要做 nofity 與 ack 這樣多餘的機制來傳檔與送回接到檔案的訊息:
A --- send ---> B
A <--- ack --- B
只要控制是否 throw RemoteException 以及 try / catch 這個 exception 即可。以 Java code 為例:
// 傳送端
// 用壓縮的 InputStream
try {
...
RemoteInputStream remoteIs = exporter.export(new GZIPRemoteInputStream(fileInputStream));
...
remoteObject.receiveData(remoteIs);
...
} catch ...
...
// 接收端
public void receiveData(RemoteInputStream remoteIs) throws RemoteException {
...
InputStream is = RemoteInputStreamClient.wrap(remoteIs);
...
if (somethingWrong) throw new RemoteException("some message");
...
// InputStream / OutputStream 後續處理
...
}
訂閱:
文章 (Atom)








