Pages

7/12/2012

Base64 encoding/decoding on Java

วันนี้ลองตั้งโจทย์ให้ตัวเอง ว่าลองทำ base64 encoding/decoding บน Java ซักหน่อย
คือเห็นว่าบน Ruby ทำได้ง่ายมากเลย เช่น
> base64=["abc"].pack("m*").chomp
 => "YWJj"
> base64.unpack("m*")[0]
 => "abc"

พอคิดว่าถ้าจะทำบน Java ก็คงทำได้ง่ายๆแหละ คิดว่าจะง่ายๆ แต่ทว่าจริงๆแล้วไม่ได้ง่ายเลย
ลอง search Google ดูปรากฎว่า Java ไม่มี built-in library สำหรับทำเรื่องนี้เลย
คือ  solution ที่จะทำได้มีดังนี้คือ

  1. เขียนเอง :  ไม่ทำแน่ๆ เพราะเยอะเกินไป และโค้ดจะรกมาก (ถ้าต้องทำก็ search หาโค้ดมาแปะเลยได้)
  2. ใช้ Built-in library ของ Sun : ใช้ class ชื่อ sun.misc.BASE64Decoder กับ sun.misc.BASE64Encoder สองตัวนี้เป็น Java's built-in library แต่ทว่าเป็น library ที่ใช้ภายในของ Sun ซึ่งจะไม่มีเอกสาร API ให้ดูว่าใช้ยังไง และที่สำคัญจะถูกยกเลิกในเร็วๆนี้  ดังนั้นตัวนี้ก็ไม่ใช่เป็นทางเลือกที่ดีนัก แต่ถ้าจะใช้ก็...
    import java.io.IOException;
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    ....
    BASE64Decoder decoder = new BASE64Decoder();
    BASE64Encoder encoder = new BASE64Encoder();
    try{
        String base64 = encoder.encodeBuffer("abc".getBytes("UTF-8"));
        byte[] normal = decoder.decodeBuffer(base64);
    }catch (IOException e){
        e.printStackTrace();
    }
    ...
    
  3. ใช้ Library ของ JavaMail (http://www.oracle.com/technetwork/java/javamail/index.html): โดยใช้ class ชื่อ javax.mail.internet.MimeUtility JavaMail ตัวนี้ต้องมีการดาวน์โหลด jar ของ JavaMail มาแล้วใส่ไว้ใน classpath เพื่อใช้งาน
  4. ใช้ Library ของ Apache Common Codec (http://commons.apache.org/codec/): โดยใช้คลาสชื่อ org.apache.commons.codec.binary.Base64 ข้อดีคือเป็น library ของ Apache แต่ว่ายังไงก็ต้องโหลด jar มาเพิ่มอีกอยู่ดี
  5. ใช้ Library ของ MiGBase64 (http://migbase64.sourceforge.net/) : ตัวนี้ก็อีกเช่นกันที่ต้องโหลด library มาเพิ่มเพื่อรัน
  6. ใช้ Library ของ Jetty (http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/util/B64Code.html)
  7. ใช้ Library ของ iHarder (http://iharder.sourceforge.net/current/java/base64/)
  8. ใช้ Built-in library ของ Java ชื่อ com.sun.org.apache.xml.internal.security.utils.Base64 แต่ว่ามันเป็นส่วนภายในซึ่งจะไม่มีเอกสารอ้างอิง
  9. ใช้ Built-in library ของ Java ชื่อ java.util.prefs.Base64 แต่ว่ามันเป็นส่วนภายในซึ่งจะไม่มีเอกสารอ้างอิง
  10. ใช้ Built-in library ของ Java ชื่อ javax.xml.bind.DatatypeConverter  ซึ่งเพิ่งเพิ่มมาใน Java6 และสามารถทำ Base64 encode/decode ได้  พร้อมเอกสาร API ที่ http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/DatatypeConverter.html
คือสรุปแล้วว่า   Java แทบจะไม่มีคำสั่งนี้ให้มาตั้งแต่แรกเลย ทั้งๆที่มันควรจะเป็นคำสั่งพื้นฐานในการจัดการกับข้อมูลสำหรับส่ง binary data โดยเฉพาะผ่านทาง HTTP  
จากที่ลิสต์จะเห็นว่า 6/10 เป็น library ที่จะต้องไปโหลดไฟล์ .jar เพิ่มเพื่อจะใช้งานนั้น
ส่วน 4/10 เป็น library ที่ built-in ใน Java เอง  แต่ใช้งานได้อย่างมาตรฐาน มีเอกสารประกอบครบเพียงแค่ 1 วิธีเท่านั้น  อีก 3 วิธีที่เหลือเป็นคำสั่งที่ใช้งานกันภายในผู้พัฒนาJava ซึ่งจะไม่มีเอกสารประกอบว่าจะใช้งานยังไง แล้วก็อาจจะถูกตัดทิ้งได้ทุกเวลา ก็จะทำให้ไม่สมควรจะใช้ในงานจริงๆ

ข้างล่างต่อไปนี้เป็นโค้ดตัวอย่างของการใช้วิธีที่ 10 (javax.xml.bind.DatatypeConverter)
class TestBase64{
    public static void main(String[] args){
        /*** ascii art gun: from http://www.ascii-art.de/ascii/ghi/gun.txt ***/
        String original_word = 
        "  +-'~`---------------------------------/\\--\n"+
        " ||\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \\\\\\\\\\\\  \\/~)\n"+
        " ||                                  \\\\\\\\\\\\  \\/_\n"+
        "  |~~~~~~~~-________________-_________________\\ ~--_\n"+
        "  !---------|_________       ------~~~~~(--   )--~~\n"+
        "                      \\ /~~~~\\~~\\   )--- \\_ /(\n"+
        "                       ||     |  | \\   ()   \\\\\n"+
        "                       \\____/_ / ()\\        \\\\\n"+
        "                        `~~~~~~~~~-. \\        \\\\\n"+
        "                                    \\ \\  <($)> \\\\\n"+
        "                                     \\ \\        \\\\\n"+
        "                                      \\ \\        \\\\\n"+
        "                                       \\ \\        \\\\\n"+
        "                                        \\ \\  ()    \\|\n"+
        "                                        _\\_\\__====~~~\n";
        System.out.println(original_word);
        try{
            String base64 = DatatypeConverter.printBase64Binary(original_word.getBytes("UTF-8"));
            System.out.println(base64);
            String result = new String(DatatypeConverter.parseBase64Binary(base64),"UTF-8");
            System.out.println(result);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

เอกสารอ้างอิง
[ - ] http://www.javatips.net/blog/2011/08/how-to-encode-and-decode-in-base64-using-java
[ - ] http://stackoverflow.com/questions/469695/decode-base64-data-in-java


No comments:

Post a Comment