神秘島出版於一八七四年,比艾西莫夫早了一百年,在還那個工業革命的時代裡,凡爾納將煉鋼、化學反應與熱氣球這些先進的技術寫到小說裡面,透過工程師賽勒斯,把所有技術實現出來。
這本書唯一看到的反派角色,只有一艘曇花一現的海盜船,這裡面還有六個逃往森林裡的海盜,其他的部份,就是五個人+一隻狗+一隻猩猩,互相幫助解決問題,後來還拯救了被放逐在塔波島的海盜愛爾迪,還有海底兩萬里的尼莫船長。
說真的情節有點悶,不夠緊湊,還有這幾個「移民」,一直撿到一些特別的,沒辦法製造出來的東西,例如槍枝,在我個人看起來,其實是有些突兀,雖然這本書最令人津津樂道的,就是「移民」能徒手以自己的知識,就地取材製造出自己所需要的東西,而且這幾個人之間,完全沒有猜忌也少有爭執,不同職業的他們,都能以工程師為核心而各司其職。如果真讓賽勒斯還能直接土法做出槍枝來,可能就太誇張了。
科幻是要預知未來,奇幻則是天馬行空,我們會對艾西莫夫如此推崇,是因為他的科幻領先了目前的所有科技,雖然凡爾納沒能作到,但因為他比艾西莫夫早了一百年,而十八世紀末到十九世紀,恰好是科學突飛猛進的時代,如果凡爾納能在二十世紀,或許能寫出另一個不同的神秘「星球」而不是神秘「島」。
2009/3/30
2009/3/22
神奇的 Runtime.exec 遇到保留字元的處理方法
要產生Process執行command line程式,在java裡面是使用Runtime.exec,在JDK 1.5之後出現了另一個 ProcessBuilder,ProcessBuilder多了管理環境變數的方法,也能切換工作目錄。一般使用Runtime Process會先遇到IO Blocking的問題,這個可以參考這些文章:When Runtime.exec() won't、java中呼叫.bat 卻沒有反應.... 、StreamGobbler的詳細解釋,使用 StreamGobbler 解決。但另外遇到 shell command 裡面的保留字元時,就會產生了一些奇怪的問題。
最常見的就是空白字元,例如在命令的執行路徑上,出現了空白字元,以 windows 來說,如果直接在"命令提示字元"中,打上 c:\Program Files\xxx\xxx.exe,就會出現路徑的錯誤,因為shell沒辦法處理有空白字元的路徑,所以要執行的時候,就得加上 雙引號 變成 "c:\Program Files\xxx\xxx.exe",這樣就可以執行了。
在Linux環境也是一樣的,遇到空白字元,就會發生問題,除了用 雙引號的方法之外,單引號也可以,或是加上escape char \,例如 /home/root/bin/xx x.sh ,可以改成 "/home/root/bin/xx x.sh" 或是 '/home/root/bin/xx x.sh' 或是在空白前面加上escape char /home/root/bin/xx\ x.sh 就可以執行了。
事實上除了空白字元之外,還有可能會遇到 ( ) " ' 這些字元,都是shell上的保留字元。為了求得一個能同時在 linux 與 windows 都能運作的執行方法,用雙引號似乎就能同時解決這樣的問題,但是事實上,放到 Runtim.exec 裡面執行時,又不是這麼一回事。為了執行一個程式,現在有幾種寫法可以用,(1) 將命令含參數,弄成一個字串,然後放到 runtime.exec 執行 (2) 將命令含參數,弄成一個字串,然後前面加上 shell ,例如windows 平台就寫 cmd /c、而linux 平台就寫 /bin/sh -c,然後放到 runtime.exec 執行 (3) 將命令與參數作成 List shellcmd,然後用 new ProcessBuilder(shellcmd).start() 執行 (4) 將命令與參數作成 List shellcmd ,前面加上 shell,cmd /c 或是 /bin/sh -c,然後用 new ProcessBuilder(shellcmd).start() 執行。
測試許久,最後還是沒有辦法找到一種方式,同時適用於 windows 與 linux,結果以 ffmpeg bin\ffmpeg.exe 與 ffmpeg bin\ffmpeg 兩個執行檔為例,假設我要執行 ffmpeg -i test.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 test.flv,在 windows平台,我得寫
List cmdlist=new ArrayList();
cmdlist.add("\"ffmpeg bin\ffmpeg\"");
cmdlist.add("-i");
cmdlist.add("\"test.wmv\""); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
cmdlist.add("-ab");
cmdlist.add("56");
cmdlist.add("-ar");
cmdlist.add("22050");
cmdlist.add("-b");
cmdlist.add("500");
cmdlist.add("-r");
cmdlist.add("15");
cmdlist.add("-s");
cmdlist.add("320x240");
cmdlist.add("\"test.flv\""); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
new ProcessBuilder(cmdlist).start();
而在 linux平台,我得寫
List cmdlist=new ArrayList();
cmdlist.add("/bin/sh");
cmdlist.add("-c");
cmdlist.add("\"ffmpeg bin\ffmpeg\" -i \"test.wmv\" -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 \"test.flv\"
"); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
new ProcessBuilder(cmdlist).start();
最常見的就是空白字元,例如在命令的執行路徑上,出現了空白字元,以 windows 來說,如果直接在"命令提示字元"中,打上 c:\Program Files\xxx\xxx.exe,就會出現路徑的錯誤,因為shell沒辦法處理有空白字元的路徑,所以要執行的時候,就得加上 雙引號 變成 "c:\Program Files\xxx\xxx.exe",這樣就可以執行了。
在Linux環境也是一樣的,遇到空白字元,就會發生問題,除了用 雙引號的方法之外,單引號也可以,或是加上escape char \,例如 /home/root/bin/xx x.sh ,可以改成 "/home/root/bin/xx x.sh" 或是 '/home/root/bin/xx x.sh' 或是在空白前面加上escape char /home/root/bin/xx\ x.sh 就可以執行了。
事實上除了空白字元之外,還有可能會遇到 ( ) " ' 這些字元,都是shell上的保留字元。為了求得一個能同時在 linux 與 windows 都能運作的執行方法,用雙引號似乎就能同時解決這樣的問題,但是事實上,放到 Runtim.exec 裡面執行時,又不是這麼一回事。為了執行一個程式,現在有幾種寫法可以用,(1) 將命令含參數,弄成一個字串,然後放到 runtime.exec 執行 (2) 將命令含參數,弄成一個字串,然後前面加上 shell ,例如windows 平台就寫 cmd /c、而linux 平台就寫 /bin/sh -c,然後放到 runtime.exec 執行 (3) 將命令與參數作成 List
測試許久,最後還是沒有辦法找到一種方式,同時適用於 windows 與 linux,結果以 ffmpeg bin\ffmpeg.exe 與 ffmpeg bin\ffmpeg 兩個執行檔為例,假設我要執行 ffmpeg -i test.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 test.flv,在 windows平台,我得寫
List
cmdlist.add("\"ffmpeg bin\ffmpeg\"");
cmdlist.add("-i");
cmdlist.add("\"test.wmv\""); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
cmdlist.add("-ab");
cmdlist.add("56");
cmdlist.add("-ar");
cmdlist.add("22050");
cmdlist.add("-b");
cmdlist.add("500");
cmdlist.add("-r");
cmdlist.add("15");
cmdlist.add("-s");
cmdlist.add("320x240");
cmdlist.add("\"test.flv\""); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
new ProcessBuilder(cmdlist).start();
而在 linux平台,我得寫
List
cmdlist.add("/bin/sh");
cmdlist.add("-c");
cmdlist.add("\"ffmpeg bin\ffmpeg\" -i \"test.wmv\" -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 \"test.flv\"
"); // 因為檔案路徑有可能會含有空白字元,就幫他加上雙引號
new ProcessBuilder(cmdlist).start();
2009/3/15
理由 by 宮部美幸
這本書是因為看了模仿犯之後,才去買來看的,這是模仿犯2001年得獎作品的前作,是在1999年得到直木獎。但老實說,看這本書的時候,並沒有看模仿犯急著想要看完的感覺,反而是硬逼著自己把他看完的。
原因在於白描的方式,又完全沒有推理的成份,我並沒有期待想看到結局的感覺,這樣的描述方式,跟我常常閱讀的科幻小說,是完全不一樣的。也跟模仿犯不同,因為在模仿犯裡,我會急著想知道和平是怎麼被抓的,在理由裡面,我卻不在意,石田直澄會怎麼落網。這兩種完全不一樣的感覺,
這本書越到後面的寫法,是以記者採訪當事者,然後當事者現身說法,描述當時發生的事情,由當事者自己描述自己的心境。許多評論都說,這是宮部美幸作品的特色,因為他能精準地描寫事件的發生,對每一個人的影響,還有每一個人的看法,看過作品之後,確實如此。
但讀完理由之後,我也沒有特別記得哪一個情節,哪一句話,只記得該案件發生的過程,另外也對石田直澄要一直逃的決定,覺得不大合理,也許是我比較自私,但如果我沒有殺人,卻又要我一直逃,為了掩護一位帶著孩子的媽,這絕對是行不通的,因為被通緝之後,等於完全沒有人生了,況且如果犯法,要逃走也是要偷渡逃到另一個國家,而不是一直留在國內,那絕對不是長久之計。
理由,不夠驚悚,也沒有緊湊的情節,還是模仿犯比較精彩一些。
原因在於白描的方式,又完全沒有推理的成份,我並沒有期待想看到結局的感覺,這樣的描述方式,跟我常常閱讀的科幻小說,是完全不一樣的。也跟模仿犯不同,因為在模仿犯裡,我會急著想知道和平是怎麼被抓的,在理由裡面,我卻不在意,石田直澄會怎麼落網。這兩種完全不一樣的感覺,
這本書越到後面的寫法,是以記者採訪當事者,然後當事者現身說法,描述當時發生的事情,由當事者自己描述自己的心境。許多評論都說,這是宮部美幸作品的特色,因為他能精準地描寫事件的發生,對每一個人的影響,還有每一個人的看法,看過作品之後,確實如此。
但讀完理由之後,我也沒有特別記得哪一個情節,哪一句話,只記得該案件發生的過程,另外也對石田直澄要一直逃的決定,覺得不大合理,也許是我比較自私,但如果我沒有殺人,卻又要我一直逃,為了掩護一位帶著孩子的媽,這絕對是行不通的,因為被通緝之後,等於完全沒有人生了,況且如果犯法,要逃走也是要偷渡逃到另一個國家,而不是一直留在國內,那絕對不是長久之計。
理由,不夠驚悚,也沒有緊湊的情節,還是模仿犯比較精彩一些。
2009/3/12
幫jar檔瘦身 Remove Unused Classes
寫程式的時候,通常會使用很多 library ,但是一旦遇到要把程式以 JNLP 的方式,送到client端的時候,產生jar的大小就很重要了,以LGPL license來看,我們的程式可以連結到LGPL license的library,我們不一定要以一個一個獨立的jar來散佈library,我們可以把所有classes集合在一個jar檔裡面,只要我們沒有修改到原始程式,就應該符合license的規定。
所以我們可以把程式沒有使用到的 binary classes 都去掉,Open Source 授權的關係,我們不修改 library 原始程式,不使用obfuscator,但也能達到縮小 jar 的目的。
首先要準備一個 使用到的 classlist 檔案,在執行程式的時候,加上 -verbose:class 參數,ex: java -verbose: Test ,把結果輸出到一個 classlist.txt 檔案檔案裡面會有類似這樣的資料,這就表示JVM從commons-logging-1.1.1.jar裡面載入了一個 class org.apache.commons.logging.LogConfigurationException。
[Loaded org.apache.commons.logging.LogConfigurationException from file:/D:/testproject/lib/commons-logging-1.1.1.jar]
1. 把所有 library 的 jar 用 org.apache.tools.zip.ZipFile 解開到某個 release 的目錄
2. 把編譯的 class 程式,也複製到 release 目錄
3. 從剛剛的 classlist.txt 裡面,把使用到的 classes 名稱,收集在一個 hash 裡面
4. 用 org.apache.commons.io.FileUtils.iterateFiles 把 release 目錄裡面所有的 .class 都集合起來
5. 一個一個比對 是不是有在 classlist.txt 的 hash 裡面
6. 如果不存在就把這個 class 刪掉
7. 最後 再用 jar cvf ..\proejct.jar . 就可以產生一個去掉沒有使用到的 classes 的 jar
所以我們可以把程式沒有使用到的 binary classes 都去掉,Open Source 授權的關係,我們不修改 library 原始程式,不使用obfuscator,但也能達到縮小 jar 的目的。
首先要準備一個 使用到的 classlist 檔案,在執行程式的時候,加上 -verbose:class 參數,ex: java -verbose: Test ,把結果輸出到一個 classlist.txt 檔案檔案裡面會有類似這樣的資料,這就表示JVM從commons-logging-1.1.1.jar裡面載入了一個 class org.apache.commons.logging.LogConfigurationException。
[Loaded org.apache.commons.logging.LogConfigurationException from file:/D:/testproject/lib/commons-logging-1.1.1.jar]
1. 把所有 library 的 jar 用 org.apache.tools.zip.ZipFile 解開到某個 release 的目錄
2. 把編譯的 class 程式,也複製到 release 目錄
3. 從剛剛的 classlist.txt 裡面,把使用到的 classes 名稱,收集在一個 hash 裡面
4. 用 org.apache.commons.io.FileUtils.iterateFiles 把 release 目錄裡面所有的 .class 都集合起來
5. 一個一個比對 是不是有在 classlist.txt 的 hash 裡面
6. 如果不存在就把這個 class 刪掉
7. 最後 再用 jar cvf ..\proejct.jar . 就可以產生一個去掉沒有使用到的 classes 的 jar
2009/3/4
模仿犯-下 by 宮部美幸
上集花了一週,下集只花了三天就看完了,原因是我看著看著,就急著想要知道最後的結果是什麼,到底和平是怎麼被抓到的。
不同於對其他人內心的詳細描寫,作者並沒有直接撰寫網川浩一 (和平)的內心世界,反而是藉由其他人的描寫,讓讀著以旁觀者的身份,瞭解這個自大的殺人犯,對和平來說,這是他精心策劃的舞台,每一次的轉折,都是由他設計導演,所有人都得按照他的劇本來表演。
雖然有時候會出現突發的狀況,但和平都能冷靜地思考,並判斷下一步,所有人該怎麼走位。遇到了有馬義男,跟塚田真一,著實讓和平有點難以應付,因為他們不像是由美子,那麼單純容易掌握。但他們兩位都是受害者,倖存下來的人,常常會自責到讓自己無法面對自己,這也是他們的弱點。受害者跟加害者兩邊倖存的家人,也是和平操控情勢的利器。
和平怎麼也沒想到,自己費盡心思導演的一切,竟然已經被十年前的一本以實際案件為基礎撰寫的小說寫出來了,雷同的情節,他被茲子在現場節目上影射只是個模仿犯,讓他一下子無法承受,當場就承認了罪狀,反駁全都是他自己策劃的。就像是費盡心思研發的成品,結果卻早在多年前,就被人申請了專利,又被以侵權告上法院,這當然讓人無法接受。
模仿犯這個主題,直到全書的最後才點明,讓人有恍然大悟的感覺,畢竟我已經等了一千多頁了。
不同於對其他人內心的詳細描寫,作者並沒有直接撰寫網川浩一 (和平)的內心世界,反而是藉由其他人的描寫,讓讀著以旁觀者的身份,瞭解這個自大的殺人犯,對和平來說,這是他精心策劃的舞台,每一次的轉折,都是由他設計導演,所有人都得按照他的劇本來表演。
雖然有時候會出現突發的狀況,但和平都能冷靜地思考,並判斷下一步,所有人該怎麼走位。遇到了有馬義男,跟塚田真一,著實讓和平有點難以應付,因為他們不像是由美子,那麼單純容易掌握。但他們兩位都是受害者,倖存下來的人,常常會自責到讓自己無法面對自己,這也是他們的弱點。受害者跟加害者兩邊倖存的家人,也是和平操控情勢的利器。
和平怎麼也沒想到,自己費盡心思導演的一切,竟然已經被十年前的一本以實際案件為基礎撰寫的小說寫出來了,雷同的情節,他被茲子在現場節目上影射只是個模仿犯,讓他一下子無法承受,當場就承認了罪狀,反駁全都是他自己策劃的。就像是費盡心思研發的成品,結果卻早在多年前,就被人申請了專利,又被以侵權告上法院,這當然讓人無法接受。
模仿犯這個主題,直到全書的最後才點明,讓人有恍然大悟的感覺,畢竟我已經等了一千多頁了。
2009/3/1
模仿犯 by 宮部美幸
因為我是網路訂購的,剛拿到這本書的時候,真的嚇了一跳,怎麼會有這麼厚的小說,不過有先看過評語,都說這位作家非常擅長寫故事,除了得獎之外,還有「國民作家」的頭銜,上下兩本書加起來總共一千三百多頁,我一開始就在懷疑,我到底要花多久的時間才能看完。
目前花了一週的時間,就把上集事件之卷讀完,作者真的非常會講故事,但我覺得更貼切的說法是,作者非常擅長描寫每一位出場人物「瞬間的雜念」,因為我自己也常常會在心裡產生許多短暫的、臨時的想法與動念,善意的就像是靈光一現的idea,會趕緊用筆記錄下來,但也會有惡意的,那些就會馬上在心裡拿起板擦抹去。
以往看過的小說人物,大多個性鮮明,說話與動作都很直接,但這本書寫法的不同,而是細膩地描寫當事人的所有「突然」的想法,所有的猜測,反反覆覆地,而且每一個人都會在心裡作不同程度的推理,有時候作者還會點明,受害者如果注意某個東西,或是換成某一種想法,可能就會發現犯人的惡行,自然能趨吉避凶。
看著犯人栗橋浩美的心境,真的有不寒而慄的感受,看著他在心裡假想,如果..那麼就會..,假設他殺人會怎麼樣,假想受害者在別墅裡會怎麼樣。我只覺得一位成功的小說作者,到底該「人格分裂」到什麼程度,才能夠具體的掌握每一個人物的心情與想法,卻又能真切地感受到他們的想法,不讓人覺得突兀,也得能製造出合理的情節。
下集開始要看和平這位極有自信又冷靜的犯人,他的內心世界,我在期待著,到底故事要怎麼收尾呢?這是限制級的小說,兒童不宜,看後我得把他藏在書架的後面。
目前花了一週的時間,就把上集事件之卷讀完,作者真的非常會講故事,但我覺得更貼切的說法是,作者非常擅長描寫每一位出場人物「瞬間的雜念」,因為我自己也常常會在心裡產生許多短暫的、臨時的想法與動念,善意的就像是靈光一現的idea,會趕緊用筆記錄下來,但也會有惡意的,那些就會馬上在心裡拿起板擦抹去。
以往看過的小說人物,大多個性鮮明,說話與動作都很直接,但這本書寫法的不同,而是細膩地描寫當事人的所有「突然」的想法,所有的猜測,反反覆覆地,而且每一個人都會在心裡作不同程度的推理,有時候作者還會點明,受害者如果注意某個東西,或是換成某一種想法,可能就會發現犯人的惡行,自然能趨吉避凶。
看著犯人栗橋浩美的心境,真的有不寒而慄的感受,看著他在心裡假想,如果..那麼就會..,假設他殺人會怎麼樣,假想受害者在別墅裡會怎麼樣。我只覺得一位成功的小說作者,到底該「人格分裂」到什麼程度,才能夠具體的掌握每一個人物的心情與想法,卻又能真切地感受到他們的想法,不讓人覺得突兀,也得能製造出合理的情節。
下集開始要看和平這位極有自信又冷靜的犯人,他的內心世界,我在期待著,到底故事要怎麼收尾呢?這是限制級的小說,兒童不宜,看後我得把他藏在書架的後面。
訂閱:
文章 (Atom)