2009年12月30日 星期三

未來五年內開發者所需的技能

剛看到這篇有趣的文章,其中提到:
1: One of the “Big Three” (.NET, Java, PHP) - 學會三大巨頭之一(.NET, Java, PHP)
2: Rich Internet Applications (RIAs) - RIA技能(Flash, Flex, JavaFX, Sliverlight)
3: Web development - 網站開發
4: Web services - 網路服務開發
5: Soft skills - 請放眼IT產業未來的觀點,並觀察公司外的走向
6: One dynamic and/or functional programming language - 雖然Ruby, Python目前還不是主流語言,但它們觀念是,所以有朝一日爬升上來時,你會的話就很吃香

2009年11月25日 星期三

免費的雲端防毒軟體 - Panda Cloud Antivirus

免費的雲端防毒軟體
http://www.cloudantivirus.com/en/
以「第一個沒有更新選項的防毒軟體」聞名全球的Panda Cloud Antivirus,能以最快最即時的雲端防護機制來對抗最新最危險的病毒威脅。別說不可能,藉由集體人工智慧的幫助,Panda先進的伺服器群組能在雲端收集來自世界各地用戶的惡意程式資訊,並且自動進行病毒碼辨識,進而將新的惡意程式病毒株在短短幾分鐘內歸檔完畢。集體人工智慧結合了本機電腦偵測技術與即時的雲端掃描機制,能在提供最強大防護的同時,帶給電腦最低程度的資源耗損(僅需消耗20MB的記憶體容量)。

2009年11月11日 星期三

Google發表新的程式語言「Go」

轉載自http://www.ithome.com.tw/itadm/article.php?c=58033:

Google周一(11/10)發表了新的系統程式語言「Go」,以加速程式開發。Go結合了像是Python動態語言的開發速度,以及擁有C及C++語言等編譯語言的效能及安全性,同時也是一個開放源碼計畫。

Google表示,近十多年來運算環境變化很大,但卻沒有新興的系統語言,導致軟體開發跟不上電腦發展速度。例如有愈來愈多的開發人員不喜歡Java及 C++的笨重型態,因而轉向動態的Python與JavaScript語言,而現在受歡迎的系統語言亦未妥善支援基本的垃圾蒐集或平行運算概念。

這也使得Google認為現在值得嘗試新的語言。Go是一個並行的,具垃圾蒐集功能的語言,並可快速編譯。它在單一電腦上可於幾秒內編譯一個大型的Go程式;而且提供一個軟體架構模型以讓相依分析更容易,並避免有過多的檔案及程式庫;Go的型態系統沒有階層,因此不用消耗時間定義各種型態的關係;Go可支援垃圾蒐集、同時執行及通訊;而且Go的主要設計之一就是用來撰寫多核機器上的系統軟體。

Go目前仍在實驗中,Google並鼓勵具冒險精神的開發人員可以試用該語言。雖然Google也希望可以採用Go來撰寫內部使用的伺服器軟體或其他軟體,但由於其功能尚未成熟到可供大規模部署,因此現階段僅進行小幅測試,例如golang.org後端的伺服器就是以Go所撰寫。

Go也是Google員工20%計畫的產物,Google允許員工可花費20%的時間於自己有興趣的專案上,Gmail實驗室亦是源自於該計畫。

------------------------------------------------------------------

GO 官方網站: http://golang.org/

Google IO大會上Guido van Rossum對於GAE的演講

由於python創始人Guido van Rossum被Google收錄進去...所以python可說是google開發的主力,而GAE也是基於python + django的環境改寫而成, 我們來聽聽去年Google IO大會上Guido van Rossum對於GAE的演講

然後也有介紹python的特性與其他相關部分

2009年10月17日 星期六

Flash Loader 載入外部 swf 時 stage=null 的問題

剛剛寫as的時候發生一個問題,由於被載入的swf裡頭有運用stage作場景控制,故被主頁載入時出現 TypeError: Error #1009: Cannot access a property or method of a null object reference.

原因在於被載入的swf在主頁尚未將它加入至場景上時就呼叫了建構子,因此,我們可以運用以下的方法解決:

public function Page05DocumentClass()
{
    if (stage){
        initApp();
    } else {
        addEventListener(Event.ADDED_TO_STAGE, initApp);
    }
}
        
private function initApp(evt:Event=null):void
{
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
}

先判斷stage是否存在,如不存在則以stage.ADDED_TO_STAGE作為啟動的依據。
但...這感覺是bug...

2009年9月10日 星期四

創造「耐心練習周期」(轉)

的確我是一個極度沒有耐心的人,所以要從現在開始訓練...

耐心是心的一種性質,可以藉由蓄意的練習而大幅提升。我發現可以磨練耐心的一個有效方法,就是創造真正的練習周期,也就是在心中設定練習耐心藝術的時間周期。生活本身變成了一間教室,課程叫做「耐心」。

你可以從短短的五分鐘開始,然後逐漸延長你的耐心的容忍度。剛開始的時候,不妨告訴自己:「好,接下來這五分鐘,我不要對任何事情生氣,我要保持耐心。」你將會有驚人的發現。保持耐心的企圖,尤其是你知道只要忍耐一下子,就會立刻加强耐心的容忍度。耐心是那種食髓知味的特質,你將會發現,你確實有能力保持耐心,即使時間長一點也可以。日子久了以後,你甚至會變成一個很有耐心的人。

當我們保持鎮定時,不讓自己生氣或懊惱時,就可以冷靜而堅定地控制行為,這比發怒生氣有效多了。這個讓心靈朝耐心努力的過程簡單易學,重要就是把持自己想發脾氣的情緒,不再鑽牛角尖。

有耐心讓自己得以維持心靈的平衡。没有耐心的話,一件小事就會化為緊急大事,以嘶吼、挫折、傷感情、和高血壓收場。這樣真是不值得,不論你是需要跟孩子、上司、或一個不可理喻的人打交道,如果你不想「為小事抓狂」,改進你的耐心功力,成就高度的EQ,這是最佳有效的調合劑,就從現在開始吧!

2009年7月27日 星期一

前瞻與創意思考

創新事實上是指創意加變革,單單只有創意但未付諸行動,就還不是創新。例如 明基科技董事長 李焜耀 說過“創新是一種行為的習慣,習慣獨特的方法、理念與結果,勇於做自己”,不隨波逐流,不盲從,正是創新的根源。

但是,創新並不是突然靈光乍現就足夠,必須還得包括詳細的分析與系統化的流程一步步實現,然而時代在變,人也在變,整個外在環境都在劇烈變動,組織的管理與運作也必須改變,不過需要改變什麼?什麼需要改變?可以奇異的領導力四個“E”為其重點:

(一) Energy : 高度的幹勁
(二) Energize : 激勵他人的能力
(三) Edge : 制定艱難決策的精準度
(四) Execute : 貫徹執行達成目標的能力

由此可見創新是能夠被管理的,但如何能有效領導創新呢?身為一個創新領導的角色,該員必須要有幹勁,並能影響其他人使他們同樣有幹勁,另外必須要精準不莽撞(瞎忙),並要真正做的到。換句話說,改變與變革必須從領導者本身做起,先革自己的命,在帶領整個企業完成變革大業,整個關鍵在主管思維的改變。邱教授認為可在日常生活中實際做出五種改變:

(一) 閱讀(而非瀏覽)
(二) 溝通(而非命令)
(三) 欣賞(而非排斥)
(四) 寬容(而非封閉)
(五) 思考(而非情緒)

創新立基於四項要素:資源、組織文化、組織氛圍、程序,四種要素都等同重要,必須善加整合才能有機會成功創新。而當條件均完備後,則必須揪出阻礙創新的幾項因子,諸如:策略模糊不清、欠缺事務輕重緩急概念、領導風格過於集權與放任、高階團隊缺乏效率、中階主管協調與溝通能力不足,部門間沒有生氣與缺乏互信等...,排除上述條件後,最後仍需要有效的前瞻性思維,如此才能將成功的機率提高。

2009年6月25日 星期四

適當地運用研發與創新

"研發"囊括了"研究"與"發展",並可細分為三個部分:

1. 基礎研究 - 主要為了增加科學知識,或許沒有後續的商業應用。
2. 應用研究 - 增加特定應用或需求的知識。
3. 發展 - 應用知識產生有用的實體產品。

Sam感覺大部分在台灣的中小企業都是先產生3的想法再回過頭去研究2...至於1基本上是無產值所以不太被重視。因為總是要在最短時間內得到成效,如果不好才能評估改進或淘汰,或許因應各國的風情不同會產生差異性的結果,但從過去歷史的經驗上,很多大賣的產品都不是專門為了商業利益所開發,可能是機緣巧合,也可能只是對該項事物有極大化的熱情,而促使個人與團隊不惜成本去研究,最後出乎意料的受到好評。

日前感謝"大Sam"的關照,有榮幸去參加Google Marissa Mayer的座談會,她也敘述了Google為外人津津樂道的80/20理論。Sam認為,20%的時間拿來計畫員工真正想做的事的確是有其必要,當然公司或許會有很好的idea產生,另一方面也是舒緩了員工的一週內的長期工作壓力,人就如同橡皮筋,久了之後會彈性疲乏,效率越來越低,如果在此能得到一些成就感之類的激勵,將會快速且有效的恢復"彈性",也為公司帶來好績效。

當員工自行利用空閒時間進行基礎研究時,應該要感到相當高興,因為他可能是真正熱愛這份工作,千萬不要認為不能為公司帶來財富就去遏止,機會是隨處可見的,遇到對的人、對的時間,就有很大的機率能夠成功。

2009年6月6日 星期六

Objective-C 初級讀本翻譯

由於目前 Sam 開始寫 iPhone 程式,但又完全不熟悉 Objective-C,所以只能依照 Apple dev center 內的教學流程走,當然也要從 Objective-C 的一些觀念下手,Sam 花了兩天時間將 Learning Objective-C: A Primer 這篇文章翻譯成中文,畢竟有關資源實在太少,也只能希望未來更多人能夠幫忙翻譯裡頭一些好文章,讓大家一起加入 iPhone 開發的行列。

如果翻的不好還請多多見諒。

文章下載

2009年5月29日 星期五

Mircosoft Azure 的野心

有在注意產業相關新聞的人應該都知道微軟已經和Zend(PHP)合作了。很多人可能覺得很奇怪,也有些人認為這樣很好,讓PHP能夠更容易在Windows伺服器上使用...

哪有那麼簡單!!!

Sam 覺得微軟是為了他們的雲端平台Azure,畢竟一開始就落後了Google, Amazon, IBM,想要及時迎頭趕上是蠻麻煩的,於是乎只好搬出這招,打著PHP的光環吸引更多PHP開發者(為數驚人的高市占率),而且其他家平台都是 Java、Python 之類的語言,較為小眾市場或不是那麼容易入門,相對的以商業角度來看,微軟下對了一步險棋。

但就Sam開發的經驗來看,PHP似乎在系統動態套件擴充部份有一點糟糕,有玩過PHP設定的人都知道要把套件 1.重新編譯(Unix-like) 2.套件檔放到lib下然後修改設定檔(Windows) ,不過雲端平台表示碰不到系統,自然就無法安裝這些東西,這是Sam目前比較大的疑問,當然,微軟也有可能做出一套虛擬設定環境,到時候可能會改觀。

相較於其他廠商,以 Google 使用 Python 來看,雖然 3rd Party Library 以往要採 setup.py 安裝,但其實它們都有附上源碼檔案,也就是說你只要把該檔案放到應用程式裡一樣可以叫用 import XXX ,和目前微軟比起來哪個比較方便就見仁見智了。

不過身為使用者的我們還是樂見許多大廠爭相開發平台,畢竟有利無弊,多了許多選擇

2009年5月26日 星期二

GAE ( Google App Engine ) 模式為什麼將來會流行?

一開始寫這篇文章標題時,本來想下"為甚麼GAE( Google App Engine )在台灣乏人問津...",但是與其批判,不如說一些真正吸引廠商或老闆的條件比較實在。

講到GAE就不能不提雲端,雲泛指網路世界,其實中國把Cloud Computing稱作雲運算,但Sam還是覺得台灣翻的好,因為重點是終"端"使用者。Google之所以能夠讓用戶端幾近立即的得到搜尋結果,在於內部程式幾乎都實作了Map和Reduce方法去驅動機器讓資料中心平行同步幫您處裡,才能夠達到如此高的效率(參見Map-Reduce)。 這時候我們開始回歸到現實面,如果您擁有一家軟體開發,或目前已經在提供現上應用服務的企業(無論大小),您會怎麼處理資料? 目前情況不外乎是砸錢設機房、買伺服器、請網管維護、負擔線路費用,或是中小企業租用虛擬伺服器。但如果以上都能省略呢? 俗話說 "打蛇打七寸",既然公司是以軟體與服務為主,我們就應該縮減實體設備造成的負擔。

GAE的聲明便是不需要再負擔實體設備成本(或極小化),只需要專心在軟體構思與服務。GAE採用的技術完全都是OpenSource,並且就算付費,也是使用公用運算(Utility Computing)的計費標準,用多少付多少,不用再像以往為了負載短時間高流量,承擔一整年其餘沒用到的費用。以下幾點為與傳統比較的好處:

1. 風險降低(不用再擔心本地伺服器硬碟毀損,雲端資料中心機器會自動複製到其他台)
2. 擴充、縮減的問題無須考慮(基本上雲端資料中心能夠任意增縮設備,當然這已經不再是您的問題)
3. 成本降低(省下設備維護費用全力開發產品)

目前GAE支援的環境為Windows、Linux、MacOS,也就是跨平台,而編寫語言除了原本的python之外,今年也加入了Java成為第二個支援語言 http://code.google.com/intl/en/appengine/

Sam 目前只有實作python的api,在安裝完GAE SDK與python2.5後便能開始編寫,裡頭大致上是追隨django這個框架的標準,包含設定檔使用yaml,與資料儲存(datastore)採ORM用物件來設定,Google也很貼心的設計了像phpMyAdmin那樣的介面來做資料表管理,而且datastore背後採用BigTable,不用太擔心效率的問題,然後除了官方API(Images, Memcache, Mail, URLFetch, Google Accounts)外,也能夠使用第三方資源庫(3rd party library),系統還能定期排程,真的甚麼事都能處理(當然還是有sandbox規範,像是socket那些不行),並且他們的free quota(免費額度)對於一般企業根本一天不會用到超量(因為非常之大),作網路服務或網站是綽綽有餘。

寫到這裡好像Sam都在幫Google打廣告,但是各位要了解,除了Google外, IBM blue cloud, Amazon EC2, 甚至微軟都在發展這個服務,拿Google來說只是因為它有free support,其它都要付費的...。

依照台灣對國際的資訊速度(差不多慢了一年或兩年),目前還很少人知道這種服務是正常的,過了不久就會像當初Google Adsence一樣在全世界掀起熱潮,只是這頭Cloud Service的小浪在Sam眼中將會是下一波科技海嘯,而未來掌握資料中心與搜尋技術的企業則會領導世界!

Web標準可能讓Flash過氣 ... 嗎?

早上起床看到一篇文章 Opera:Web標準可能讓Flash過氣,大致上是敘述Opera的執行長說下一版HTML網路程式設計語言推出後,可能讓Adobe公司(奧多比)的Flash技術顯得多餘。

當然不可否認的 HTML 5.0 的確新增了許多讓人心動的功能,如:

‧ 本機儲存(Local storage),在個人的電腦上儲存資料的技術。此功能可讓你在離線狀態下使用網頁電子郵件,儲存瀏覽器擴充套件的個人設定。

‧ 影像支援(Video support),讓影片更容易嵌入網頁,並且更容易與Flash等影像技術整合。

‧ 網路工作者(Web workers),此功能讓瀏覽器在背景執行繁雜的處理任務,讓複雜的網路程式完成任務,又能避免造成使用者介面變得太笨重。

另外還有一些標籤更詳細的定義等...不過不要忘記,就算功能再如何增加,還是在處理Client端的事情,而目前flash真正有用的部份在於與Server端溝通,並“動態“的顯示資訊,像是 swfUpload 就是個很好的例子。

反而Sam較為擔心的是 Flex,推出時非常轟動,但目前感覺慢慢在衰退,Sam之前使用的一些感想如下:

1. 檔案笨重: 把所有套件一起編譯,又不好將不同頁面分成數個swf批次載入,導致有些用戶端載入非常久。

2. Flex 能辦到的事,Flash 也做的到。

3. 組件還是一樣不好用。

4. 排版採用類似 Java 的方式,沒錯你可能想吸引 Java 開發者,但 Flash 開發者會慢慢遠離你...

5. 自己定義的語言標準 ... 恩 ... 不與置評。

其實論網路服務實用性 Flex 很低,而被取代性很高。

哪些 Flex 所謂的應用程式拖移功能,事件等動態方式目前 javascript 做不到?而且就使用者而言,原生性的(使用html + javascript)永遠比要安裝外掛 (Flash, java, silverlight)好,尤其是現在 js 引擎速度那麼快!

總之Flash不容易被淘汰,它仍是設計師最快最好呈現的工具,只是以往用Flash開發應用程式的大概得考慮一下換個方式走以後的路。

2009年5月20日 星期三

學習 CakePHP

之前回絕掉一個cakePHP的案子, 實在是因為要寫報告和找資料太忙了...。

說到cakePHP, 最重要的就是 MVC(Model-View-Controller) 的設計模式, 以往由於php是比較近似於程序導向語言, 故大家都會把所有動作與畫面顯示寫在一隻程式上, 當然這樣是很方便的, 不過萬一遇到的不是網站而是大型的網路應用程式, 可能這個做法會讓你非常頭痛, 等到寫幾百隻php時回頭除錯真可形容為"欲哭無淚"。而 MVC 所指的是把 1.資料處裡 2.流程邏輯 3.畫面顯示 分開, 這樣針對不同的功能產生清晰的分類, 維護與除錯就不再是一件惱人的事。

傳統的寫法


MVC的寫法


此外 cakePHP 在資料層(Model)做了物件關連映射 ORM(Object-Relational Mapping) 的處理, 可以以物件導向的方式操作資料庫欄位(做了映射, 欄位變成物件屬性或方法), 對於不熟悉關連資料庫的朋友也是一大福音。

長久以來物件導向與程序導向都各擁有一派死忠者, 但我個人認為並沒有甚麼好擁護的, "適得其所"才是最重要, 一個小型程式不需要把它用大工程的方式進行, 而一項大工程基於良好的時效與後續維護, 也應該採用物件導向而非程序導向。

但說來說去還是沒有好好研究cakePHP, 或許等以後有案子碰到在說, 畢竟重點是觀念而不是技術。

2009年3月30日 星期一

PyPdf 讀取中文Pdf亂碼問題

最近找論文資料常常會下載一堆相關題目的pdf檔然後慢慢消化,不過這樣實在是很浪費時間,所以週末就想說寫一隻程式搜尋資料夾中所有pdf,然後給它關鍵詞,最後能夠顯示這些關鍵詞在哪幾篇pdf的第幾頁中,如此一來就省事多了。

python的好處就是擴充套件多如過江之鯽,當然光pdf就好多個,這裡挑選的是PyPdf.

安裝完成之後先以取出內容文字為主寫出一段程式測試,測試pdf為中文big5編碼,但除了標題encode("big5")能夠正常顯示中文外,內容卻是一片亂碼,於是把每段文字拆解成char再使用hex code列印出來...

0xb8 0xea ... 這不是big5的"資"嗎?表示編碼是正確的阿!為何print就是有錯誤?

於是我使用一個範例字串 zh = "\xb8\xea" ,print出來是"資"沒錯,但 u"\xb8\xea" 加上unicode就會和上面呈現一模一樣的亂碼。原來PyPdf中PageObject extractText()會將所有內容編碼成unicode,所以我們要把unicode反解回來 str.encode('latin-1') ,嗯正常了^^。

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

from pyPdf import PdfFileReader

input = PdfFileReader(file("infosafe.pdf", "rb"))

# Show title from this pdf.
print input.getDocumentInfo().title.encode("big5")

# Total pages.
pages = input.getNumPages()

# Loop to print content.
for i in range(0, pages):
    pageObj = input.getPage(i)
    str = pageObj.extractText()
    
    # The extracted text has been set to unicode, therefore, we should transfer it's format to the normal 'latin-1'.
    print str.encode('latin-1')
    
    """
    # Print hex code.
    for j in range(0, len(str)):
        print hex(ord(str[j]))
    
    break
    """
"""
# This is an example.
zh = u"\xb8\xea".encode('latin-1')
print type(zh)
print zh
"""

2009年3月26日 星期四

妙事一籮筐

這幾天真的很妙~

前天收到一個加拿大台灣留學生請我幫忙寫他們教授出的python作業

今天早上iCloud CEO也發了一封信請我幫忙翻譯(當然不是只有我啦, 還有很多其他中國地區使用者)

內容大概是這樣

算是為了這周平凡無奇的生活添加一點樂趣^^

2009年3月25日 星期三

Python RssParser with MySQL

其實繼上次寫了python資料型態上下集之後,這次應該來寫一下迴圈與條件式等的教學,但是其實那些東西都是廢話,我下一次再把一些注意事項放上來就好了!不然難道你認為if條件式會寫成怎樣??

這次開始從實例下手,之前我寫過Java RssParser,是儲存成檔案的方式,現在用python教大家如何parse Google RSS新聞檔並儲存 發布時間、標題、連結、相關內容 等資訊到MySQL中。

把玩這支程式之前請先安裝兩個函式庫,feedparserMySQLdb(說明)。裡頭都有安裝說明與教學。

By the way, 我的python是2.5版

sql -- 建立資料庫並使用SQL新增下列資料表

CREATE TABLE IF NOT EXISTS `FEED_MSTR` (
 `ID` int(11) NOT NULL AUTO_INCREMENT,
 `DATE` datetime NOT NULL,
 `TITLE` varchar(255) CHARACTER SET utf8 NOT NULL,
 `LINK` text CHARACTER SET utf8 NOT NULL,
 `SUMMARY` text CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`ID`),
 KEY `DATE` (`DATE`,`TITLE`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

RssParser.py

#!/usr/local/bin/python
# -*- coding: utf-8 -*-

# Copyright (C) 2009 Kakapo Studio.
# Author: Sam Wang
# Contact: sam.wang.0723@gmail.com

""" This program can parse any RSS or Atom type file on the internet and put it into database. """

import feedparser
import datetime
import MySQLdb

from time import mktime 

data = feedparser.parse(r"http://news.google.com.tw/news?pz=1&ned=tw&hl=zh-TW&topic=t&output=rss")

conn = MySQLdb.connect(host="localhost", user="root", passwd="********", db="YOUR_DATABASE", charset="utf8")
cursor = conn.cursor()

# Loop to get data.
param = []
for item in data.entries:

   # Make tuple to timestamp.
   ts = mktime(item.updated_parsed)
   # Transfer to datetime format.
   dt = datetime.datetime.fromtimestamp(ts)

   ntime = dt.strftime("%Y-%m-%d %H:%M:%S")
   ntitle = item.title.encode('utf8')
   nlink = item.links[0].href.encode('utf8')
   nvalue = item.summary_detail.value.encode('utf8')
  
   # Insert into param.
   param.append((ntime, ntitle, nlink, nvalue))

# Write to database.
sql = "insert into FEED_MSTR(DATE, TITLE, LINK, SUMMARY) values(%s,%s,%s,%s)"
cursor.executemany(sql, param)
  

cursor.close()
conn.close()

稍微說明一下 cursor.executemany(sql, param) 那段,executemany可以用字串當樣板然後給他list或tuples動態給予參數,假設一次update 3筆資料, 每筆有2個欄位, list儲存方式要像如此[(x,x) , (y,y), (z,z)]...這樣update時就會分開成len(list)的執行次數, 每次update len(list[i])個欄位了

2009年3月24日 星期二

最新十大透支健康行業

轉載自http://big5.xinhuanet.com/gate/big5/news.xinhuanet.com/health/2006-08/18/content_4977708.htm

很高興IT業榮獲榜首...說這句話的同時壽命又少了0.01歲...

但是國外工程師好像都很悠閒, 每天穿短褲, 到處有零食與電動...而且人家的創意與技術就是比我們強...
總有一天我也要打造這樣的環境...

健康透支十大行業依次為:

1、IT
2、企業高管(含民營企業主)
3、媒體記者
4、證券
5、保險
6、出租車司機
7、交警
8、銷售
9、律師
10、教師
調查發現,精神壓力過大,生活節奏過快,飲食和生活不規律,是這十大行業的人群嚴重透支健康的主要原因。

關于壓力來源,31%的受調查者反映最大的壓力源自家人,19%的人反映是性生活。受調查者認為,面對源自領導同事和經濟生活方面的壓力,未婚青年面對創業、婚姻的擔憂,已婚人士頭頂巨額按揭房款和教育支出,只能繼續透支健康。

2009年3月19日 星期四

不知道要下什麼標題

就像美國總統歐巴馬一樣面對AIG發放紅利氣到嗆到, 今早我也發生了一樣的事, 剛出門騎車就拋錨所以只好等附近的機車行開門就把車牽過去麻煩他修一下...以下為對話(對方可能不是老闆但我還是叫老闆):

我: "老闆, 我機車掛點了可以幫我看一下嗎?"
老闆: "...."(準備開店中...)
我: "老闆, 我把機車推上去歐"(把機車推到維修區)
老闆: "你推上去幹麼...我有叫你推上去嗎?"
我: "...拍謝"(把機車倒退回去)
我: "請問大概什麼時候能好?"
老闆: "要等啦!你先留你的聯絡方式"
我: "不能幫個忙先看一下嗎?我等等還有事"
老闆: "急什麼, 留下機車鑰匙修好在和你說!"
我: "..."(留下鑰匙默默走人)

走掉得路上我越想越氣...媽的...我是叫你修免費的歐!長得一副好像我欠他的樣子!

後來中午接到電話回去看換下來的零件, 變成一個比較菜的技師在修, 態度很好也會和我說哪裡燒壞等等還會指給我看...早上那個王八蛋在一旁看電視...我當然是青了他一下...不過他好像沒看到。

這件事讓我回想到以前當兵的時候, 我是二級廠補給士, 想當然爾各連的裝備都是要找我補料或更換, 自然權力就很大, 尤其是老了之後, 別連要上來申請料件都還要帶吃的喝的才行, 那時候的我在他們眼中一定也是這樣, 而我去聯保廠的時候對學長姐也是差不多, 好像是一種風氣吧!差別只在於他們修裝備不需要付錢而已, 是國家出。

這件事氣歸氣...反正只要車子修好了就好~我還向那個菜鳥技師要了電話以後只找他修

2009年3月9日 星期一

PHPMailer utf-8郵件主旨亂碼問題

日前使用PHPMailer發送utf-8格式的中文郵件時, 發現收件夾內接收的郵件均為亂碼, 而且連帶影響到郵件的html內文, 原因在於E-Mail標準格式中表頭的部分不允許使用雙位元的文字(也就是中文等...), 所以必須使用mb_encode_mimeheader()函式將雙位元文字編碼為單位元字串。

但是因為mb_encode_mimeheader()預設的字串編碼為西方ISO-8859-1, 所以如果你的編碼中文字為UTF-8就必須使用mb_internal_encoding()將內部預設編碼改為UTF-8。

<?php
mb_internal_encoding('UTF-8');    // 內部預設編碼改為UTF-8
$mail->Subject = mb_encode_mimeheader($_POST['title'], "UTF-8");
$mail->Body = $_POST['content'];
?>

2009年3月6日 星期五

研究開發iPhone應用程式

最近和歐拔聊天, 想說來玩一下iPhone的開發, 雖然我自己去年就買了G1 Dev版, 本來要加入Android的行列, 但好死不死今年又買了MacBook而且實在逃不出它的魔掌...

首先要先從Objective-C開始學, 基本上宣告和一些寫法有點差異, 但畢竟大體上結構差不多, 只是又要自己管理記憶體有點煩就是了, 畢竟Java寫久都覺得釋放記憶體這種動作應該是VM應該做的吧~

最近也找了蠻多相關文件, 但是早上這個讓我比較興奮, 是史丹福大學的iPhone開發課程講義耶!http://www.stanford.edu/class/cs193p/cgi-bin/index.php, 裡面的程式碼與pdf都可以下載來用, 網路真是太棒了

2009年3月4日 星期三

Python 資料型態(下)

4. Dictionaries -> Dictionaries擁有鍵與值的對照, 類似Java中的Map類

>>> demo = {'a':123, 'b':456, 'c':789} # 使用“:“分隔鍵與值
>>> demo['a']
123

當然也可以不必在一開始就做指定動作, 能夠在不同位置指定內容讓Dictionaries擁有了極大的彈性

>>> demo = {}  #  指定一個空殼給demo
>>> demo['a'] = 123
>>> demo['b'] = 456
>>> demo
{'a' : 123, 'b' : 456}

巢狀內容的呼叫

>>> demo = {'name':{'first':'Bob', 'last':'Smith'},
      'job':['dev', 'mgr'],
      'age':40.5}
>>> demo['name']['first']
'Bob'

依照鍵值排序顯示內容:事實上我們可以發現Dictionaries顯示出的內容並不會從左到右排序, 所以有以下方法可供參考

>>> D = {'a':1, 'c':2, 'b':3}
>>> Ks = D.keys()
>>> Ks
['a', 'c', 'b']
>>> Ks.sort()
>>> Ks
['a', 'b', 'c']
>>> for key in Ks:
   print key, '=>', D[key]
a => 1
b => 2
c => 3

上面的方法是先取出鍵值陣列排序在依序取出值, 但還有一種更簡單的方式就是使用內置的sorted()方法

>>> for key in sorted(D):
    print key,'=>',D(key)
a => 1
b => 2
c => 3

5. tuples -> tuples 是python中一個特別的元件, 你可能不曾在別的語言中碰過, 它類似List但卻無法更動順序, 也無法在宣告之後指定參照

>>> T = (1, 2, 3, 4)
>>> len(T)
4
>>> T + (5, 6)
(1, 2, 3, 4, 5, 6)
>>> T[0]
1
>>> T[0] = 2   # 如果想指定參照會出現Exception

Traceback (most recent call last):
 File "<pyshell#4>", line 1,in <module>
   T[0]=2
TypeError:'tuple' object does not support item assignment

事實上tuples並不像List那麼常被用在練習中...但是tuples的好處就是在於"不可更動性"

6. Files -> 檔案操作物件通常一般不會包含在核心物件之內, 古怪的是你無法使用敘述式建立它們, 唯一的方法只有呼叫open()函式

寫入資料

>>> f = open('data.txt', 'w')    #開啟data.txt, 'w'為寫入write模式
>>> f.write('Hello\n')       # 寫入字串
>>> f.write('world\n')
>>> f.close()      # 關閉檔案flush剛剛寫入的資料

讀取資料

>>> f = open('data.txt')  # 也可以在型態上加上'r'
>>> data = f.read()  # 讀取函式read(), 但其實也可以使用 for text in f 來讀
>>> data
'Hello\nworld\n'
>>> print data
Hello
world

其他還有一堆類似Files物件的工具, 譬如pipes, fifos, sockets, keyed-access files, object persistence, descriptor-based files, relational and object-oriented database interfaces等, 以後陸續有學習到再做介紹。

Python 資料型態(上)

Python 有一個特性, 就是變數的宣告不需要使用強型態, 你可以指定 a = 2, 也可以在下一行改變成 a = 'sample', 包括陣列存放都可以使用多種不同型態的變數例如 a = [123, 'abc', 1.23]。

介紹一下 Python 核心物件內含的資料型態

1. Numbers -> 整數(integer), 含小數的數字(floating-point numbers), 另外像是一些長整數(unlimited-precision “long” integers), 複雜的數字(complex numbers)與固定精度的小數(fixed-precision decimals)等...。

範例:

>>> 123 + 456   # 整數相加
579
>>> 1.5 * 4    # 小數運算
6.0
>>> 2 ** 100   # 2的100次方
1267650600228229401496703205376L

另外有一些有趣的功能, 例如把一個高精度的小數用 print 顯示的話, 用戶只會看到部份好辨認的位數

>>> 3.1415 * 2  # 完整精度
6.2830000000000004
>>> print 3.1415 * 2 # 使用者好觀看的數字
6.283

Learning Python (Oreilly 出版) 的作者Mark Lutz說道 if something looks odd, try showing it with a print statement. (如果某樣東西看起來很莫名奇妙, 請嘗試使用print將它顯示出來)

2. Strings -> 字串, 基本上你可以將字串敘述成多個字元組合成的陣列, 譬如 'Spam' 就等於一個 ['S', 'p', 'a', 'm']。

範例:

>>> S = 'Spam'
>>> len(S)   # 字串長度
4
>>> S[0] # 該字串的第一個字元
'S'
>>> S[1]  # The second item from the left
'p'

也可以使用另外一些方式取出字元

>>> S[-1]  # 最後一個字元
'm'
>>> S[len(S)-1]  # 用總長減去一(麻煩的作法)
'm'

如果要取出範圍

>>> S[1:3]  # 取出從第一個到從頭數第三個
'pa'
>>> S[1:]  # 第一個字元以後
'pam'
>>> S[:-1]  # 最後一個字元以前
'Spa'

Python 中字串也可以用乘法運算

>>> S * 8  # 重複顯示8次
'SpamSpamSpamSpamSpamSpamSpamSpam'

字串相加

>>> S + 'xyz'  # 字串合併
'Spamxyz'

另外字串也有一些相關函式

>>> S.find('pa')   # 找尋比對字串出現位置
1
>>> S
'Spam'
>>> S.replace('pa', 'XYZ')   # 取代 'pa' 為 'XYZ', 但請注意原本字串不會被更動
'SXYZm'
>>> S
'Spam'
>>> line = 'aaa,bbb,ccccc,dd'
>>> line.split(',')  # 拆解字串為陣列
['aaa', 'bbb', 'ccccc', 'dd']
>>> S.upper( )  # 轉為大寫
'SPAM'
>>> line = 'aaa,bbb,ccccc,dd\n'
>>> line = line.rstrip( )   # 去除右方空白字元, 如同trim()
>>> line
'aaa,bbb,ccccc,dd'

3. List -> 集合, 不需指定長度並可容納不同型態的物件

>>> L = [123, 'spam', 1.23]
>>> len(L)  # List 長度
3
>>> L + [4, 5, 6]   # 串接List
[123, 'spam', 1.23, 4, 5, 6]
>>> L.append('NI')   # 新增一個元素到最後面
>>> L
[123, 'spam', 1.23, 'NI']
>>> L.pop(2)   # 將L[2]移除並返回值
1.23
>>> L      # "del L[2]" 一樣可以達成刪除目的
[123, 'spam', 'NI']
>>> M = ['bb', 'aa', 'cc']
>>> M.sort( )   # 正向排序(小到大)
>>> M
['aa', 'bb', 'cc']
>>> M.reverse( )  # 反向排序(大到小)
>>> M
['cc', 'bb', 'aa']

巢狀List

>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> M[1]
[4, 5, 6]
>>> M[1][2]
6

還有一點蠻有趣的就是在中括號內寫迴圈與條件式, 個人認為能省下很多行程式碼的寫法

>>> col2 = [row[1] for row in M]  # 取出M中每一個元素的第1個元素(0,1,2...)
>>> col2
[2, 5, 8]

>>> [row[1] + 1 for row in M]  # 取出M中每一個元素的第1個元素並加上一
[3, 6, 9]

>>> [row[1] for row in M if row[1] % 2 == 0] # 判斷元素中2的倍數
[2, 8]

未完待續...

2009年3月3日 星期二

什麼是 Python?

Python的創始人為Guido van Rossum。在1989年聖誕節期間的阿姆斯特丹,Guido為了打發聖誕節的無趣,決心開發一個新的指令碼解釋程式,作為ABC語言的一種繼承。之所以選中 Python(大蟒蛇的意思)作為程式的名字,是因為他是一個Monty Python的飛行馬戲團的愛好者。

就這樣,Python在Guido手中誕生了。實際上,第一個實作是在Mac機上。可以說,Python是從ABC發展起來,主要受到了Modula-3(另一種相當優美且強大的語言,為小型團體所設計的)的影響。並且結合了Unix shell和C的習慣。

雖然 Python 可能被粗略地分類為「指令碼語言」(script language),但實際上一些大規模軟體開發計劃例如 Zope、Mnet 及 BitTorrent,Google 也廣泛地使用它。 Python 的支援者較喜歡稱它為一種高階動態編程語言,原因是「指令碼語言」泛指僅作簡單編程任務的語言,如 shell script、JavaScript 等只能處理簡單任務的編程語言,並不能與 Python 相提並論。

此外,由於 Python 對於 C 和其他語言的良好支援,很多人還把 Python 作為一種「膠水語言」(glue language)使用。使用 Python 將其他語言編寫的程式進行整合和封裝。 在 Google 內部的很多專案使用 C++ 編寫性能要求極高的部分,然後用Python叫用相應的模組。

Python是一門跨平台的指令碼語言,Python規定了一個Python語法規則,實作了Python語法的解釋程式就成為了Python的直譯器,我們用的比較多的是C版本的Python,也就是使用C語言實作的Python直譯器,除此之外還有使用Java實作的Jython和使用.NET實作的 IronPython,這些實作可以使Python使用者充分利用己有的Java及.NET資源。

同時,Python支援幾乎所有常用的作業系統,包括:Windows/DOS、Macintosh、Linux 及 FreeBSD。及很多不常用的作業系統,包括AIX、AS/400 (OS/400)、BeOS、OS/2、OS/390與z/OS、Palm OS、PlayStation與PSP、Psion、QNX、RISC OS、Series 60、Sparc Solaris、VMS、VxWorks、Windows CE或Pocket PC、Sharp Zaurus、MorphOS等。

可擴充性可說是Python作為一種編程語言的特色。新的內置模組(module)可以用C 或 C++寫成。而我們也可為現成的模組加上Python的介面。Python可以使使用者避免過分的語法的羈絆而將精力主要集中到所要實作的程式任務上。

因此Python具有非常龐大的程式庫,透過它們可以快速完成絕大部分常用的任務,如:從某個URL中獲取資訊、正則運算式、獲得某個檔案或字串的MD5特徵字串、多執行緒、XML及HTML的分析等。

Python也被稱為是一門清晰的語言。因為它的作者在設計它的時候,總的指導思想是,對於一個特定的問題,只要有一種最好的方法來解決就好了

摘錄自http://zh.wikipedia.org/w/index.php?title=Python&variant=zh-tw

2009年3月2日 星期一

HTML 5.0

W3C據說2004年就開始推動5.0草案, 但是我想根本沒有什麼人知道這件事, 直到最近Apple Sarfari 4 beta版釋出之後, 看見其中新功能支援HTML5.0影音標籤才赫然驚覺。Google一下才知道5.0是近期最大的改版行為, 目標是在2010年之前,HTML 5的正式版將面世,目標是把這種超文字標示語言(markup language) 帶往今天的豐富媒體網路環境,以新型的應用程式設計介面,控制影音內容。

其中一些改變例如引入了一整套全新的元素來讓構建頁面變得更加簡單與直接使用video, audio之類的標籤描述影像與音效嵌入等...詳細資訊可以參考這篇http://www.wowbox.com.tw/blog/article.asp?id=2446

最近剛好也寫到一篇報告, 內容是有關數位出版, 大部分的權力也是被西方組織或是出版社壟斷, 甚至積極想鉅資吞食華文市場。 所以我的夢想是希望華語地區的人也能團結(雖然中國人真的有夠鬆散), 我們也來創立一個組織, 擁有以華文為主的標準, 讓外國人學中文學到欲哭無淚...哈哈

2009年2月26日 星期四

Flash的鳥問題

這幾天用Flash做事老是碰到一堆鳥問題, 首先是前一版本編輯的class拿來cs4使用會有“The name of this class conflicts with the name of another class that was loaded”, 表示類別名稱有衝突, google一下之後, 把系統時間用NTPClock校正再重新除錯就沒問題, 這部份還好...。

昨天重灌了cs3, 為什麼呢?因為cs4 bug實在太多了, 例如像是MovieClip裡有很多文字欄位, 整個編輯的速度就會慢到不像話, 但換回去之後麻煩才大, 首先把原本的fla存成cs3格式, 打開cs3後相當順暢, Ctrl + Enter compile過程也很順利, 放到網站上, 咦...怎麼某一部份的元件就是無法addChild上去?原本還以為程式寫錯, 但是本機執行一切正常, 網路上就會有問題, 找到今天才想到會不會是版本, 開啟cs4重新編譯放上去後...正常= =, 差點跌到在座位前。

然後之前flp的檔案cs4也沒有了, 硬是要用AIR作一個檔案管理的組件放在cs4中, 又不好操作。所以最後還是換回cs3比較保險。

感覺Adobe也開始和微軟一樣想靠軟體亂改版賺錢...大公司的詬病!總是想把使用者榨乾

2009年2月18日 星期三

程式語言版本的相容性

雖然Sam不會因為程式語言版本相容問題而去學習一種語言, 但最近的情況的確困擾了我。

首先是前年ActionScript2.0晉升3.0, 完全變成一種類Java語言, 當然2.0之前的概念已不復見, 即使這樣但看見優化多倍的效能時還是得盡力去學習, 目前也在專案當中使用, 事實上對於像Sam這種物件導向起家的工程師來說如此的改變再好不過, 因為有Java的底子所以學起來事半功倍, 但對於那些程序導向的工程師就...

然後PHP6的改變, 最恐怖的就是資料庫這段上面統一了(使用PDO), 不再像以前一樣每種資料庫要調用不同的module, 基於oo的立場是很好的改變但對大多數現在線上仍然使用php4, 5的朋友就是惡夢了, 表示你們要砍掉重練!

其他的變革像是:

1.支援Unicode

2.Register Globals將被移除

3.Magic Quotes 將消失

4.Safe Mode Out

5.類別內的Var宣告變成public

6.Return by Reference will error

7.Freetype1 and GD1 support 將不見

8.dl() 加載extension Libs現在被移到 SAPI

9.一些Extension的變更

10.告別ASP風格的啟始標籤

而重點是php6效能不一定比php5好, 所以國內大概也都不會換成php6, 下場應該和Windows Vista一樣。

再來, 我最近很努力的想學python(因為這個語言很簡單上手, 直譯式語言, 可以作到幾乎任何事情, 跨平台, 有規則的約束撰寫縮排等...), Google和Youtube都把python當成開發語言之一(NASA也是), 可以用document執行, 也能用script在終端運作, 可以套用不同的library寫出視窗軟體, 也能寫網頁, 以上已經表示它很強了, 另外還有加速器。

記得去年國外某知名linux討論區評選python榮登年度最佳語言, 國內市場上應用的卻很少, 最近幾年有在某些大專院校研究所聽到在使用而已。Anyway, 我想要得就是它的簡單中帶著強大, 有時候我只是單純的想寫出某些功能卻還是要用Eclipse在那裡搞來搞去實在很煩, 所以就想說不如來學一下python, 沒想到它也改版為3.01, 而且官網上說

Python 3.0 (a.k.a. "Python 3000" or "Py3k") is a new version of the language that is incompatible with the 2.x line of releases.

講到這裡我不知道要該哭還是該笑, 學最新版本的感覺有很多套件來不及搭配, 但是還好他的教學頁面裡有蠻多補充http://docs.python.org/3.0/, 還是來花時間研究一下好了。

總之最近都東一個西一個語言在大幅度的更新, 真是無言~

2009年2月7日 星期六

一些php網頁驗證小技巧

一般而言坊間教學書上對於登入驗證這塊都沒有說明的很詳細, 但其實還有一些技巧需注意, 雖然這些技巧並不能讓你網站100%安全, 但是至少能夠防範"輕易"的被誤用或連結.

例如說處理表單的php來源照理來說應該要是表單的html等, 如果不判斷來源, 就能夠使用一些機器人隨意新增或修改資料, 下段程式判斷時否有來源網頁, 有的話是否是你設定的網頁.

<?php
$referrer = $_SERVER['HTTP_REFERER'];
if($referrer == '' || strpos($referrer, 'your_php.php') == false){        // 判斷來源網頁
    die('來源網頁錯誤');
}
?>

至於登入很多人可能會忘記要驗證當初登入的瀏覽器與IP位址, 你可以在登入時註冊一個session為如下:

<?php
$_SESSION['userAgent'] = $_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
?>

如果要使用cookie記憶長時效, 為了不讓cookie被破解我們會做一些混淆動作, 但要還原卻又很困難, 所以我們把混淆後的cookie記錄在資料庫中, 並設定時效, 每次瀏覽需要驗證的頁面時都去比對, 直到cookie過期失效.

<?php
$cookie = md5($date.$mail.$identify.rand(0, 1000000));
$cookieexpiry = (time() + 21600);
setcookie('memberVerify', $cookie, $cookieexpiry); //時效驗證
?>

如果有看過我之前破解一些網站的文章就知道上述方法還是能夠被手動取代, 但至少不會輕易讓門外漢利用!

2009年1月22日 星期四

HP Scrawlr 幫你偵測網站安全性

今天朋友傳了一個軟體給我玩, 主要是這隻程式會用盡辦法去入侵你輸入的網站, 也就是SQL Injection, 以香港AAStock來作測試, 發現一堆頁面都可以被攻擊, 也能掃出資料表內容...實在很可怕。

但是我是那種唯恐天下不亂的人, 所以搞不好能拿來幹些見不得人的事 :P

下載HP Scrawlr

2009年1月15日 星期四

去除UTF-8 BOM表頭的InputStreamReader

如果你曾經使用Java遇過讀一些文字檔前面出現??等亂碼的話, 表示該份文件有加入bom(byte order mark), 基本上bom的用途原本是用來讓程式辨別該份文檔的編碼格式, Microsoft在Windows 2000以後的Notepad存UTF-8的檔案會加上 BOM(Byte Order Mark, U+FEFF), 主要是因為UTF-8和ASCII是相容的, 為了避免使用者自己忘記用甚麼存, 造成UTF-8檔案用 ASCII 模式開看到是亂碼, 所以在檔案最前面加上BOM.

看到這裡可能有很多人會開始%#~!微軟...

但是碰到問題總是得解決的, 下面這個改寫InputStreamReader的UnicodeInputStreamReader就能夠讓你免去上述煩惱, 所有功能仍然和InputStreamReader相同, 只是在constructor中加入判斷bom表頭的機制, 使用PushbackInputStream當讀取到相關格式時能夠移動檔案開始位置.

使用方式: BufferedReader in = new BufferedReader(new UnicodeInputStreamReader(new FileInputStream(file), encode));

UnicodeInputStreamReader:

package com.progking.io;

import java.io.IOException;
import java.io.PushbackInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import sun.nio.cs.StreamDecoder;

public class UnicodeInputStreamReader extends InputStreamReader
{
   private static final int BOM_SIZE = 4;
   private final StreamDecoder decoder;
   private PushbackInputStream pushBack;
   private String encode;
   private String defaultEnc;

   public UnicodeInputStreamReader(InputStream input, String defaultEnc) throws UnsupportedEncodingException
   {
       super(input);
       try {
           this.defaultEnc = defaultEnc;
           pushBack = new PushbackInputStream(input, BOM_SIZE);
           init();
       } catch (Exception e) {
           e.printStackTrace();
       }
       decoder = StreamDecoder.forInputStreamReader(pushBack, this, encode);
   }

   private void init() throws IOException
   {
       byte[] bom = new byte[BOM_SIZE];
       int n, unread;

       // 初始讀取一次
       n = pushBack.read(bom, 0, bom.length);

       // 比對表頭
       if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) {
           encode = "UTF-32BE";
           unread = n - 4;
       } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) {
           encode = "UTF-32LE";
           unread = n - 4;
       } else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) {
           encode = "UTF-8";
           unread = n - 3;
       } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) {
           encode = "UTF-16BE";
           unread = n - 2;
       } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) {
           encode = "UTF-16LE";
           unread = n - 2;
       } else {
           // 如果沒有找到任何表頭, 則退回長度等於原先總長
           encode = defaultEnc;
           unread = n;
       }
       System.out.println("has BOM=" + ((unread == n) ? false : true) + ", encode=" + encode + ", read=" + n + ", unread=" + unread);
       // 計算應該退回多少byte
       if (unread > 0)
           pushBack.unread(bom, (n - unread), unread);
   }

   public String getEncoding()
   {
       return encode;
   }

   public int read() throws IOException
   {
       return decoder.read();
   }

   public int read(char cbuf[], int offset, int length) throws IOException
   {
       return decoder.read(cbuf, offset, length);
   }

   public boolean ready() throws IOException
   {
       return decoder.ready();
   }

   public void close() throws IOException
   {
       decoder.close();
   }
}