2006年9月5日星期二

解讀郵件中的UUEncode附件 (續)

前天說了遇上一個大問題,就是不知解讀UUEncode.今天有了突破性發展.

參考了幾個C#的UUDecode程序後,雖然只有二百行的Source
Code.但是憑我對C#語法皮毛的認識.轉至VB.NET都搞了我一整天.

做測試時,在System.IO下的Stream / MemoryStream / FileStream / Bytes / BytesArray等等統統搬了出來,但最後亦是自己複雜化問題.C#的UUDecode Source Code可看這裡.
Implementation of UUEncoding in C#
我的做法是,用StringBuilder,寫入由BEGIN至END的UU碼,再轉至Bytes.
經UUDecoding後,用FileStream把Bytes再寫成binary File即可.

2006年9月4日星期一

.NET Framework下,如何解碼UUencode?

現在100%根性製作中的ASP.NET版本NNTP Reader已經有樣子看....
解決了效能問題,現在Download 400個Title都只需要最多兩秒,當中最困難是要寫很多Error Exception,例如很多人貼文沒有email或者名字都會出現問題.寫這些Error Handler反而用上我很多時間. 不過當中考量的問題很多.

說真的,ASP.NET的Newsgroup Reader,網上實在少之有少,可參考的,實在不多.但好彩在Microsoft的技術討論區上,多次得到台灣微軟MVP相助.有一些已經解開迷團



1.DataTable 還是DataSet? GridView還是TreeList?
這問題較簡單,一般網上看到的示範都會把DataTable轉至DataSet集合中.
給GridView做DataSource. 但是次製作我只需要一個DataTable,故沒需要使用DataSet.只需使用DataTable,收取所有資料後,轉至DataView便可.不需動輒都用DataSet.
至於Layout方面,考慮到Newsgroup會有[回應]文章,要做到類似Outlook Express般,回覆跟隨主文,必要要用上TreeList,但可惜.NET中沒有TreeList控件,就算有.要把Reference對照文章ID再加入TreeNodes都是十分複雜的事.雖然我嘗試在GridView中加入TemplateField,並放上Treeview,但實際出來的效果並不好.這問題日後再解決.

2. ArrayList還是Array?
這是一個較多面化的問題,兩者很相似,因為應用在不同地方有不同的好處.
以下是MSDN上Array和ArrayList的要點:

- ArrayList 並不保證已經經過排序。進行需要 ArrayList 的作業 (例如BinarySearch()) 之前,一定要先排序 ArrayList
- ArrayList 的容量是可以保存的項目數。ArrayList 的預設初始容量為 0。隨著元素逐漸加入 ArrayList 內,也會視需要透過重新配置的方式自動增加容量。若要降低容量,可以呼叫TrimToSize()或明確地設定Capacity屬性。
- ArrayList 接受 Null 參照 (即 Visual Basic 中的 Nothing) 做為有效值,並允許重複的元素。
- Array 的容量是固定的,ArrayListList 的容量卻是按照需要自動擴充的。如果 Capacity 屬性的值變更,記憶體重新配置和元素的複製會自動完成。
- ArrayListList 提供加入、插入或移除元素範圍的方法。在 Array 中,您一次只可以取得或設定一個元素的值。
- ArrayListList 提供了方法,可以將唯讀和固定大小的包裝函式傳回給集合;但 Array 則否。
另一方面,Array 提供了某些 ArrayListList 所沒有的彈性。例如:
- 您可以設定 Array 的下限,但 ArrayListList 的下限永遠為零。
- Array 可以擁有多個維度 (Dimension),而 ArrayListList 則永遠只有一個維度。
- 特定型別 (Object 以外) 的 Array 具有比 ArrayList 更佳的效能,因為 ArrayList 的元素型別為 Object,而且儲存或擷取實值型別 (Value Type) 時,通常會產生 Boxing 和 Unboxing 的狀況。然而,List 如果不需要重新配置,亦即如果初始容量是清單大小上限的概數,它便具備了與相同型別的陣列相近的效能。

大部分情況下,可以使用 ArrayListList 來取代陣列呼叫;它們比較容易使用,並且一般而言,具有與相同型別的陣列相似的效能。

3.如何做UUDecode?
先前的Base64 Encode已解決,現在的,是我的終極問題,因為這是牽涉到郵件中的附件解碼.
一般NNTP附件都是以UUEncode去篇碼,雖然我已經準確地得到由Begin至End中的編碼,但是怎樣Decode,再送給FileStream已是一個大問題.參考過C語言,PHP語言的Library,憑我的能力去寫一個Class是沒可能的.在Google上找,給DotNET的,同樣是少得可憐...最後在Google上找到一個C#的...我嘗試過Decode相片會出錯誤,不知為什麼.大家可以看看.

uuEncode and uuDecode in VB.NET and C#

2006年7月31日星期一

在Microsoft DotNET上進行NNTP Protocol 開發心得

自幾年前,使用VB6開始一直都有寫過下NNTP Newsgroup Access既o野,一直都未有完成品,因為原因實在太多,效能,亂碼,Bug,等等問題都影響到我進展.上左DotNet後,使過很多NNTP既Library,如Smilla .NET Communication Library,雖然沒有亂碼問題,但效能上實在太差.其次那些較出名的IP*Work , Indy Socket等等,雖然效能可接受,但由於始終都是別人出品,要深層次去控制NNTP Protocol 是很難的. 近日的起心干再次研究....得到台灣Microsoft MVP的幫助,有了進展.

在DotNET上,要寫和Server交流的,都是要使用System.Net.Socket低下的Member.
其中TCPCleint是必須的. 除了要對Socket有了解,亦需要了解System.Text.Encoding的使用方法. 因為和外國不同的是,我們是中文字,需要進行轉碼(下文有解說) ,而外國都是英文,故普遍不用轉行轉碼. 而且當然要了解一下RFC977
這份文件.因為從RFC977,我們可以知道NNTP的Command,Response,以及State Code等等有用資料.因為在網上,即使你用Google Search,要找到DotNET上的NNTP資源實在少得可憐.
故以下是我個人小小心得,希望幫到有需要的人,當然有錯請更正^^

1. NNTP Server 接收的資料都是Bytes,而不是String.
當我們由NNTP Server接收到資料時,其實都是以ASCII編碼的Bytes形態.要顯示的話,需要使用ASCIIEncoding.GetBytes方式去取得
Bytes,並轉至DotNET預設的Unicode 和String.如果不轉的話,就是出現"????" 的問號出現了.

2. 傳送資料給NNTP Server其實也是Bytes
一般我們都會使用TCPClient下的GetStream以Read和Write方法去讀寫,就如第一個Point,在GetStream.Write時,都需要把NNTP Command進行String to Bytes的處理才送出.而部份人會使用System.IO下的StreamWriter去送出資料,可能會問,為什麼StreamWriter不用轉Bytes,其實因為StreamWriter在你送出前,已經自動轉成Bytes,所以至可以直接傳送.

3.什麼是MIME ? 什麼是8Bit Encoding ,什麼是Base64 ?
NNTP文章都一定有Mail Header,而Mail Header中都有MIME資訊, MIME含有Subject , Content-Type 和Content-Transfer-Encoding,例如:
Subject: Word =?Big5?B?VkJBpc5XZWJCcm93c2VysN3DRA==?=
Content-Type: text/plain; charset=Big5
Content-Transfer-Encoding: 8bit
Subject不用多說,是標題
Content-Type是信件型式和編碼
Content-Transfer-Encoding則是傳送編碼
明顯地我們看到Subject是未能正確顯示的,就是因為使用8Bit Encoding關係.
8Bit Encode顯示格式為:
=?encode?c?string?=
=? ?= 為起始和結束
encode 為語系編碼
c 為字串編碼方式,b 為 base64 、q 為 Quoted-printable Code.
"VkJBpc5XZWJCcm93c2VysN3DRA"
就是Base64的方式顯示了。
要轉回正常字串,先依字串編碼轉為ByteArray,再使用 .Net 的 Convert.FromBase64String 依語系轉回來即可。

4.如何處回覆的郵件至原文?
若以 Re: 起始的回覆郵件,都會有References的項目 ,一般顯示為 : <a href="mailto:44cc1cd0$1@news.3home.net">44cc1cd0$1@news.3home.net</a> , 冒號後的,就是原文Message-ID,在NNTP Server中的唯一的.故自然可以依據References去連結原文.

2006年7月12日星期三

Flash與ASP.NET共同作業與數據交流心得

Best practices of Flash工作上,近個多月每天都是處理Flash與ASP.NET的事,技術上很易,但出現的未預期錯誤,比想像中多.在Google上找到的,都是教人怎樣去接收發送數據. 所以這篇文重點不會重於技術上,反之會是技巧上.和大家分享一下,從我過去個多月每天都在100%根性上工作所啟發的心得.Flash雖然可以做到很多很酷的動畫,和網頁程式,如最常見的留言板,討論區等...但直到Flash 8,官方還未有任何Provider供Flash做Database存取,而即使MySQL,Oracle都沒有Connector給Flash,當然我知道有Third Party的Socket Component,可以令到Flash得到該功能,但是價錢不便宜,而且效能未明...故依然需要ASP/JSP/PHP做Backend處理....

大家先可看看Intel Software Network中的Flash and .NET Integration Using ASP.NET
在兩者數據交流上,大可以有三種較容易的,都是以Flash的SendAndLoad方式送出:
1. 把數值放在網址上 (如Data.aspx?Name=Ming&Age=24)
但這方法只適合少量數值,如大量數據的話,更是怪怪的,例如我要傳送一段留言,達三百多字,放在網址上..你有看過嗎? 我沒試過,亦保留會出現overflow的可能性. 當然asp一方很方便地以Request.QueryString的方法就可以得數值是不錯的.

2. 把數值以Array方式放在網址上 (如Data.aspx?Value=1|2|3|4|5)
這是一個比起 (1)較折衷的方法,因為我們可以去掉數值前的Item Name,但會苦了asp的一方,因為asp方面要把整個Array,以Split 方式去分割,並取其Index,而且亦因為沒有Item Name,要記著那個Index是代表那個數值是很痛苦的.
example:
Dim StrData as String = Trim(Request.QueryString("Value")
Dim AryData as Array = Split(StrData,"|")
textbox1.text = AryData(1)
textbox2.text = AryData(2)
.....一直下去....

3.以XML中轉檔案方式.
這是一個不錯的選擇,Flash以XML檔案把數值放在Element中,ASP.NET方面亦容易使用XmlTextReader去取數值. 但從Programming上說,由Flash去產生XML檔亦需要時間,而且如果大量使用者的話,伺服器有一定的影響.

三者都有優缺點,要使用那個,就要看情況.
了解過Flash如何把數據送出後,再看看ASP.NET要注意的地方
1.進行QueryString時,視乎情況,使用Trim把空白除去.
有時可能Flash人員沒有留意這個時,就可能會出現很多誤會的情況.即使使用者沒有故意輸入空白,但亦不排除Flash在定義Variable時大意.Teamwork共中就是互相補漏洞吧...

2. response.write前,加上一句Response.Buffer = True
這是ASP時代很重要的,因為我們都知道ASP和ASP.NET不同的是,ASP.NET是有Precompliation的,故所以效能高於ASP,而處理流程是伺服器執行完成程式後,把結果顯示在瀏覽器上,並不是IE去執行ASP,所以我們把IIS要輸出的資料先寫到緩衝區,是保險的一環.在ASP.NET上,很多人都認為不是必須的,但ASP人員是有責任確保Flash能接收完整數據的.

3.事前先決定存取XML中的那個項目
一個XML中可以有很多Parent和Nodes,而Nodes中,亦分Element , attributes等等,Flash可以有選擇性把數值寫在那裡, 在工作前,要確認Flash把數值是寫在那一部份,像我的工作上的Flash程式員,把數值寫在attributes,但我卻把Function寫了讀Element就真是花了無謂時間.

4. 敬請Flash人員建立標準XML
同樣是重要的,直接影響ASP.NET一方,有些人往往把XML寫到一團槽,建立的是XML檔案,同樣有Tags,Parent,Nodes...但有始卻沒有終,卻往往忘記關閉Parent或其他.導致ASP.NET不能正確辨認.

5.盡可能讓Flash的Action Script以Include方式去執行
Flash一方可以直接在Notepad打開*.VB檔,相信你都希望可以直接打開*.AS吧,不用動輒都要開Flash軟件.

6.Flash應建立一個Debug Handler
假如你不修改Web.config中CUSTOM ERROR MESSAGES的話,當問題出現在ASPX上,都能在瀏覽器出現Debug訊息,或者一般程式人員都慣常使用Error Handler或Try..Catch方式.但Flash不同的是,遇到錯誤,往往只會停在Flash Player上,並不會主動做什麼.更不會傳回任何東西回客戶端.最後只會令ASPX人員呆坐....

不過最後我依然是覺得,有些網頁程式,如討論區,都是交回ASP.NET全權負責吧,我個人並不主張網頁全Flash化,顯然濫用只會更像大陸網頁 (一個網頁有十多條Flash Banner....)
暫時想到的只有這些,是我小小的心得,希望大家在萬事俱備下,可以寫得更得心應手.