Java 8 初探 - Base64

閱讀時間約 5 分鐘
此為過去的舊文,2014 年 5 月 11 日初次發表於 logdown。

這次看一個比較小的東西,就是 Java 8終於將 Base64 編解碼器內建到 java.util 套件中了。Base64 雖然會增加實際傳輸資料的長度,但在只用文字的網路協定中傳輸 binary 資料時常常用到 (例如:MIME email),所以一直到 Java 8 才內建確實讓人意外,在 Java 8 之前,需要 Base64 編解碼器,都需要透過第三方函式庫,例如 Apache Commons Codec

還記得之前某個工作內容是當使用者透過瀏覽器上傳 A 檔案到 X 系統時,因某些原故,X 系統不提供檔案儲放的功能,實際上是將該檔案 A 放到另一個有提供檔案內容檢索的 Y 系統;另一個類似的情況是,當使用者透過瀏覽器在 X 系統下載 B 檔案(內容是機器生成的)時,該檔案 B 會放到 Y 系統的另一個資料夾中備查。X 系統與 Y 系統都是標準的 RESTful Web Service,當時,X 和 Y 系統間檔案內容就是先以 Base64 編碼後,以文字的方式夾帶在 JSON 中透過 HTTP 傳輸。當時用的 Base64 編解碼器正是 Apache Commons Codec。

既然 Java 8 內建 Base64 編解碼器,那就來寫點程式試用看看吧!不過個人的習慣,對於從輸入讀取資料放到輸出這種事,喜歡使用 Apache Commons IOIOUils.copy(InputStream, OutputStream) 函式,不過如果沒有使用 Apache Commons IO,也可以自己寫一個,之後就可以不用再寫 while loop 做資料讀取複製的程式了。


有了輔助函式後,就先使用編碼器,將一個 InputStream 的資料用 Base64 編碼器編碼後放到指定的 OutputStream,下例中,encode(InputStream, OutputStream, Base64.Encoder) 函式接受三個參數,第一個是代表資料的來源,第二個是代表編碼後資料的目的地,這兩個蠻容易理解的,那第三個呢?為什麼還要指定編碼器?難道 Base64 編碼有不同種類嗎?是的,Base64 在不同通訊協定中有些變形,所以 Java 8 提供三種 Base64 的編解碼器。

第一種是基本版 (分別用 Base64.getEncoder()Base64.getDecoder() 取得編解碼器),只用 0-9a-zA-Z+/= 字元編碼且內容不換行;第二種針對網址和檔名修改的版本 (用Base64.getUrlEncoder()Base64.getUrlDecoder() 取得編解碼器),由於 +/ 符號在網址中有特殊用途,某些檔案系統也不允許 / 作為檔名,所以第二種用 - (減號) 取代 +,用 _ (底線) 取代/;第三種針對 MIME 調整的版本 (用 Base64.getMimeEncoder()Base64.getMimeDecoder() 取得編解碼器),使用的編碼字元和第一種一樣,但每輸出76個字元會加上一組 \r\n 換行。假設第一種是比較常用的情況,是可以如下例那樣寫一個無第三參數的版本方便使用。


編碼後就可以用解碼器進行解碼的動作,下例中 decode(InputStream, OutputStream, Base64.Decoder) 同樣接受三個參數,第一個參數是待解碼的資料來源,第二個是解碼後的資料目的地,第三個是解碼器。剛提到的三種不同編解碼器是無法混用的,所以使用第一種編碼器編碼的內容一定要用第一種解碼器來進行解碼。同樣,也可以提共一個無第三參數的版本方便使用,接下來的範例程式都可以用同樣的方法提供一個預先使用第一種編解碼器的版本。


有了從 InputStream 讀取資料進行編碼或解碼動作後放到 OutputStream 的函式後,就可以來點不一樣的變形了,例如像下例,可以指定輸入的檔案和輸出的檔案,利用 FileInputStreamFileOutputStream將檔案包裝成串流來使用,這時就可以使用上面提供的 encodedecode 函示來進行編解碼的動作。


當然,很多時候編解碼後的內容並不是要放到檔案中,以剛剛提到的例子,檔案內容會先被編碼,然後當成 JSON 的一部分,這時會希望有類似的程式,將編解碼後的內容當成字串,這時可以用 ByteArrayOutputStream 暫時存放編解碼後的內容,然後使用 toString(String) 將結果以字串輸出。


同樣,需要被編解碼的資料來源不一定是從檔案來,可能就是個字串,這時下面的函式就幫得上忙了,先用 getBytes() 取得字串的位元組陣列,接著用 ByteArrayInputStream 將位元組陣列包裝成輸入串流,然後用同樣的方法,對輸入的字串進行編解碼的動作。


Java 8 有了 Base64 編解碼器,方便不少,不過 Apache Commons Codec 提供更多常用的編解碼器,其實是更方便的,但如果你的應用程式中只需要 Base64 編解碼器,在有 Java 8 的環境中確實不需要將 Apache Commons Codec 和專案一起打包,對~前提是要有 Java 8 的環境,變成用不用內建的 Base64 編解碼器又是一種抉擇了。

52會員
102Content count
這是從 Medium 開始的一個專題,主要是想用輕鬆閒談的方式,分享這幾年軟體開發的心得,原本比較侷限於軟體架構,但這幾年的文章不僅限於架構,也聊不少流程相關的心得,所以趁換平台,順勢換成閒談軟體設計。
留言0
查看全部
發表第一個留言支持創作者!
Spirit的沙龍 的其他內容
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
最後,Java 8 雖然支援 Lambda,但我覺得 Closure 某種程度上還不稱不上是 Java 的第一級居民,我還是比較喜歡寫一些小而易測的 class,而不是使用 Lambda,至於捕捉變數,透過建構子將變數帶入物件也是一種方式。
Java 8 終於在 2014 的 3 月 18 日正式釋出了,不過自從用 Objective C 開發 iOS App後,我已經有好一陣子沒碰 Java,期間曾經有短暫寫一點點,但卻沒有時間去用 beta 版的 Java 8,直到最近才又開始玩一下。
內容十分精實,一百多頁很薄的一本書,但含了很多有用的資訊,就算不是開發微服務,書中的內容也可以用在很多雲端服務的開發與維運上。中文版唯一可惜的地方,翻譯非常不通順,很多不像中文的句子,會看到好幾個「與」連在一起用,標點符號的用法也有點怪,閱讀的痛苦指數有點高...
3/5高品質微服務
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
最後,Java 8 雖然支援 Lambda,但我覺得 Closure 某種程度上還不稱不上是 Java 的第一級居民,我還是比較喜歡寫一些小而易測的 class,而不是使用 Lambda,至於捕捉變數,透過建構子將變數帶入物件也是一種方式。
Java 8 終於在 2014 的 3 月 18 日正式釋出了,不過自從用 Objective C 開發 iOS App後,我已經有好一陣子沒碰 Java,期間曾經有短暫寫一點點,但卻沒有時間去用 beta 版的 Java 8,直到最近才又開始玩一下。
內容十分精實,一百多頁很薄的一本書,但含了很多有用的資訊,就算不是開發微服務,書中的內容也可以用在很多雲端服務的開發與維運上。中文版唯一可惜的地方,翻譯非常不通順,很多不像中文的句子,會看到好幾個「與」連在一起用,標點符號的用法也有點怪,閱讀的痛苦指數有點高...
3/5高品質微服務
你可能也想看
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
學習Spring Boot是Java工程師必備技能,文章分享瞭如何自學並快速上手Spring Boot開發,包括架構、開發工具、專案建立以及實作過程。
Thumbnail
本文章將介紹如何在LINE Notify上設定及使用權杖(access token)來進行通知功能。透過此API,可以使用curl或JAVA CODE來讓結果顯示在Line上面,達到及時的通知效果。
Thumbnail
WORA, Write Once Run Anywhere Java 不依賴於任何平台,Java可以在任何平台上執行,前提是那平台上要有安裝JVM Java的執行流程
Thumbnail
下載完JDK之後,在本機的環境變數中加入此JDK的bin路徑以便系統能識別使用 javac 是java compiler
Thumbnail
相信很多初學者學python的原因,不外乎語法簡單、好上手、重點是有很多現成的套件可以玩。那麼,Java呢?有!當然有!而且還多到你不知道該選哪個好! 今天的文章主要示範如何在vscode新建立Java 的maven專案,並且透過maven安裝這些額外的套件(依賴)
Thumbnail
最近配合公司政策換了新電腦,重新回想起從頭建環境的惡夢。本篇文就來記錄一下如何開始踏入Java的第一步,方便起見也使用相對Eclipse、IntelliJ來說輕量不少的VScode作為編輯器。
來到學期2-3的階段,第一個作業就是打造餐廳清單。原本認為經過電影清單的學習經歷之後,對於打造餐廳清單應該也不會太過困難;沒想到我花了2個月的時間才把作業完整交出去。 在寫餐廳清單的初期,第一個碰到的問題就是首頁無法秀出餐廳評分這個選項。我試著參考其他同學的作品也改了版面的設計,卻始終無法出現餐廳評
Thumbnail
位在通化街尾端,靠近六張犁的禾雀咖啡工作室,質樸的感覺是一家適合假日早晨來待上好一會兒的好去處。 主打自家烘培手沖及義式咖啡,最大特色還有自家製的麵包、甜點輕食,最喜歡吃的莫過於他們的鮮奶吐司。曾經住在這裡好長一段時間,週末去搶個一包可以在家裡烤來吃,是相當幸福的感覺。 冰羅馬咖啡則是我喝過最喜歡的
Thumbnail
abstract class = 抽象類別 interface = 介面 抽象類別與介面都無法建立物件。 1. 使用abstract關鍵字來建立抽象類別,interface關鍵字建立介面。 interface只能繼承interface,且可以繼承多個:
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
學習Spring Boot是Java工程師必備技能,文章分享瞭如何自學並快速上手Spring Boot開發,包括架構、開發工具、專案建立以及實作過程。
Thumbnail
本文章將介紹如何在LINE Notify上設定及使用權杖(access token)來進行通知功能。透過此API,可以使用curl或JAVA CODE來讓結果顯示在Line上面,達到及時的通知效果。
Thumbnail
WORA, Write Once Run Anywhere Java 不依賴於任何平台,Java可以在任何平台上執行,前提是那平台上要有安裝JVM Java的執行流程
Thumbnail
下載完JDK之後,在本機的環境變數中加入此JDK的bin路徑以便系統能識別使用 javac 是java compiler
Thumbnail
相信很多初學者學python的原因,不外乎語法簡單、好上手、重點是有很多現成的套件可以玩。那麼,Java呢?有!當然有!而且還多到你不知道該選哪個好! 今天的文章主要示範如何在vscode新建立Java 的maven專案,並且透過maven安裝這些額外的套件(依賴)
Thumbnail
最近配合公司政策換了新電腦,重新回想起從頭建環境的惡夢。本篇文就來記錄一下如何開始踏入Java的第一步,方便起見也使用相對Eclipse、IntelliJ來說輕量不少的VScode作為編輯器。
來到學期2-3的階段,第一個作業就是打造餐廳清單。原本認為經過電影清單的學習經歷之後,對於打造餐廳清單應該也不會太過困難;沒想到我花了2個月的時間才把作業完整交出去。 在寫餐廳清單的初期,第一個碰到的問題就是首頁無法秀出餐廳評分這個選項。我試著參考其他同學的作品也改了版面的設計,卻始終無法出現餐廳評
Thumbnail
位在通化街尾端,靠近六張犁的禾雀咖啡工作室,質樸的感覺是一家適合假日早晨來待上好一會兒的好去處。 主打自家烘培手沖及義式咖啡,最大特色還有自家製的麵包、甜點輕食,最喜歡吃的莫過於他們的鮮奶吐司。曾經住在這裡好長一段時間,週末去搶個一包可以在家裡烤來吃,是相當幸福的感覺。 冰羅馬咖啡則是我喝過最喜歡的
Thumbnail
abstract class = 抽象類別 interface = 介面 抽象類別與介面都無法建立物件。 1. 使用abstract關鍵字來建立抽象類別,interface關鍵字建立介面。 interface只能繼承interface,且可以繼承多個: