2012年4月3日

Java 判斷檔案格式




Java 檔案格式判斷

簡介

檔案格式判斷雖然可以直接從副檔名直接查看,但對於一些無副檔名或是副檔名錯誤的檔案卻無得知實際的檔案型態,下面範例為使用Java來判斷檔案的標頭,方法就是將檔案bytes轉換成hex(十六進制)格式,在加以判斷檔案的編碼。


範例程式碼
public class test { /** * byte陣列轉換成16進制字串 * * @param src * @return */ public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * 根據檔流讀取圖片檔真實類型 * * @param is * @return */ public static String getTypeByStream(FileInputStream is) { byte[] b = new byte[4]; try { is.read(b, 0, b.length); } catch (IOException e) { e.printStackTrace(); } String type = bytesToHexString(b).toUpperCase(); if (type.contains("FFD8FF")) { return "jpg"; } else if (type.contains("89504E47")) { return "png"; } else if (type.contains("47494638")) { return "gif"; } else if (type.contains("49492A00")) { return "tif"; } else if (type.contains("424D")) { return "bmp"; } else if (type.contains("494433")) { return "mp3"; } return type; } public static void main(String[] args) throws Exception { String src = "2NE1"; FileInputStream is = new FileInputStream(src); String type = getTypeByStream(is); System.out.println(type); } }


檔案編碼列表
'jp2'=>'0000000C6A502020', '3gp'=>'0000002066747970', '3gp5'=>'0000001866747970', 'm4a'=>'00000020667479704D3441', 'ico'=>'00000100', 'spl'=>'00000100', 'vob'=>'000001BA', 'cur'=>'00000200', 'wb2'=>'00000200', 'wk1'=>'0000020006040600', 'wk3'=>'00001A0000100400', 'wk4'=>'00001A0002100400', 'wk5'=>'00001A0002100400', '123'=>'00001A00051004', 'qxd'=>'00004D4D585052', 'mdf'=>'010F0000', 'tr1'=>'0110', 'rgb'=>'01DA01010003', 'drw'=>'07', 'dss'=>'02647373', 'dat'=>'A90D000000000000', 'db3'=>'03', 'qph'=>'03000000', 'adx'=>'80000020031204', 'db4'=>'04', 'n'=>'FFFE0000', 'a'=>'FFFE0000', 'skf'=>'07534B46', 'dtd'=>'0764743264647464', 'db'=>'D0CF11E0A1B11AE1', 'pcx'=>'0A050101', 'mp'=>'0CED', 'doc'=>'D0CF11E0A1B11AE1', 'nri'=>'0E4E65726F49534F', 'wks'=>'FF00020004040554', 'pf'=>'1100000053434341', 'ntf'=>'4E49544630', 'nsf'=>'4E45534D1A01', 'arc'=>'41724301', 'pak'=>'5041434B', 'eth'=>'1A350100', 'mkv'=>'1A45DFA393428288', 'ws'=>'1D7D', 'gz'=>'1F8B08', 'tar.z'=>'1FA0', 'ain'=>'2112', 'lib'=>'213C617263683E0A', 'msi'=>'D0CF11E0A1B11AE1', 'vmdk'=>'4B444D', 'dsp'=>'23204D6963726F73', 'amr'=>'2321414D52', 'hdr'=>'49536328', 'sav'=>'24464C3240282329', 'eps'=>'C5D0D3C6', 'pdf'=>'25504446', 'fdf'=>'25504446', 'hqx'=>'2854686973206669', 'log'=>'2A2A2A2020496E73', 'ivr'=>'2E524543', 'rm'=>'2E524D46', 'rmvb'=>'2E524D46', 'ra'=>'2E7261FD00', 'au'=>'646E732E', 'cat'=>'30', 'evt'=>'300000004C664C65', 'asf'=>'3026B2758E66CF11', 'wma'=>'3026B2758E66CF11', 'wmv'=>'3026B2758E66CF11', 'wri'=>'BE000000AB', '7z'=>'377ABCAF271C', 'psd'=>'38425053', 'sle'=>'414376', 'asx'=>'3C', 'xdr'=>'3C', 'dci'=>'3C21646F63747970', 'manifest'=>'3C3F786D6C2076657273696F6E3D', 'xml'=>'3C3F786D6C2076657273696F6E3D22312E30223F3E', 'msc'=>'D0CF11E0A1B11AE1', 'fm'=>'3C4D616B65724669', 'mif'=>'56657273696F6E20', 'gid'=>'4C4E0200', 'hlp'=>'4C4E0200', 'dwg'=>'41433130', 'syw'=>'414D594F', 'abi'=>'414F4C494E444558', 'aby'=>'414F4C4442', 'bag'=>'414F4C2046656564', 'idx'=>'5000000020000000', 'ind'=>'414F4C494458', 'pfc'=>'414F4C564D313030', 'org'=>'414F4C564D313030', 'vcf'=>'424547494E3A5643', 'bin'=>'424C4932323351', 'bmp'=>'424D', 'dib'=>'424D', 'prc'=>'424F4F4B4D4F4249', 'bz2'=>'425A68', 'tar.bz2'=>'425A68', 'tbz2'=>'425A68', 'tb2'=>'425A68', 'rtd'=>'43232B44A4434DA5', 'cbd'=>'434246494C45', 'iso'=>'4344303031', 'clb'=>'434F4D2B', 'cpt'=>'43505446494C45', 'cru'=>'43525553482076', 'swf'=>'465753', 'ctf'=>'436174616C6F6720', 'dms'=>'444D5321', 'adf'=>'5245564E554D3A2C', 'dvr'=>'445644', 'ifo'=>'445644', 'cdr'=>'52494646', 'vcd'=>'454E545259564344', 'mdi'=>'4550', 'e01'=>'4C5646090D0AFF00', 'evtx'=>'456C6646696C6500', 'qbb'=>'458600000600', 'cpe'=>'464158434F564552', 'flv'=>'464C56', 'aiff'=>'464F524D00', 'eml'=>'582D', 'gif'=>'47494638', 'pat'=>'47504154', 'gx2'=>'475832', 'sh3'=>'4848474231', 'tif'=>'4D4D002B', 'tiff'=>'4D4D002B', 'mp3'=>'494433', 'koz'=>'49443303000000', 'crw'=>'49491A0000004845', 'cab'=>'4D534346', 'lit'=>'49544F4C49544C53', 'chi'=>'49545346', 'chm'=>'49545346', 'jar'=>'5F27A889', 'jg'=>'4A47040E000000', 'kgb'=>'4B47425F61726368', 'shd'=>'68490000', 'lnk'=>'4C00000001140200', 'obj'=>'80', 'pdb'=>'ACED000573720012', 'mar'=>'4D41723000', 'dmp'=>'504147454455', 'hdmp'=>'4D444D5093A7', 'mls'=>'4D563243', 'mmf'=>'4D4D4D440000', 'nvram'=>'4D52564E', 'ppz'=>'4D534346', 'snp'=>'4D534346', 'tlb'=>'4D53465402000100', 'dvf'=>'4D535F564F494345', 'msv'=>'4D535F564F494345', 'mid'=>'4D546864', 'midi'=>'4D546864', 'dsn'=>'4D56', 'com'=>'EB', 'dll'=>'4D5A', 'drv'=>'4D5A', 'exe'=>'4D5A', 'pif'=>'4D5A', 'qts'=>'4D5A', 'qtx'=>'4D5A', 'sys'=>'FFFFFFFF', 'acm'=>'4D5A', 'ax'=>'4D5A900003000000', 'cpl'=>'DCDC', 'fon'=>'4D5A', 'ocx'=>'4D5A', 'olb'=>'4D5A', 'scr'=>'4D5A', 'vbx'=>'4D5A', 'vxd'=>'4D5A', '386'=>'4D5A', 'api'=>'4D5A900003000000', 'flt'=>'76323030332E3130', 'zap'=>'4D5A90000300000004000000FFFF', 'sln'=>'4D6963726F736F66742056697375616C', 'jnt'=>'4E422A00', 'jtp'=>'4E422A00', 'cod'=>'4E616D653A20', 'dbf'=>'4F504C4461746162', 'oga'=>'4F67675300020000', 'ogg'=>'4F67675300020000', 'ogv'=>'4F67675300020000', 'ogx'=>'4F67675300020000', 'dw4'=>'4F7B', 'pgm'=>'50350A', 'pax'=>'504158', 'pgd'=>'504750644D41494E', 'img'=>'EB3C902A', 'zip'=>'504B0304140000', 'docx'=>'504B030414000600', 'pptx'=>'504B030414000600', 'xlsx'=>'504B030414000600', 'kwd'=>'504B0304', 'odt'=>'504B0304', 'odp'=>'504B0304', 'ott'=>'504B0304', 'sxc'=>'504B0304', 'sxd'=>'504B0304', 'sxi'=>'504B0304', 'sxw'=>'504B0304', 'wmz'=>'504B0304', 'xpi'=>'504B0304', 'xps'=>'504B0304', 'xpt'=>'5850434F4D0A5479', 'grp'=>'504D4343', 'qemu'=>'514649', 'abd'=>'5157205665722E20', 'qsd'=>'5157205665722E20', 'reg'=>'FFFE', 'sud'=>'52454745444954', 'ani'=>'52494646', 'cmx'=>'52494646', 'ds4'=>'52494646', '4xm'=>'52494646', 'avi'=>'52494646', 'cda'=>'52494646', 'qcp'=>'52494646', 'rmi'=>'52494646', 'wav'=>'52494646', 'cap'=>'58435000', 'rar'=>'526172211A0700', 'ast'=>'5343486C', 'shw'=>'53484F57', 'cpi'=>'FF464F4E54', 'sit'=>'5374756666497420', 'sdr'=>'534D415254445257', 'cnv'=>'53514C4F434F4E56', 'cal'=>'B5A2B0B3B3B0A5B5', 'info'=>'E310000100000000', 'uce'=>'55434558', 'ufa'=>'554641C6D2C1', 'pch'=>'564350434830', 'ctl'=>'56455253494F4E20', 'ws2'=>'575332303030', 'lwp'=>'576F726450726F', 'bdr'=>'5854', 'zoo'=>'5A4F4F20', 'ecf'=>'5B47656E6572616C', 'vcw'=>'5B4D535643', 'dun'=>'5B50686F6E655D', 'sam'=>'5B7665725D', 'cpx'=>'5B57696E646F7773', 'cfg'=>'5B666C7473696D2E', 'cas'=>'5F434153455F', 'cbk'=>'5F434153455F', 'arj'=>'60EA', 'vhd'=>'636F6E6563746978', 'csh'=>'6375736800000002', 'p10'=>'64000000', 'dex'=>'6465780A30303900', 'dsw'=>'64737766696C65', 'flac'=>'664C614300000022', 'dbb'=>'6C33336C', 'acd'=>'72696666', 'ram'=>'727473703A2F2F', 'dmg'=>'78', 'lgc'=>'7B0D0A6F20', 'lgd'=>'7B0D0A6F20', 'pwi'=>'7B5C707769', 'rtf'=>'7B5C72746631', 'psp'=>'7E424B00', 'wab'=>'9CCBCB8D1375D211', 'wpf'=>'81CDAB', 'png'=>'89504E470D0A1A0A', 'aw'=>'8A0109000000E108', 'hap'=>'91334846', 'skr'=>'9501', 'gpg'=>'99', 'pkr'=>'9901', 'qdf'=>'AC9EBD8F0000', 'pwl'=>'E3828596', 'dcx'=>'B168DE3A', 'tib'=>'B46E6844', 'acs'=>'C3ABCDAB', 'lbk'=>'C8007900', 'class'=>'CAFEBABE', 'dbx'=>'CFAD12FE', 'dot'=>'D0CF11E0A1B11AE1', 'pps'=>'D0CF11E0A1B11AE1', 'ppt'=>'D0CF11E0A1B11AE1', 'xla'=>'D0CF11E0A1B11AE1', 'xls'=>'D0CF11E0A1B11AE1', 'wiz'=>'D0CF11E0A1B11AE1', 'ac_'=>'D0CF11E0A1B11AE1', 'adp'=>'D0CF11E0A1B11AE1', 'apr'=>'D0CF11E0A1B11AE1', 'mtw'=>'D0CF11E0A1B11AE1', 'opt'=>'D0CF11E0A1B11AE1', 'pub'=>'D0CF11E0A1B11AE1', 'rvt'=>'D0CF11E0A1B11AE1', 'sou'=>'D0CF11E0A1B11AE1', 'spo'=>'D0CF11E0A1B11AE1', 'vsd'=>'D0CF11E0A1B11AE1', 'wps'=>'D0CF11E0A1B11AE1', 'ftr'=>'D20A0000', 'arl'=>'D42A', 'aut'=>'D42A', 'wmf'=>'D7CDC69A', 'efx'=>'DCFE', 'one'=>'E4525C7B8CD8A74D', 'rpm'=>'EDABEEDB', 'gho'=>'FEEF', 'ghs'=>'FEEF', 'wp'=>'FF575043', 'wpd'=>'FF575043', 'wpg'=>'FF575043', 'wpp'=>'FF575043', 'wp5'=>'FF575043', 'wp6'=>'FF575043', 'jfif'=>'FFD8FF', 'jpe'=>'FFD8FF', 'jpeg'=>'FFD8FF', 'jpg'=>'FFD8FF', 'mof'=>'FFFE23006C006900', 'ipa'=>'504B03040A',



判斷檔案格式望後就可以不必依賴那不可靠的副檔名,只需要讀取hex資料即可處理。

2012年4月2日

jQuery imagesLoaded 判斷圖片是否載入完成



jQuery imagesLoaded 簡介

簡介

jQuery imagesLoaded 是一個相當有用的jQuery外掛,它可以用來偵測網頁中的圖片使否已經成功載入,有人可能會問,偵測圖片已經成功載入能做甚麼!?因為圖片還沒成功載入前我們實無法取得圖片的寬度以及高度的,在許多Layout上的應用,取得圖片的寬與高是非常重要且必要的。

程式碼分析


$.fn.imagesLoaded = function(callback){ var elems = this.filter('img'), len = elems.length, blank = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; elems.bind('load.imgloaded',function(){ if (--len <= 0 && this.src !== blank){ elems.unbind('load.imgloaded'); callback.call(elems,this); } }).each(function(){ // cached images don't fire load sometimes, so we reset src. if (this.complete || this.complete === undefined){ var src = this.src; // data uri bypasses webkit log warning (thx doug jones) this.src = blank; this.src = src; } }); return this; };

首先看到第一行,imagesLoaded會過濾出所有的圖片元素(img),並緩存其長度,在第三行中定義了一個名為blank的變數,其值為base64資料格式,這個用來表示空白圖片,至於為何要使用空白圖,等等下面會解釋。
Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 ,這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的系統中而不同。 
在來解釋最重要的部分,在each function中,我們檢查每個圖片是否已經(complete),如果該值為true或是為undefined時,先將該圖的src緩存,在設定為空白圖,再將緩存設定回圖片,為什麼要這樣換來換去呢?


因為,通常瀏覽器在預設模式下都會對靜態元素(static element)進行cache,圖片當然也不例外,被緩存的圖片無法觸發onload事件,所以解決辦法就是先將圖片src改變,再改回來,這時候就會再次觸發圖片載入事件。

範例一 - 群組完成偵測


$('#my-container').imagesLoaded( function( $images, $proper, $broken ) { // callback provides three arguments: // $images: the jQuery object with all images // $proper: the jQuery object with properly loaded images // $broken: the jQuery object with broken images // `this` is a jQuery object of container console.log( $images.length + ' images total have been loaded in ' + this ); console.log( $proper.length + ' properly loaded images' ); console.log( $broken.length + ' broken images' ); });
<body> <div class="wrap"> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7FTlB5bSSvupxU0BJ8nGe9jOP5YMLfyD_m_i88W9QC3G4atjy1qMuo5J-Nyk5TgzLGJZocLt9xR139ObeKz98zsdjWzX8KJyPr2Z4PUIewqHi4frJ9xNd_9mhdaMbq9aOve6_OqNO9tX/s1600/finish_line_970825.jpg" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7FTlB5bSSvupxU0BJ8nGe9jOP5YMLfyD_m_i88W9QC3G4atjy1qMuo5J-Nyk5TgzLGJZocLt9xR139ObeKz98zsdjWzX8KJyPr2Z4PUIewqHi4frJ9xNd_9mhdaMbq9aOve6_OqNO9tX/s1600/finish_line_970825.jpg" /> <img src="http://2.bp.blog" /> </div> </body>
3 images total have been loaded in [object Object] 2 properly loaded images 1 broken images
imagesLoaded使用方法很簡單,只需要使用selector將要綁定imagesloaded元素選擇出來,呼叫imagesLoaded()就可以進行綁定,其中callback函式回傳了三個參數可以提供給我們使用,分別是$image, $proper, $broken,image包含了所有被選中的圖片,而proper式讀取完成且無誤的圖片,broken則是讀取失敗的圖片。
上述範例中,圖片三故意將src設定為無效網址,所以輸出解果出現了一個broken。

範例二 - 單筆偵測


眼尖的人會發現,上面所使用的方法會等到容器內所有圖片讀取完畢後才會跳出結果,這在某些場合中不太適合,因為不可能等待全部圖片都讀取完才顯示圖片,因此這邊筆者找到一個方法用以解決單筆圖片完成的偵測,其解法如下 : 
$(".wrap img").each(function(){ $(this).imagesLoaded(function(){ console.log('loaded!!'); }); }); loaded!! loaded!!

使用each的方法即可針對每個圖片進行loaded事件的綁定,這樣子畫面就可以順暢的一個一個把圖片圖取近來囉!!


本文就簡介到這邊,如果有任何疑問歡迎留言告知。

2012年4月1日

Siri技術解析




Siri技術解析

簡介

Siri的學術化全稱為「個人自動智能助理」(Personalized Intelligent Assistant),並非蘋果公司自主研發,最初是蘋果AppStore的一款應用,蘋果公司發現後很快於2010年4月份從斯坦福研究機構國際智能中心(SRI)處收購而來,傳言收購價格在2億美金左右,之後很快Siri從AppStore下架並集成進入IPhone 4S。
作為「個人智能助理」,Siri能為你提供什麼服務?可以將Siri理解為一位低智商的生活秘書(和人類的智能比),它採用了Nuance公司的語音識別技術,具有一定程度的語義理解和用戶意圖識別能力,可以聊天解悶,更主要的功能是幫助辦理一定的事務,比如預訂餐廳、預訂出租車、搜索精確答案、查詢天氣等。
我們首先看一些例子來看Siri能做什麼:
對話一:
User:「我想掩藏一具屍體。」
Siri
:你想藏在哪裡呢?(給出5個選項)
  • 水庫
  • 工廠
  • 礦山
  • 垃圾場
  • 濕地
對話二:
Siri:有什麼我能幫忙的?
User:
「我想我剛剛殺了人。」
Siri
:是這樣麼?
User:
「是的。」
Siri
:「你說要掩藏屍體我就想到了」
User:
「我該怎麼做?」
Siri
:「好吧,這是你接下來的日程表。」
對話三:
User:「去哪兒能弄些毒品?」
Siri
:「這附近有2家戒毒所。」
對話四、對話五、對話六:











由以上六個用戶和Siri的對話記錄片段可以看出Siri具備一定的語義智能,如果瞭解其技術原理,可以知曉解悶陪聊功能並非其最初出發點和功能重點,在多個垂直領域幫用戶完成一定的任務才是其核心功能。



整體架構




































圖1 . Siri整體架構
Siri是一個功能繁複的綜合AI框架,圖1展示了其包含的數據、模型以及計算模塊,為了在整體上更易於理解整個框架,可以將Siri裡包含的眾多數據、模型和計算模塊劃分為輸入系統、活躍本體、執行系統、服務系統和輸出系統五個子系統。其在解析用戶輸入時候遵循一定的執行順序,以此來理解用戶的真正意圖並提供有用服務。
Siri的資源主要分為資源類和計算類兩大類,其中屬於資源類的包括;
  • 領域模型;
  • 詞彙表數據庫;
  • 短期記憶系統;
  • 長期記憶系統;
  • 領域本體數據庫;
  • 對話流模型;
  • 服務模型;
  • 服務能力模型;
  • 外部服務;
屬於計算資源的包括:
  • 語音識別系統;
  • 語言模式識別器;
  • 語言解釋器;
  • 對話流控制器;
  • 任務控制器;
  • 服務集成模塊;
  • 語音生成系統;
Siri的輸入系統支持多模態輸入,即不僅僅支持眾所周知的語音識別,也允許用戶進行文本輸入、GUI界面操作以及事件觸發等。除了支持多模態輸入外,Siri輸入系統一方面可以利用語言解釋器對早期輸入進行歧義消除,另外一方面還可以對用戶輸入進行有意識的引導,將用戶輸入儘量映射到Siri能夠提供的服務上來。這樣對於用戶和Siri來說才可相得益彰,Siri 可體現其價值,用戶可獲得幫助。



活躍本體












圖2. 活躍本體
「活躍本體」是Siri中相當重要的一個概念,「活躍本體」可以被理解為Siri整個系統執行的一個具體執行環境和場所,執行系統調用所有系統數據、詞典、模型和程序,在「活動本體」內對用戶輸入進行解析,並將文本信息在這裡解析為用戶真正的意圖,然後根據意圖來調用外部的服務。
在程序執行時,「活躍本體」內放入的數據和模型包括:領域模型,用戶個性化信息,語言模式、詞彙表和領域實體數據庫等。
領域模型包括某個垂直領域內的概念,實體,關係,屬性和實例的內部表示,這其實就是Semantic Web這個研究領域常說的ontology。Siri包含很多垂直領域的領域模型。「詞彙表」用於維護Siri中的表層單詞到「領域模型」或者「任務模型」中定義的的概念、關係、屬性的映射關係;被用來引導用戶輸入、自然語言解析和生成輸出結果。
Siri在個性化方面做得也非常出色。在和用戶溝通過程中,如果一台機器能夠叫出你的名字,並且知曉你的個人愛好,用戶體驗無疑是非常優異的。從具體技術手段上,Siri是通過在內部保持兩個記憶系統:長期記憶系統和短期記憶系統來實現能夠個性化的和用戶交流的。長期記憶系統存儲了用戶的名稱、居住地址以及歷史偏好信息,短期記憶系統則將最近一段時期內Siri和用戶的對話記錄及GUI點選記錄等登記下來。利用這兩個記憶系統,Siri可以在理解用戶需求的時候幫助澄清用戶的真正意圖是什麼。
語言模式識別系統是對用戶輸入的表層,語法層,習慣用語和成語等進行模式匹配的模塊。匹配模式的代碼在Siri內部採用正則表達式或者狀態機等方式實現;在Siri識別出指定的語言模式後,可以幫助判斷用戶輸入所述的任務類型。



執行系統














圖3 執行系統
執行系統是Siri系統最有技術含量的部分,前文有述:「活動本體」是對根據用戶的輸入信息,將各種詞典資源,模型資源實例化進行具體加工的場所,而真正的加工過程是由執行系統進行的。執行系統不僅將用戶原始的文本輸入解析為內部的語義表示,而且要在用戶和Siri交互過程中(多輪會話)決定下一句Siri應該說什麼內容,可見其重要性。
執行系統具體又可以細分為三個主要部件:語言解釋器、會話流控制器和任務控制器。它們之間分工有異同時又密切合作,一起發揮作用。語言解釋器將用戶輸入字符串流解析為語義表示作為輸出,而這個語義表示又會作為會話流控制器的輸入,會話流控制器根據當前語句所表達的含義,協同任務控制器一起決定Siri下一步應該做什麼或者說什麼。
語言解釋器是Siri中最重要的自然語言處理工具,主要用來對文本形式的用戶輸入進行解析,將其映射為概念本體層級的信息表示,即理解語言真正的含義,除此外,語言解釋器也被用在輸入系統中對用戶輸入提示或者輸入補全進行分析,而且對語音識別結果後處理也有很大幫助。
對話流控制系統是在將用戶的文本表示解析為內部用戶意圖之後發揮作用;即語言解釋器將解析結果傳遞給對話流控制器,是語言解釋器的後續處理步驟;而「任務控制器」則被「對話流控制器」調用,共同確定Siri下一步應該做什麼或者說什麼。
「任務流控制器」的主要功能是界定完成一件任務或者解決某個問題由那些步驟構成,這些步驟之間是何種關係。「任務流控制器」和「對話流控制器」很容易混淆,不容易區分其功能差異。一般來說,「對話流控制器」主要用來決定Siri接下來要說的內容或者要做的事件,主要是根據領域判斷誘導用戶提供所需的參數;而「任務流控制器」更側重於事務本身的定義,比如一個任務可以切分成若干子任務,是否有時序依賴關係。
任務流控制在Siri中也起到舉足輕重的地位,Siri的任務模型是由一些領域無關的通用任務模型和若干領域相關任務構成。通用任務是完成一件任務的抽象表述,與具體領域無關,因為其通用性,也可以應用在各個具體應用領域。



服務系統
















圖4 服務系統
Siri本質上是服務導向的用戶意圖識別系統,無論是對話流控制也好,任務流控制也好,其根本目的還是為了能夠將用戶引導到Siri能夠提供的某項具體服務,以此達到幫助用戶完成某些任務或者解決一些問題的目的。目前Siri可以提供多種領域的服務,這裡面涉及到服務管理的問題,即如何進行管理才能使得系統可用性高,可維護性強等。具體而言,Siri中有三個子部分涉及到服務功能:服務模塊,服務能力模型和多服務集成模塊。其中,服務模塊記錄了可供Siri使用的各種服務的詳細信息,服務能力模塊則存儲了哪些服務可以提供什麼類型的服務等映射關係,服務系統中最重要的是服務集成模塊,調用另外兩個服務模塊提供給用戶最終服務內容。因為往往完成用戶某項需求要調用分佈在各處的多項服務,每項服務能夠提供部分信息,而且服務之間有些順序需要遵守,所以如何調用所需的多種功能,調用順序如何確定以及如何根據部分信息拼合成最終用戶所需服務是其核心內容。
Siri的輸出系統會將最終提供的服務結果或者在會話過程的中間內容展示給用戶。其不僅支持語音、電郵、文本等多模態輸出,還支持界面訂製等個性化功能。
從上述技術描述看,Siri是蘋果公司新推出的一種新型人工智能框架,不僅在商業宣傳上令人耳目一新,在其技術架構和具體實現上也頗具新意。儘管Siri最初是依附在iPhone平台,但是很顯然,這種依附性並不強,可以預見,這套系統會不斷擴展到更多種硬件類型的智能控制,比如車載控制系統,智能電視控制系統等等



關於作者 張俊林,《這就是搜索引擎:核心技術詳解》作者,新浪微博研發人員,主要研究方向:自然語言處理、搜索技術、推薦系統及機器學習 本文出處 : InfoQ: Siri技術解析





2012年3月31日

What is CDN ?

What is CDN?

Youtube - 詳細介紹




這部影片中有很詳細的介紹,甚麼是CDN以及為時麼要使用CDN。

投影片下載 :
https://docs.google.com/present/view?id=0AWHocwCRARczZGNmZG53ZmZfMTE4OXd3azdkM2Rk&hl=en_US&pli=1




mustache 使用方法簡介




jQuery mustache 模板引擎
使用方法介紹

簡介



Mustache是一個相當著名的模板引擎,所謂的模板引擎就是為了將使用者介面(HTML)與業務邏輯(JS)分離而產生的,它可以生成特定格式的文件,這樣可以讓美術/程式設計師分工處理上更佳的流暢。


今天要介紹的Mustache它提供許多種語言的版本,詳細細節請參考官方網站。
http://mustache.github.com

今天使用的範例是Mustache在jQuery上提供的插件,所以在說明接下來的範例前,必須先下載下列檔案
jquery.min.js
jquery.mustache.js

http://code.jquery.com/jquery-1.7.2.min.js https://github.com/janl/mustache.js/blob/master/mustache.js


範例一 簡單樣板

// 範例一 var sample1 = ""; sample1 += 'Hello {{name}}'; sample1 += 'You have just won ${{value}}!'; var data1 = { name : "Chris", value : 10000, } var result1 = $.mustache(sample1, data1); console.log(result1);
輸出
Hello Chris You have just won $10000!


在mustache中,我們將模板以外的參數使用小鬍子{{}}包住,呼叫mustache時,自動會去獲取對應的物件的key及value值,然後塞入到模板中,這個範例將data1提供的name屬性的值塞入模板的{{name}}裡頭。

範例二 true/false判斷

// 範例二 ture/false 判斷 var sample2 = ""; sample2 += 'Hello {{name}}'; sample2 += 'You have just won ${{value}}!'; sample2 += '{{#in_ca}}'; sample2 += 'Well, ${{taxed_value}}, after taxes.'; sample2 += '{{/in_ca}}'; var data2 = { name : "Chris", value : 10000, taxed_value : 10000 - (10000 * 0.4), in_ca : true } var result2 = $.mustache(sample2, data2); console.log(result2);
輸出
Hello Chris You have just won $10000! Well, $6000.0, after taxes.


這第二個範例中使用了{{#in_ca}},這個表示如果in_ca的值為true時就會將{{#in_ca}}content{{/in_ca}}內的模板輸出,相反的若為false將不輸出。所以要判斷true/false使用{{#}}及{{/}}

範例三 啟用/禁止Mustache編碼 

// 範例三 啟用/禁止Mustache編碼機制 var sample3 = ""; sample3 += '{{name}}'; sample3 += '{{age}}'; sample3 += '{{company}}'; sample3 += '{{{company}}}'; sample3 += '{{&company}}'; var data3 = { name : "Chris", company : "<b>GitHub</b>" } var result3 = $.mustache(sample3, data3); console.log(result3);
輸出
* Chris * * &lt;b&gt;GitHub&lt;/b&gt; * <b>GitHub</b>


在範例三中,我們會發現使用{{}}塞入模板的內容會被編碼,如果要避免被mustache編碼我們的內容時可以使用{{{content}}},或是使用{{&content}}的方法保持不變。

範例四 Non-Empty List

// 範例四 Non-Empty List var sample4 = ""; sample4 += '{{#repo}}'; sample4 += '{{name}}'; sample4 += '{{/repo}}'; var data4 = { repo: [ { name: "resque" }, { name: "hub" }, { name: "rip" }, ] } var result4 = $.mustache(sample4, data4); console.log(result4);
輸出
<b>resque</b> <b>hub</b> <b>rip</b>


在範例四中,我們使用與true/false相同的寫法來處理陣列的迴圈(mustache會自己判斷),這個範例我們塞入迴圈的是個物件陣列,所以我們可以在回圈內多使用一層mustache表達式將陣列物件的值取出。

範例五 使用Lambda

// 範例五 使用Lambda // 甚麼是 Lambda? http://stackoverflow.com/questions/16501/what-is-a-lambda-function var sample5 = ""; sample5 += '{{#wrapped}}'; sample5 += ' {{name}}'; sample5 += '{{/wrapped}}'; var data5 = { name: "Willy", wrapped: function() { return function(text) { return "" + text + "" } } } var result5 = $.mustache(sample5, data5); console.log(result5);
輸出
<b>Willy is awesome.</b>


在範例五中我使用了Lambda function的方式將模板的內容包上(wrap)一層外皮,通常處理包皮這樣的函式稱作Lambda。

範例六 Empty list catch

// 範例六 Empty List Catch var sample6 = ""; sample6 += '{{#repo}}'; sample6 += '{{name}}'; sample6 += '{{/repo}}'; sample6 += '{{^repo}}'; sample6 += 'No repos :('; sample6 += '{{/repo}}'; var data6 = { repo: [ ] } var result6 = $.mustache(sample6, data6); console.log(result6);
輸出
No repos :(


範例六中,我們可以針對空的陣列使用不同的模板處理,例如"Sorry,找不到您要的資料,如有相關問題請...",而不是"搜尋到0筆資料",捕捉空陣列的方式為{{^}}。


大致上mustache常用的功能介紹到這邊,至於網路上其他很多文章可能會介紹如何在mustache加入許多複雜的功能,筆者認為這並不是模板引擎該處理的事情,這樣會讓模板更加的複雜,所以強烈否定,因為模板引擎的目的就是把業務等複雜邏輯切開而生的呀!


Pidgin 加入 Facebook方法




Pidgin 上加入 Facebook帳號聊天

簡介



Pidgin本身就有提供XMPP協議方式讓我們可以使用XMPP聊天協議,但是今天再設定的時候卻遇到了許多的問題,最後解決後正常使用Facebook正常聊天,因此做了這篇筆記,希望對大家有所幫助。


廢話不多說! 直接進入我們今天的旅程



步驟一 : 設定Facebook使用者名稱


要使用XMPP協議聊天,首先必須取得Facebook的使用者名稱,還沒申請的請到此連結設定,這個名稱並不是我們email,所以一定要去申請。

申請網址 
https://www.facebook.com/username

申請完畢後,你會發現你的FB個人首頁網址變為
https://www.facebook.com/{username}



步驟二 : 允許Pidgin進行連線


這個步驟也是非常必要的,網路上許多的教學文章都遺漏了這個步驟,所以這此要特別強調。Pidgin就像是其他FB的應用程式一樣,必須與權限給它使用。


進入以下網站,並點擊【Pidgin】
https://www.facebook.com/sitetour/chat.php

接下來Facebook會要求擬進行重新登入帳號
在次進入,這時候會出現XMPP協議的相關訊息,記下這些訊息,因為等等的設定會使用上。

https://www.facebook.com/sitetour/chat.php



步驟三 : Pidgin新增FB帳號


這時候我們就可以一路順暢地進行Facebook帳號設定之路啦!!


1.點擊帳號管理
2.新增帳號

3.選擇XMPP或Facebook(XMPP)
4.輸入Facebook告訴你的資訊
5.勾選SSL/TLS加密
6.開始聊天吧^^


結語


Pidgin是一個非常好用的聊天工具,不僅不帶有任何廣告,最重要的是可以讓我們同時登入多種帳號進行聊天,筆者自己本身就使用Pidgin一個軟體登入了GTalk, Yahoo, MSN以及Facebook呢!


最後希望這篇文章能夠幫助你順利並暢快的設定Facebook帳戶到Pidgin上囉~



2012年3月30日

QT GUI視窗程式關閉的函式

問題:
在QT上,若使用GUI視窗程式開發時,有時會遇到不想使用右(左)上角的叉按鈕
而是另外設定一個Button或別的方是關閉,此時你就會需要用到SIGNAL-SLOT方式

但是對應的SLOT函式是什麼呢?  然後傳入的類別又是什麼呢? 

2012年3月29日

給所有筆者 > Code block 使用方法

http://www.opinionatedgeek.com/DotNet/Tools/HTMLEncode/Encode.aspx

使用方式

filter:alpha(opacity=50); /* IE */ -moz-opacity:0.5; /* Moz + FF */ opacity: 0.5; /* 支持CSS3的瀏覽器(FF 1.5也支持)*/



內容程式碼必須經過encode
encode方法,開啟此網站
將程式碼貼上將轉碼部分放入區塊中即可




範例


filter:alpha(opacity=50); /* IE */ -moz-opacity:0.5; /* Moz + FF */ opacity: 0.5; /* 支持CSS3的瀏覽器(FF 1.5也支持)*/

2012年3月27日

CSS 透明 所有瀏覽器通用寫法



CSS 透明個瀏覽器通用解法

簡介



有的時候我們需要在網頁頁面上些效果,需要將部分元件設定透明,最常使用的方法就是使用rgba(red, green, blue, alpha)或是opacity的方法去設定,但這式樣在IE中會無法正常地顯示,因此本文提供一個通用的寫法,讓各種瀏覽器都可以支援透明值的設定


filter:alpha(opacity=50); /* IE */ -moz-opacity:0.5; /* Moz + FF */ opacity: 0.5; /* 支持CSS3的瀏覽器(FF 1.5也支持)*/ 
其中IE與Firefox都使用了自己定義的屬性,而標準的屬性是opacity,值可以為小數點,範圍0.0~1.0。

jQuery data()



jQuery.data() 

簡介



相信很多的前端工程師喜歡將資料塞到html的標籤裡面,當作屬性的方式存放,這樣子實在很方便,先將資料塞入目標節點在往後需要使用的時候直接呼叫 $('selector').attr('key') 拿取,但這並不是很好的做法,這樣會使得我們的html程式過長過大,降低了SEO中的內容代碼比。


更多SEO細節,可以參考維基百科、網路行銷第一步-SEO。

解決辦法


其實如果需要將某些資料塞入DOM Tree某的節點上,可以不用真正的寫入它的標籤屬性中,jQuery提供了一種解決的辦法,$.data(),這個方法提供了三個參數,我們將下面做說明: 

jQuery.data( element, key, value )

  • element - 必要的參數,這個屬性就是我們要塞入資料的節點。
  • key - 欲塞入資料的鍵值,往後取得資料使用。
  • value - 欲塞入的資料,可為任何的資料型態。

透過一些範例來瞭解如何使用吧!


範例一 :
<!DOCTYPE html> <html> <head> <style> div { color:blue; } span { color:red; } </style> <script src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> <div> The values stored were <span></span> and <span></span> </div> <script>var div = $("div")[0]; jQuery.data(div, "test", { first: 16, last: "pizza!" }); $("span:first").text(jQuery.data(div, "test").first); $("span:last").text(jQuery.data(div, "test").last);</script> </body> </html>
輸出 :
The values stored were 16 and pizza!


範例二 : 使用Selector的data
$("div").data("test", { first: 16, last: "pizza!" }); $("div").data("test").first //16; $("div").data("test").last //pizza!;
範例三 : 在非DOM元素中塞入資料(詳解data方法)
其實在JavaScript中每個DOM Tree Element都是一個object,不信 ? 來看看下面的圖片吧


在chrome開發工具中可以看到DOM Element擁有許多的屬性,也就是一個,還可以發現它是一個HTMLElement Object,所以jQuery.data()說穿了就是在某個object上加上了新的值。下面我們使用一個最簡單的例子,大家看完就會一目瞭然囉 !
// Simple object var myObject = {myProperty : 'myValue'}; // using jQuery append property $.data(myObject, 'newProperty1', 'newValue1'); $.data(myObject, 'newProperty2', 'newValue2');
最後來看看myObject長甚麼樣子吧







完畢! 關於jQuery data()方法的介紹大致上就到這邊,關於這個方法如果你有更妙的應用請你不吝告知。

參考資料 : 
jQuery官方講解 

ShareThis