2011-10-03

以 Java 實作 Base 64 Encoder

或許有人會覺得奇怪,Java 本身已經有支援 Base 64 Encoder 了,為什麼還要自己重新寫一個? 事實上,Java 平台的 Base64Encoder 需要 import sun.misc.BASE64Encoder,然而這個類別卻不是在所有平台上面都可以正常執行(我個人的經驗是,在 android 執行時會當機)。 以下為 Base 64 Encoder 實作程式碼,歡迎各位朋友切磋學習。
private static String base64_encode( byte[] bytes ) {
        String[] base64 = { "A", "B", "C", "D", "E", "F", "G", "H",
                            "I", "J", "K", "L", "M", "N", "O", "P",
                            "Q", "R", "S", "T", "U", "V", "W", "X",
                            "Y", "Z", "a", "b", "c", "d", "e", "f",
                            "g", "h", "i", "j", "k", "l", "m", "n",
                            "o", "p", "q", "r", "s", "t", "u", "v",
                            "w", "x", "y", "z", "0", "1", "2", "3",
                            "4", "5", "6", "7", "8", "9", "+", "/" };
        String encoded = "";

        int pad_length = 0;
        if ( bytes.length % 3 == 1 )
            pad_length = 2;
        else if ( bytes.length % 3 == 2 )
            pad_length = 1;
        
        byte[] padded = new byte[ bytes.length + pad_length ];

        for( int i = 0; i < bytes.length; ++i ) {
            padded[ i ] = bytes[ i ];
        }
        if ( pad_length == 1 ) {
            padded[ padded.length - 1 ] = 0;
        } else if ( pad_length == 2 ) {
            padded[ padded.length - 1 ] = 0;
            padded[ padded.length - 2 ] = 0;
        }
        
        for( int i = 0; i < padded.length; i += 3 ) {
            encoded += base64[ ( ( padded[ i ] & 255 ) >>> 2 ) ];
            encoded += base64[ ( ( ( padded[ i ] & 3 ) << 4 ) | ( ( padded[ i + 1 ] & 255 ) >>> 4 )  ) ];
            encoded += base64[ ( ( ( padded[ i + 1 ] & 15 ) << 2 ) | ( ( padded[ i + 2 ] & 255 ) >>> 6 )  ) ];
            encoded += base64[ ( padded[ i + 2 ] & 63 ) ];
        }
        
        encoded = encoded.substring( 0, encoded.length() - pad_length );
        
        if ( pad_length == 1 ) {
            encoded += "=";
        } else if ( pad_length == 2 ) {
            encoded += "==";
        }

        return encoded;
    }

2011-09-02

再玩一下 AES 加密解密

上次在這篇「玩了一下AES加密解密」裡面寫的程式碼有些缺點,就是加密過後的結果是 byte[] 而不是 String,對於 Java 的操作上不是很方便。看了幾位高手的博文,自己做了些改良,同時也將程式碼放上來拋磚引玉。主要的改良是透過 BASE64Encoder 和 BASE64Decoder 將 byte[] 轉為可讀的英文字母 + 數字字串,這在網址的傳遞上也有好處,不需要變成%xx%xx的 UTF-8 形式,更容易偵錯與閱讀,也不減少其安全性。
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder; 

public class Base64AES {

    public static String decrypt( String key, String text ) throws Exception {
        byte [] results = decrypt( key.getBytes(), new BASE64Decoder().decodeBuffer( text ) );
        return new String( results );
    }

    public static String encrypt( String key, String text ) throws Exception {
        byte[] results = encrypt( key.getBytes(), text.getBytes() );
        return new BASE64Encoder().encode( results );
    } 
    
    public static byte[] encrypt( byte[] key, byte[] msg ) throws Exception {
        if ( key.length != 16 ) {
            throw new IllegalArgumentException( "Key length should be 16." );
        }
        SecretKeySpec spec = new SecretKeySpec( key, "AES" );
        IvParameterSpec ivSpec = new IvParameterSpec( key );
        Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
        cipher.init( Cipher.ENCRYPT_MODE, spec, ivSpec );
        return cipher.doFinal( msg );
    }
    
    public static byte[] decrypt( byte[] key, byte[] msg ) throws Exception {
        if ( key.length != 16 ) {
            throw new IllegalArgumentException( "Key length should be 16." );
        }
        SecretKeySpec spec = new SecretKeySpec( key, "AES" );
        Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
        IvParameterSpec ivSpec = new IvParameterSpec( key );
        cipher.init( Cipher.DECRYPT_MODE, spec, ivSpec );
        return cipher.doFinal( msg );
    }
    
    public static void main( String[] args ) throws Exception {
        String msg = "This is so easy.";
        
        System.out.println( "原字串: " + msg );
        System.out.println( "加密後: " + encrypt( "vegafish12345678" , msg ) );
        System.out.println( "解密後: " + decrypt( "vegafish12345678", encrypt( "vegafish12345678" , msg ) ) );
    }

}
執行結果如下:
原字串: This is so easy.
加密後: KczRl5uSsrgfwWRKpfR5FoKEIVU0jPvxX1VsEYl/jl0=
解密後: This is so easy.

2011-08-31

少子化的感想

少子化對臺灣所造成的影響,就是未來20年的經濟不景氣甚至倒退、生產力被侵蝕、到消亡的地步,已經有很多書籍探討,如《人口減少經濟時代》(ISBN 978-986-788942-3),在此就不多做論述了。

政府為何要人民生育?因為我們追求的是經濟成長率,我們一輩子都活在成長的年代,不管是營業額、GDP。一兩季的營業額負成長,即使是大如台積電的公司,員工、股東們會怎麼看?同樣的,當經濟負成長時,政府就得要擴大公共支出、舉債建設,以便提振景氣。

然而之前的經濟成長是怎麼來的呢?簡言之,龐氏騙局(Ponzi scheme)。從前的人民靠著新加入的勞動人口來推動經濟成長,加入的人比退出的人多,經濟就成長。而臺灣的經濟並不是靠高附加價值產業起家的,加入的人比退出的人少,經濟當然會衰退。

如果公司的營業額負成長達兩年、四年甚至十年,這種股票我們會想買嗎?很明顯的未來,我們已經看到了,只是從沒想過。那麼,我們已經在社會裡面的人要怎麼辦呢? :)

因為人民的短視近利,政客靠著生育補助、教育補助、老人照顧等等,就可以騙到選票。但人民卻忘了最基本的事情:為什麼要領生育補助、老人照顧的錢?

「因為我們和子女、父母相處的時間被剝奪了」

民主國家政府,很擅長利用數字混淆視聽。不論央行和政府如何唬爛,在世界上許多專業的投資者都是用國際金價當成購買力指標,直到現在,各國的幣值、甚至償債能力仍還是用黃金做為結算單位。

1990 臺灣人均收入 TWD 223,860 元,換算美金 USD 8,325 元,購買力相當於 20.8 oz 黃金
2011 臺灣人均假設 TWD 600,000 元,換算美金 USD 20,000 元,購買力相當於 11.4 oz 黃金

臺灣現在的實質薪水,比1990的薪資少了一半,所以雙薪家庭才能負擔一個20年前一個正常家庭的生活。在20年前的傳統是,爸爸出門賺錢,媽媽在家顧小孩、照顧爸媽、公婆。現在則是夫妻兩人去上班,小孩丟給爸媽、保母。這種環境下,不要說注重生活品質的人不想生了,就連想花時間陪小孩的人也沒辦法生。

會有這種「實質薪資下降」的結果原因很多,這邊的空間不夠寫(誤)。人民希望政府達到經濟成長的目標->政府為了達到目標,創造出有利企業賺錢的環境->企業為了追求獲利,會為了穩定的低毛利來源,放棄了投資高附加價值的產品,如創意、設計、藝術產業,甚至為了賺錢壓榨勞工。

我只能說臺灣人的現狀,是自找的啊。

2011-08-24

玩了一下AES加密解密

我將自己寫的程式碼貼上來,這是很簡短的程式,希望高手能稍加提點我自己不足之處。
import javax.crypto.Cipher;

import javax.crypto.spec.SecretKeySpec;

public class TestAES {

public static byte[] encrypt( byte[] msg ) throws Exception {
byte[] key = "vegafish12345678".getBytes(); // key 長度 = 16
return encrypt( key, msg );
}

public static byte[] encrypt( byte[] key, byte[] msg ) throws Exception {
if ( key.length != 16 ) {
throw new IllegalArgumentException( "Key length should be 16." );
}
SecretKeySpec spec = new SecretKeySpec( key, "AES" );
Cipher cipher = Cipher.getInstance( "AES" );
cipher.init( Cipher.ENCRYPT_MODE, spec );
return cipher.doFinal( msg );
}

public static byte[] decrypt( byte[] msg ) throws Exception {
byte[] key = "vegafish12345678".getBytes(); // key 長度 = 16
return decrypt( key, msg );
}

public static byte[] decrypt( byte[] key, byte[] msg ) throws Exception {
if ( key.length != 16 ) {
throw new IllegalArgumentException( "Key length should be 16." );
}
SecretKeySpec spec = new SecretKeySpec( key, "AES" );
Cipher cipher = Cipher.getInstance( "AES" );
cipher.init( Cipher.DECRYPT_MODE, spec );
return cipher.doFinal( msg );
}

public static void main( String[] args ) throws Exception {
String msg = "要被加密的訊息, the text would be encrypted.";

System.out.println( "原始String : " + msg );
System.out.println( "byte[]加密後: " + new String( encrypt( msg.getBytes() ) ) );
System.out.println( "byte[]解密後: " + new String( decrypt( encrypt( msg.getBytes() ) ) ) );
}

}

2011-08-16

Re: [新聞] 台灣生育率跌破1全球最低 (by hedonic.bbs@ptt.cc)

作者: hedonic (黑東尼克) 看板: Gossiping
標題: Re: [新聞] 台灣生育率跌破1全球最低
時間: Mon Aug 15 15:12:29 2011

※ 引述《blackponpon (自我充實)》之銘言:
: 為什麼新加坡在全球經濟不景氣的情況下可以脫穎而出
: 甚至政府還能夠發紅包給人民(不是消費券 那種東西就算了)
: 當政府說"沒有不景氣 只有不爭氣"的時候
: 我只想反問政府一句話:"那你爭氣了嗎?"


心得一下,我有兩位以前的同事到新加坡去工作(大馬僑生),目前都剛剛結婚

新加坡政府鼓勵增產很迂迴。

他鼓勵" 家庭的價值 ",甚麼是家庭的價值呢? 就是族群和諧、階級消除、互相扶持
創造回憶、社會公平。

新加坡的所得稅極低,即使外國人也只有10%,而所得極高,平均是台灣的兩倍,
雖然新加坡人抱怨他們房價上漲了五成,兩房的小家庭要20萬新幣( 大概台幣五百萬)

根據調查,新加坡人有97% 認為它們有能力購買房屋。

所以新加坡政府有很多手段去抑制房屋成為商品,包括年齡限制、轉手限制、諸如此類

第二點則是鼓勵新加坡的國家認同度,鼓勵新加坡人以新加坡國民自豪,大量吸納
外國人才進入,大量人才交換。

一旦年輕人順利成家、安心工作、居住解決,自然就會生養下一代。新加坡的教育相反的
對於高等教育並不是採用無差別升大學方式,平均教育年限並不高( 對台灣而言是很低)。
企業提供大量獎學金( 新加坡大企業有一半以上是國營企業)~~

新加坡的公務員採用面試方式錄用,也是會看顏色看血統看學習紀錄,( 總之不是看你會
不會考試),擔任公務員薪資並不會比民間特別高,(每次區長拿來比較的是新加坡的高官)
,由於新加坡的國營企業太廣泛所以其實所謂的公務員或是在國營事業都是幫李家打工。


現在回過頭來看我們腦殘的中華民國ER 區長以及弱智部下

我們有強調家庭價值嗎?

我們有賦稅公平,受薪階級所得稅低嗎?
我們有高所得環境嗎?
我們有低房價環境嗎?
我們有強調國家認同嗎? ( 好像有ROCER說燒成灰會變成TIWANESE)
我們有保障青年就業嗎? ( 22k.....
我們有優秀的高級公務員嗎?

我另一個同事,夫妻都是台大碩博士,收入兩人年薪破兩百,最近在台北想看個三房的
老公寓,開價幾乎都在兩千以上,中正大安信義他們連問都不敢問。

我們的房屋成為商品投資標的,兒童成為教育鬥爭犧牲品,公共政策成為撒錢途逕,
區長只有口號,部長都找一些阿里不達的廢渣,只會辦口號票選,不然就辦台灣國花博
( 有基隆、新北、新竹、花蓮等等國家參加)。

你叫人家怎麼安心生蛋?

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.124.255.100


我並沒有說新加坡不是獨裁國家。他是民主制度,共產國家。
李家天下控制了新加坡主要的經濟活動,包括公用事業、媒體。( 別忘記這些台灣大部分
也還在KMT手上,當然KMT控制力已經弱化很多了)

新加坡對國宅的控制很細膩,包括格局、族群、每個組屋要按照人口族群比例分配,
比如你是印度人,你要賣掉也只能賣印度人之類,總之嚴格控制各種轉賣。

許多組屋也設定比如結婚才能買,幾口之家才能買之類,另外區位也配合大眾運輸等等

但總之人家是真的再推社會住宅,不像台灣是口水住宅,或是像A7那種去搶農民給財團
在分配給人的不公不義宅。

民主社會一樣可以推公平國宅政策,只是我們的高官每個都是比有錢的,郝龍斌市長
他爸爸一生當兵繁忙之餘還買了七八十塊土地,你認為他會希望房價飆漲還是社會公平?

我住在天龍區,我的周圍一堆法官、老師、國營事業、銀行退休人員,大多有數間房產
你覺得台北人希望房價飆還是平?

2011-08-13

富爸爸窮爸爸 之 現金流遊戲 (Cashflow 202 e-game) 介紹

現金流遊戲這個遊戲已經有十幾年的歷史,其目的是將投資理論(Modern Portfolio Theory)教育給普羅大眾。這個遊戲是由「富爸爸.窮爸爸」系列書籍作者「羅伯特.清崎」所開發,一開始是紙上遊戲,後來演變為電子遊戲的形式。以「寓教於樂」的方式,讓使用者了解近代現實生活之投資理論,有很重要的幫助。

「富爸爸.窮爸爸」系列書籍旨要在提倡一個重要的觀念(轉載自 Wikipedia):「資產就是將錢放進你口袋裡的東西,而負債則是把你口袋的錢拿走的東西。」資產和負債不同的現金流向,會造成不同的財富結果。窮人只通過工作獲取收入,通過消費將掙來錢花出去,沒有任何資產。中產階級通過工作獲取收入,再去購買一些他們認為是資產的負債,然後通過償還負債,花光他們的錢,他們同樣也沒有資產。而富人則通過購買資產來產生收入,再用收入來購買資產,不斷地循環下去,最終獲得大量的財富,實現無需工作也能不斷獲得收入的財務自由狀態。同時,他認為,能真正讓人達到財務自由的,不是工作,也不是金錢,而是能帶來源源不斷現金流的資產

這個遊戲一開始,你扮演一隻老鼠,在現實生活中的財務迷宮繞圈圈(如圖1),無法掙脫這個圈圈,遊戲的目的簡單而言,在於讓玩家賺取到超過支出兩倍之被動收入,就可以逃出財務迷宮,進入財富高速公路,最後實現玩家的夢想。

老鼠賽跑
圖一:老鼠賽跑


實際上,財務迷宮是一個圈圈,老鼠的形象代表一般人,逃不出這個財務迷宮的圈圈,因為一般人總是有了收入,進而支出花費,但從未考慮要增加自己的被動收入。當花費增加,一般人只知道要改變工作、或是增加工時(接外務或打工),而不是先考慮添購能夠產生被動收入的資產。這代表了一般人若是失業、或是某些因素不能、不想工作的時候,就是不斷的吃老本、耗費儲蓄;但如果有足夠的被動收入,即使在不工作的狀況之下,儲蓄仍然會不斷增加,這就是被動收入的美妙之處。

那麼,什麼是可以產生被動收入的資產?在遊戲中只有一種:「各式各樣的房地產,透過收租金的方式,來製造現金流入」。而在現實生活中,可以產生被動收入的資產有很多:例如股票(每年會發配股利)、投資公司、商店或服務(投入資本回收獲利)、不動產如房屋、公寓或土地(透過出租的方式收取租金),其觀念是大同小異的:「用現金,買到一個不需要工作,而會每年,甚至每個月產生錢之標的物」就像會下金蛋的金雞,這就是被動收入。

遊戲進行過程中,走到綠色的格子,代表你有機會可以投資股票、選擇權(option)、或是房地產,遊戲設計者為了簡單化,遊戲中的股票沒有股息(dividend)僅用來賺取資本利得(capital gains);走到深藍色的格子,代表市場有變化,此時可以改變自己的投資部位;走到粉紅色的格子和紫色的格子,代表每月支出增加了,粉紅色代表非理性購物、意外,紫色代表玩家添了一個孩子(這個遊戲並不是提倡不要生孩子,而是告訴玩家,當不了解被動收入的重要時,和孩子相處的時間就會大幅下降,而孩子也不會快樂);當通過黃色或站在黃色的格子,就會獲得一次月收益(表示過了一個月);當走到紫色的格子,代表失業,需要支付一個月的支出,並暫停兩回合,本遊戲的失業機率出奇的高,會讓玩家感受到失業的痛苦(畢竟一般時候不常體會)。

每次有財務狀況的變更(如圖二),就需要更新自己的財務報表,若玩家有會計學(accounting)的基礎,一下就會知道遊戲裡面的報表有兩個:現金流量表(cash flow statement)和資產負債表(balance sheet),若玩家沒有會計學的基礎沒關係,遊戲會一直提示你將這個新的財務狀況歸檔至正確的會計名目下(如圖三)。

財務狀況變更
圖二:財務狀況變更


整理財務報表
圖三:整理財務報表


當玩家一旦取得了每月支出的兩倍被動收入,就可以逃出老鼠賽跑(如圖四)。在現實生活中,當被動收入超過每月支出的時候,就可以不用工作,讓被動收入來養活自己、甚至繼續累積資產,遊戲中訂為支出兩倍,可能是為了增加遊戲困難度之故。

逃出老鼠賽跑
圖四:逃出老鼠賽跑


逃出老鼠賽跑的迷宮之後,代表了完全的財富自由,遊戲中以進入財富高速公路(如圖五)的方式表示,玩家會發現自己可以買得起任何東西、投資失敗也完全不在意等。這邊要解說一下所謂的不在意:「因為被動收入大於投資失敗的損失,在投資心理學(psychology of finance)上會讓人冷靜,不會因為資產損失而患得患失、作出愚蠢判斷」這有些誇張,但不失為一種給玩家一個向財富自由靠攏的願景。

財富高速公路
圖五:財富高速公路


遊戲結束畫面,如圖六。

遊戲結束
圖六:遊戲結束

2011-08-01

中油直營站地圖

此系列地圖中,標示了臺灣中油公司直營加油站的地點與地址,並做以下標示:
黃色:提供刷卡自助加油服務的加油站
綠色:24小時營業的加油站
紅色:提供刷卡自助加油服務,並且24小時營業的加油站

資料來源:台灣中油全球資訊網
各位朋友若發現有任何錯誤、闕漏,請用信件或於地圖上留言的方式告訴我。
您的熱心將是地圖正確的重要因素。

中油直營站地圖(北北基)
中油直營站地圖(北北基) http://goo.gl/yR6Pd


中油直營站地圖(桃竹苗)
中油直營站地圖(桃竹苗) http://goo.gl/dkqP3


中油直營站地圖(中彰投)
中油直營站地圖(中彰投) http://goo.gl/qK61L


中油直營站地圖(雲嘉南)
中油直營站地圖(雲嘉南) http://goo.gl/jr6E8


中油直營站地圖(高屏)
中油直營站地圖(高屏) http://goo.gl/Fx4jE

2011-07-31

如何用 Blendtec 製作芒果奇異果飲料

先讓我們看看這位大叔如何用 Blendtec 把 iPhone4 打成碎片好了。(默)



其實這篇只是用來證明 Blendtec 可以直接把水果打成泥,不用切塊。

材料(2人份):
芒果 x 0.5顆
奇異果 x 3顆
不用加水、不用加糖

步驟:
1. 材料去皮
2. 丟進 Blendtec 並闔上蓋子
3. 按 Cycle Menu 直到螢幕出現 Beverage(飲料)選項
4. 按 Speed 直到螢幕出現 Fruit Drinks 選項
5. 按 Start/Stop 一次
6. 處理過程中,請壓著上蓋
7. 處理完畢後,將成品倒出即得

Blendtec 全貌
Blendtec 全貌


材料一覽
材料一覽


奇異果切半去皮
奇異果切半去皮


芒果去皮
芒果去皮


這麼大塊也可以處理
這麼大塊也可以處理


闔上蓋子
闔上蓋子


選擇 Fruit Drinks
選擇 Fruit Drinks


按下 Start/Stop
按下 Start/Stop


處理中
處理中


不到40秒就處理完畢
不到40秒就處理完畢


成品
成品

2011-05-04

使用 RMaps 記錄路徑並匯出到 Google Maps

RMaps 是 android 的地圖應用程式,一般用在手機無網路連線時,來觀看離線地圖。如何下載並製作離線地圖在 Dr. TYT 的 Android 地圖 有教學,這裡就不贅述了。

但其實很少人知道,RMaps 有如同另一個應用程式 My Tracks 的功能,可以記錄手機移動的路徑,並且可以匯出到 Google maps 做記錄。以下為使用此功能的步驟詳解:

1. 開啟 RMaps,並叫出功能表,點選 Tracks 選項。如圖一所示:

圖一
圖一


2. 欲開始記錄路徑時,點選 Start track record 按鈕。如圖二所示:

圖二
圖二


3. 正在記錄路徑的過程中,會在 android 狀態列顯示一個腳踏車的圖示,使用者可以根據這個圖示知道 RMaps 正在記錄,也可以點選它回到 RMaps 程式中。如圖三所示:

圖三
圖三


4. 路徑記錄完畢之後,點選 Stop 停止記錄。如圖四所示:

圖四
圖四


5. 點選路徑名稱標籤右方的綠色勾勾,該條路徑就會顯示在 RMaps 的地圖上,此步驟只和 RMaps 的顯示有關,若不想顯示路徑記錄可以略過。如圖五、六所示:

圖五
圖五

圖六
圖六


6. 長按路徑名稱標籤,叫出選單後,選擇 Export to KML file。如圖七所示:

圖七
圖七


7. 在步驟6.之後,記憶卡中的 \rmaps\export 目錄下,會看到一個 路徑名稱.kml 的檔案,這就是剛剛所匯出的路徑檔。

8. 在 Google maps 自己建的地圖內,點選 編輯 按鈕。如圖八所示:

圖八
圖八


9. 在地圖的編輯模式下,點選 匯入。如圖九所示:

圖九
圖九


10. 選擇步驟7.所看到的 kml 檔,再按 從檔案上載 按鈕,完成後即可在自建地圖內看到 RMaps 所記錄的路徑了。如圖十所示:

圖十
圖十