Search

Java - PTT Client 軟體開發經驗(1) - 前置準備

2015-12-16 11:41 AM

警告! 開發 PTT Client 非常之危險!

無所不在的時間黑洞以及各種無法預料的狀況會將你的精神折磨至崩潰!!!

哈哈哈哈哈哈哈哈哈哈(就像這樣)

--

以下都是廢話加閒談,趕時間的可以按這裡跳到重點

可喜可賀!

經過了漫長的開發時間終於成功上架了

目前似乎也運氣很好的穩定運行了一段時間

有興趣的朋友可以自己在部落格內尋找 App 連結,我就不多打廣告了

自信滿滿,人稱程式小Bug王的我原本想說這種小東西大概一兩個月就可以完成了吧!

結果花了我快半年...

其中一個原因是第一次開發 Android App

另一個就是氣死人不償命的 VT100 終端機訊息傳遞機制,這個留待往後慢慢說明

而且網路上的資源可以說是少之又少

很多東西都是自己Google來東拼西湊才知道的

所以很多東西看看就好不一定是對的,自己找重點記(超不負責任)

尤其很多都是英文的資料,對於 PTT 這中文的論壇所需的技術來說實在是很不友善

於是我就想說寫這篇教學文章來好好闡述一下這血與淚的開發史

希望可以求得一些歷史定位(!?)

呃...是造福其他開發者啦

最主要的目的是告訴其他有興趣的開發者趕快放棄開發的計劃,因為實在太難做了

如果再讓我選一次我絕對不會選擇開發這個 App!!!

心理準備

首先我們來彈彈 PTT 的額頭,要很用力!(到底有多恨...)

是來談談 PTT 使用的 ANSI Escape Sequence 以及相關的知識

如果以為這只是單純的文字處理那就大錯特錯了!

當初天真爛漫的我其實就是這麼想的,殊不知背後龐大的利益鳩葛與情仇交纏...

PTT 是使用 VT100 這種類型的終端機定義來傳遞訊息

而使用 ANSI Escape Sequence 則可以將訊息格式化

諸如文字顏色、背景顏色、閃爍、文字出現位置以及清除畫面等等

所以你用 PC MAN 或任何終端機連上後可以看得見如此精美的畫面


但是你得到的資料其實是...

 [H [1;37;44m【主功能表】                      [33m批踢踢實業坊 [0;1;37;44m                                  
 [0;47m        [30m│ [2;6H                                                      [0;47m﹎ [30m﹏︷~一︸一~︷﹏﹎ [0;47m  
     [30;43m╱ [3;3H     [31;47m◢ [3;5H [41m      [30m﹏     ╱ [3;15H [47m           [1m▄ [3;23H    ▄ [3;25H    ▄ [3;27H    ▄ [3;29H    ▄ [3;31H    ▄ [3;33H    ▄ [3;35H    ▄ [3;37H    ▄ [3;39H    ▄ [3;41H                       [0;30;47m∕ [3;61H明天要出去玩,  ﹨  
 [0;43m   [41m  [30m#          ╱ [4;13H   [47m          [0;47m█ [4;22H [0;1;30m  [34m/  [0;1;37m.       [5;34m∕ [4;30H     [0;30m█ [4;32H [1;36m/   [5;34m/ [0;5;34m      [0;1;30m║ [4;40H    █ [4;42H [0;47m           ▁ [4;51H     [30m▂ [4;53H    ▁ [4;55H [0;47m     [30m﹨   雨還沒停嗎...    ∕ [4;79H  
     [0;43m◢ [5;3H [33;41m     [30m〞    ╱ [5;11H _   [47m          [0;47m█ [5;22H [0;1;30m   [5;36m/ [0;5;36m  [0;1;5;37m.      [0;1;36m∕ [5;31H     [30m█ [5;33H [0;30m  [0;1;37m.     ● [5;38H [30m人    █ [5;42H [0;47m          [30m◢ [5;49H [0;30m           [47m◣ [5;57H [0;47m  ﹊ [30m`"︸一~︷~一︸"`﹊ [0;47m  
     [43m◤ [6;3H [33;41m      [30m氵 [6;6H     ╱ [6;9H     ╱ [6;12H    ║ [6;14H  [47m          [0;47m█ [6;22H [0;1;30m      [34m∕ [6;25H     [36m′ [6;27H [0;36m       [30m▃ [6;31H     [1m█ [6;33H     [5;34m′ [6;35H [36m/      [0;1;37m▲ [6;39H      [30m█ [6;42H [0;47m          [30m◤ [6;49H     [43m◤ [6;51H    ◤ [6;53H [0;30m        [47m▏ [6;58H      ∞ [6;62H [0;47m         [36m▃ [6;68H    ▄ [6;70H    ▃ [6;72H [0;47m         
     [33;41m◤ [7;3H       [30m╱ [7;7H    ▏ [7;9H/      ║ [7;14H  [47m          [0;47m█ [7;22H [0;1;30m     [5;34m/ [0;1;36m/     [0;30m◤ [7;31H     [1m█ [7;33H [0;30m  [1;34m/     ′ [7;38H [0;34m  [1;5m/     [0;1;30m█ [7;42H [0;47m       [43m      [30m˙ [7;51H      [33m◤ [7;54H     [30m◥ [7;56H     [47m▎ [7;58H。           [36;46m◤ [7;68H [1;33;47m/|\          
 [0;30;41m`     ╱ [8;5H      [31m▋ [8;8H     [30m║ [8;10H      ║ [8;14H  [47m          [0;47m█ [8;22H [0;1;30m      [36m′ [8;25H [0;36m     [1;34m/     [30m█ [8;33H [0;30m   [1;36m/ [0;36m  [0;1;5;37m.      [0;1;30m█ [8;42H [0;47m       [43m          [33m◢ [8;55H [0;30m      [47m▏ [8;58H         [46m  [47m              
     [41m╱ [9;3H _      [31m▋ [9;8H     [30m║ [9;10H      ║ [9;14H  [47m          [0;47m█ [9;22H     [0;1;5;36m∕ [9;24H     [0;1;34m′ [9;26H [5;36m/ [0;5;36m  [0;1;37m.      [30m█ [9;33H     [34m∕ [9;35H     [5;36m′ [9;37H [0;5;36m      [0;1;36m∕ [9;40H     [30m█ [9;42H [0;47m         ◥ [9;49H [31;43mㄟ [33m      ▲ [9;55H     [30;47m◤ [9;57H [0;47m          [46m  [47m                [1;30mξ [9;80H 
 [0;41m      [30m╱ [10;4H    ║ [10;6H     [31m▋ [10;8H     [30m║ [10;10H      ║ [10;14H  [47m          [0;47m█ [10;22H     [0;1;30m▄ [10;24H    ▄ [10;26H    ▄ [10;28H    ▄ [10;30H    ▄ [10;32H    ▄ [10;34H    ▄ [10;36H    ▄ [10;38H    ▄ [10;40H    █ [10;42H [0;47m              [30;42m╭ [10;53H    ╮ [10;55H [47m             [33m◢ [10;65H     [36;43m▃ [10;67H    ▃ [10;69H [33m       [31m▁ [10;73H    ▁ [10;75H       [33m▲ [10;79H     [44m▲ [10;81H
 [30;41m/      ║ [11;6H     [31m▋ [11;8H     [30m║ [11;10H      ║ [11;14H      [1;47mψ [11;17Hrod24574575                            [0;30;42m│ [11;53H    │ [11;55H [47m           [33m◢ [11;63H [43m           [31m▕ [11;71H     [30;47m≡ [11;73H     [1m▏ [11;75H     [0;31;43m▏ [11;77H  [34m ̄ 
 [m [K
    ─ [13;3H    ─ [13;5H    ─ [13;7H    ─ [13;9H    ─ [13;11H    ─ [13;13H    ─ [13;15H    ─ [13;17H    ─ [13;19H 上方為使用者心情點播留言區,不代表本站立場     ─ [13;65H    ─ [13;67H    ─ [13;69H    ─ [13;71H    ─ [13;73H    ─ [13;75H    ─ [13;77H    ─ [13;79H [14;10H             ( [1;36mA [m)nnounce     【 精華公佈欄 】 [K [15;10H             ( [1;36mF [m)avorite     【 我 的 最愛 】 [K [16;10H             ( [1;36mC [m)lass        【 分組討論區 】 [K [17;10H             ( [1;36mM [m)ail         【 私人信件區 】 [K [18;10H             ( [1;36mT [m)alk         【 休閒聊天區 】 [K [19;10H             ( [1;36mU [m)ser [19;38H【 個人設定區 】 [K [20;10H             ( [1;36mX [m)yz          【 系統資訊區 】 [K [21;10H             ( [1;36mP [m)lay         【 娛樂與休閒 】 [K [22;10H             ( [1;36mN [m)amelist     【 編特別名單 】 [K [23;10H           > ( [1;36mG [m)oodbye         離開,再見    … [23;53H [K
 [34;46m[12/16 星期三 12:04] [1;33;45m [ 天秤時 ]    [24;36H [30;47m線上 [31m108017 [30m人, 我是 [31mnoartsarc [30m    [呼叫器] [31m打開  [m [23;21H

有沒有感覺到一種被欺騙了的感覺

...

...

...

那麼接下來我們就進入正式的介紹了(現在才開始!? 那前面打那麼多字幹嘛啦)

ANSI Escape Sequence

首先我希望各位將以下幾個網頁加入最愛或是直接儲存整個網頁

對於往後的開發來說會是非常重要的資源

控制字元對照表 - ASCII code caracters

ANSI 控制碼對照表 - ANSI Codes

CTRL 複合按鍵對照表 - Key Pressed with CTRL key down

第一個跟第三個連結暫時還用不上,我們先打開 ANSI Codes 的連結

然後看到下方表格的 color and text formatting 這欄


這邊主要是在說明所有可以用的文字格式設定控制碼

 /**
  * ESC 就是代表鍵盤上的 ESC 字元, 如何輸入留待後面再提
  * [#(;#) 中間的 # 就是表格內的數字組合, 可以放很多組格式設定
  * 但重複的設定會被後面的覆蓋掉
  * 例如我想要有紅色的字體, 綠色的背景再讓他閃爍就會使用以下控制碼
  * ESC[1;31;42m紅字綠背景ESC[m
  * 而如果重複使用了前景或背景設定
  * ESC[1;36;35;34;33;32;43;42m紅字綠背景ESC[m
  * 他則會以最後出現的設定來顯示(以上範例為32;42兩組設定)
  * 所以以上兩個範例顯示的結果會是相同的
  * 最後面的 ESC[m 則是還原用控制碼
  * 將所有文字格式設定還原
  * 而控制碼的結尾必須要以 m 告知處理器格式設定已經完成了
  * 這邊的觀念非常重要, 因為我們必須親自寫出一個上面提到的處理器
  * 也就是 ANSI Escape Sequence Parsing Engine
  */
 ESC[#(;#)m

再來就是另一個比較複雜的重頭戲了

請看到網頁中表格的 cursor controls 以及 erase functions


這邊主要是在處理文字的排版

也是上面那一大串文字的最主要原因

PTT 回傳的資料有很多種類型, 有時會給你完整的字串用空白補齊位子

有時會不給你空白, 而是使用 ESC[12;30H 的方式告訴你接下來的字是放在哪個位置

 /**
  * ESC 就是代表鍵盤上的 ESC 字元, 如何輸入留待後面再提
  * [#;#H 中間的 # 表示要將游標移動到哪個位置
  * 而這個游標位置又影響了接下來的字串會在哪個位置開始插入
  * 可以想像成一個 24 * 80 的矩陣會比較容易了解
  * 例如PTT回傳了要在 第 2 行的第 20 個的位置開始插入字串就會使用
  * ESC[2;20H隨便字串
  * 以此類推, 而若是使用
  * ESC[H
  * 則表示將游標位置歸零
  */
 ESC[#;#H

 // 清空所有資料
 ESC[2J
 // 清空目前所在行數的資料
 ESC[K

 // 將游標往後退一格 Backspace
 \b

 // 將游標回到同一列的第一個位置
 \r

 // 將游標往下移動一個 row
 \n

其他的部分因為 PTT 不會回傳那些控制碼所以可以暫時不用看

下一章就會開始講解 ANSI Escape Sequence Parsing Engine 該如何撰寫

用一長串英文有沒有感覺很專業?

其實就是將 PTT 回傳的資料一個蘿蔔一個坑的放入剛剛提到的 24 * 80 陣列的方法

算是整個 PTT Client 的第一個最重要的核心

也是當初撰寫時遇到的第一個難關

那麼就容我稍微拖個稿,請待下回分解!!!

各項資料連結
Java - PTT 文章代碼(AID)轉換為 URL
VT100
ASCII code caracters
ANSI Codes
Key Pressed with CTRL key down
PTT 完全操作手冊

No comments:

Post a Comment