Saya memiliki gambar yang disandikan Base64. Apa cara terbaik untuk memecahkan kode itu di Jawa? Semoga hanya menggunakan perpustakaan yang disertakan dengan Sun Java 6.
Apa pun jenis aplikasi yang Anda gunakan (bereksperimen atau tidak), itu hanya semudah membuat file Base64.java tunggal dalam paket utilitas Anda menggunakan kode di sini: migbase64.sourceforge.net Lihat grafik kinerja dan perhatikan perbedaannya: 4-5 kali lebih cepat.
javacoder
FYI: JEP 135 mengusulkan untuk memperkenalkan API standar yang dapat ditemukan untuk ini di platform Java.
Namun, tampaknya printBase64Binary(..)metode ini tidak melakukan versi MIME dari Base64 ( en.wikipedia.org/wiki/Base64#MIME ), sementara implementasi private Sun dan the Commons menggunakan ini. Khususnya, untuk String yang lebih besar dari 76 karakter, baris baru ditambahkan. Saya tidak menemukan cara mengkonfigurasi implementasi JAXB untuk perilaku ini ... :-(
KLE
7
Namun, implementasi matahari akan mengabaikan baris baru. Jadi mereka kompatibel.
Esben Skov Pedersen
9
Peringatan! parseBase64Binary diam-diam akan melompati karakter yang tidak valid dan tidak akan memeriksa validitas base64. Lebih baik menggunakan Commons Codec atau Guava Base64. Perhatikan bahwa Guava menolak baris baru dan karakter spasi putih, jadi Anda perlu mengurai string dengan spasi putih dihilangkan: BaseEncoding.base64 (). Decode (s.replaceAll ("\\ s", ""))
Martin Vysny
9
Hati-hati. Fungsi ini tidak berfungsi dengan data yang lebih lama dari 65000. (java versi 1.6)
Hüseyin Yağlı
5
Jangan gunakan itu, karena Anda akan mendapatkan masalah di jdk 9: java.lang.NoClassDefFoundError (javax / xml / bind / DatatypeConverter)
rupashka
381
Pada Java 8 , ada API yang didukung secara resmi untuk encoding dan decoding Base64. Pada waktunya, ini mungkin akan menjadi pilihan default.
API mencakup kelas java.util.Base64dan kelas bersarangnya. Ini mendukung tiga rasa berbeda: dasar, URL aman, dan MIME.
The dokumentasi untukjava.util.Base64 mencakup beberapa metode yang lebih untuk mengkonfigurasi encoders dan decoders, dan untuk menggunakan kelas yang berbeda sebagai input dan output (array byte, string, ByteBuffers, java.io sungai).
Saya menggunakan Java 8. Apakah ini pendekatan yang disarankan jika menggunakan Java 8?
JohnMerlino
4
@JohnMerlino jika kompatibilitas dengan versi Java yang lebih lama tidak diperlukan, saya akan merekomendasikan menggunakan API ini karena JRE memiliki kebijakan kompatibilitas yang lebih kuat daripada kebanyakan perpustakaan. Juga, dimasukkan dalam JRE, itu tidak membatasi ketergantungan Anda dengan cara apa pun yang mungkin.
Andrea
4
Java 7 EOLed, Java 9 akan datang, ini benar jawaban untuk saya!
eskatos
1
Hampir bagus: ini hanya menerima stream base64 mentah, bukan file base64. Saya harus menggunakan final byte[] decoded = Base64.getMimeDecoder().decode(encoded);sebagai gantinya. Tapi Terimakasih! (Baik dengan commons-io FileUtils.readFileToByteArraydan FileUtils.writeByteArrayToFile- terutama ketika Anda menyadari encodedbisa menjadi byte[]juga.)
mirabilos
101
Tidak perlu menggunakan commons - Sun mengirimkan encoder base64 dengan Java. Anda dapat mengimpornya seperti:
Dimana encodedBytesa java.lang.Stringatau a java.io.InputStream. Berhati - hatilah karena itusun.* kelas tidak "didukung secara resmi" oleh Sun.
EDIT: Siapa yang tahu ini akan menjadi jawaban paling kontroversial yang pernah saya posting? Saya tahu bahwa sun. * Paket tidak didukung atau dijamin untuk terus ada, dan saya tahu tentang Commons dan menggunakannya setiap saat. Namun, poster itu meminta kelas yang "disertakan dengan Sun Java 6," dan itulah yang saya coba jawab. Saya setuju bahwa Commons adalah cara terbaik untuk pergi secara umum.
EDIT 2: Seperti yang ditunjukkan amir75 di bawah ini, Java 6+ dikirimkan bersama JAXB, yang berisi kode yang didukung untuk menyandikan / mendekode Base64. Silakan lihat jawaban Jeremy Ross di bawah ini.
-1 - ini adalah kode internal Sun, BUKAN bagian dari J2SE (tidak portabel), dan dapat menghilang kapan saja - Sun secara eksplisit mengatakan TIDAK menggunakan perpustakaan internal mereka dalam kode pengguna
kdgregory
59
Benar, karena itu sanggahan saya pada akhirnya.
MattK
20
Ini untuk proyek jangka pendek dan hanya eksperimen dan tidak ingin melalui proses persetujuan untuk perpustakaan baru. Jadi ini jawaban yang benar untuk pertanyaan ini.
Ryan P
44
Bzzt. Dalam lingkungan profesional, menggunakan fitur yang tidak didukung dan tidak berdokumen bukanlah keputusan yang tepat. Dan di lingkungan perusahaan, "percobaan" menjadi "kode produksi" tanpa peluang untuk memperbaiki peretasan.
kdgregory
29
Di departemen penelitian di mana kode itu ditandai sebagai eksperimen dan ketika itu ditandai selalu dihapus itu adalah keputusan yang benar.
Ryan P
55
Khususnya di Commons Codec : kelas Base64ke decode(byte[] array)atauencode(byte[] array)
Anda dapat menautkan teks 'Commons Codec' ke halaman proyek. Dengan begitu jawaban ini akan lebih baik daripada Kevin :)
mmutilva
1
Saya tahu ini adalah pertanyaan lama, tetapi mengapa ini bukan jawaban yang diterima? Bukankah codec commons disertakan dengan sebagian besar instalasi java, dan jauh lebih sedikit baris kode untuk digunakan daripada memutar versi Anda sendiri?
Li Haoyi
2
@LiHaoyi Pertanyaan yang diajukan untuk perpustakaan yang dikirimkan bersama Sun's JDK, yang tidak termasuk apa pun dari Commons.
Guava 14 masih merupakan kandidat pelepasliaran, tetapi ini masih membuat saya tersentuh - pada saat ia mencapai posisi yang layak, ia harus berwarna emas :-)
Peter Becker
1
Decoder Guava base64 menolak karakter baris dan spasi baru sehingga Anda harus menghapusnya sebelumnya.
Martin Vysny
34
Solusi saya tercepat dan termudah.
publicclassMyBase64{privatefinalstaticchar[] ALPHABET ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();privatestaticint[] toInt =newint[128];static{for(int i=0; i< ALPHABET.length; i++){
toInt[ALPHABET[i]]= i;}}/**
* Translates the specified byte array into Base64 string.
*
* @param buf the byte array (not null)
* @return the translated Base64 string (not null)
*/publicstaticString encode(byte[] buf){int size = buf.length;char[] ar =newchar[((size +2)/3)*4];int a =0;int i=0;while(i < size){byte b0 = buf[i++];byte b1 =(i < size)? buf[i++]:0;byte b2 =(i < size)? buf[i++]:0;int mask =0x3F;
ar[a++]= ALPHABET[(b0 >>2)& mask];
ar[a++]= ALPHABET[((b0 <<4)|((b1 &0xFF)>>4))& mask];
ar[a++]= ALPHABET[((b1 <<2)|((b2 &0xFF)>>6))& mask];
ar[a++]= ALPHABET[b2 & mask];}switch(size %3){case1: ar[--a]='=';case2: ar[--a]='=';}returnnewString(ar);}/**
* Translates the specified Base64 string into a byte array.
*
* @param s the Base64 string (not null)
* @return the byte array (not null)
*/publicstaticbyte[] decode(String s){int delta = s.endsWith("==")?2: s.endsWith("=")?1:0;byte[] buffer =newbyte[s.length()*3/4- delta];int mask =0xFF;int index =0;for(int i=0; i< s.length(); i+=4){int c0 = toInt[s.charAt( i )];int c1 = toInt[s.charAt( i +1)];
buffer[index++]=(byte)(((c0 <<2)|(c1 >>4))& mask);if(index >= buffer.length){return buffer;}int c2 = toInt[s.charAt( i +2)];
buffer[index++]=(byte)(((c1 <<4)|(c2 >>2))& mask);if(index >= buffer.length){return buffer;}int c3 = toInt[s.charAt( i +3)];
buffer[index++]=(byte)(((c2 <<6)| c3)& mask);}return buffer;}}
itu bukan buggy! - baca komentar javadoc ... parameter decode (..) adalah base64 String bukan sembarang String. byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));// => true
GeorgeK
9
Tercepat dan termudah ?? Menemukan kembali roda ?!
Nicolas Barbulesco
7
Saya menjalankan beberapa tes membandingkan kelas ini dengan commons-codec dan sepertinya berfungsi OK. Saya membutuhkan sesuatu yang sederhana seperti ini karena saya hanya membutuhkan encoding base64 dan tidak ingin semua hal tambahan yang disediakan oleh commons-codec, terima kasih.
Michael
2
Apakah ini amanah? Tampaknya menjadi yang termudah jika Anda tidak ingin mengimpor perpustakaan eksternal.
Felipe
2
itu tidak bekerja dengan byte yang diperoleh dari algoritma AES
shontauro
11
Inilah implementasi saya sendiri, jika bisa bermanfaat bagi seseorang:
publicclassBase64Coder{// The line separator string of the operating system.privatestaticfinalString systemLineSeparator =System.getProperty("line.separator");// Mapping table from 6-bit nibbles to Base64 characters.privatestaticfinalchar[] map1 =newchar[64];static{int i=0;for(char c='A'; c<='Z'; c++) map1[i++]= c;for(char c='a'; c<='z'; c++) map1[i++]= c;for(char c='0'; c<='9'; c++) map1[i++]= c;
map1[i++]='+'; map1[i++]='/';}// Mapping table from Base64 characters to 6-bit nibbles.privatestaticfinalbyte[] map2 =newbyte[128];static{for(int i=0; i<map2.length; i++) map2[i]=-1;for(int i=0; i<64; i++) map2[map1[i]]=(byte)i;}/**
* Encodes a string into Base64 format.
* No blanks or line breaks are inserted.
* @param s A String to be encoded.
* @return A String containing the Base64 encoded data.
*/publicstaticString encodeString (String s){returnnewString(encode(s.getBytes()));}/**
* Encodes a byte array into Base 64 format and breaks the output into lines of 76 characters.
* This method is compatible with <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>.
* @param in An array containing the data bytes to be encoded.
* @return A String containing the Base64 encoded data, broken into lines.
*/publicstaticString encodeLines (byte[] in){return encodeLines(in,0, in.length,76, systemLineSeparator);}/**
* Encodes a byte array into Base 64 format and breaks the output into lines.
* @param in An array containing the data bytes to be encoded.
* @param iOff Offset of the first byte in <code>in</code> to be processed.
* @param iLen Number of bytes to be processed in <code>in</code>, starting at <code>iOff</code>.
* @param lineLen Line length for the output data. Should be a multiple of 4.
* @param lineSeparator The line separator to be used to separate the output lines.
* @return A String containing the Base64 encoded data, broken into lines.
*/publicstaticString encodeLines (byte[] in,int iOff,int iLen,int lineLen,String lineSeparator){int blockLen =(lineLen*3)/4;if(blockLen <=0)thrownewIllegalArgumentException();int lines =(iLen+blockLen-1)/ blockLen;int bufLen =((iLen+2)/3)*4+ lines*lineSeparator.length();StringBuilder buf =newStringBuilder(bufLen);int ip =0;while(ip < iLen){int l =Math.min(iLen-ip, blockLen);
buf.append (encode(in, iOff+ip, l));
buf.append (lineSeparator);
ip += l;}return buf.toString();}/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted in the output.
* @param in An array containing the data bytes to be encoded.
* @return A character array containing the Base64 encoded data.
*/publicstaticchar[] encode (byte[] in){return encode(in,0, in.length);}/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted in the output.
* @param in An array containing the data bytes to be encoded.
* @param iLen Number of bytes to process in <code>in</code>.
* @return A character array containing the Base64 encoded data.
*/publicstaticchar[] encode (byte[] in,int iLen){return encode(in,0, iLen);}/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted in the output.
* @param in An array containing the data bytes to be encoded.
* @param iOff Offset of the first byte in <code>in</code> to be processed.
* @param iLen Number of bytes to process in <code>in</code>, starting at <code>iOff</code>.
* @return A character array containing the Base64 encoded data.
*/publicstaticchar[] encode (byte[] in,int iOff,int iLen){int oDataLen =(iLen*4+2)/3;// output length without paddingint oLen =((iLen+2)/3)*4;// output length including paddingchar[] out =newchar[oLen];int ip = iOff;int iEnd = iOff + iLen;int op =0;while(ip < iEnd){int i0 = in[ip++]&0xff;int i1 = ip < iEnd ? in[ip++]&0xff:0;int i2 = ip < iEnd ? in[ip++]&0xff:0;int o0 = i0 >>>2;int o1 =((i0 &3)<<4)|(i1 >>>4);int o2 =((i1 &0xf)<<2)|(i2 >>>6);int o3 = i2 &0x3F;
out[op++]= map1[o0];
out[op++]= map1[o1];
out[op]= op < oDataLen ? map1[o2]:'='; op++;
out[op]= op < oDataLen ? map1[o3]:'='; op++;}return out;}/**
* Decodes a string from Base64 format.
* No blanks or line breaks are allowed within the Base64 encoded input data.
* @param s A Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException If the input is not valid Base64 encoded data.
*/publicstaticString decodeString (String s){returnnewString(decode(s));}/**
* Decodes a byte array from Base64 format and ignores line separators, tabs and blanks.
* CR, LF, Tab and Space characters are ignored in the input data.
* This method is compatible with <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>.
* @param s A Base64 String to be decoded.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException If the input is not valid Base64 encoded data.
*/publicstaticbyte[] decodeLines (String s){char[] buf =newchar[s.length()];int p =0;for(int ip =0; ip < s.length(); ip++){char c = s.charAt(ip);if(c !=' '&& c !='\r'&& c !='\n'&& c !='\t')
buf[p++]= c;}return decode(buf,0, p);}/**
* Decodes a byte array from Base64 format.
* No blanks or line breaks are allowed within the Base64 encoded input data.
* @param s A Base64 String to be decoded.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException If the input is not valid Base64 encoded data.
*/publicstaticbyte[] decode (String s){return decode(s.toCharArray());}/**
* Decodes a byte array from Base64 format.
* No blanks or line breaks are allowed within the Base64 encoded input data.
* @param in A character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException If the input is not valid Base64 encoded data.
*/publicstaticbyte[] decode (char[] in){return decode(in,0, in.length);}/**
* Decodes a byte array from Base64 format.
* No blanks or line breaks are allowed within the Base64 encoded input data.
* @param in A character array containing the Base64 encoded data.
* @param iOff Offset of the first character in <code>in</code> to be processed.
* @param iLen Number of characters to process in <code>in</code>, starting at <code>iOff</code>.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException If the input is not valid Base64 encoded data.
*/publicstaticbyte[] decode (char[] in,int iOff,int iLen){if(iLen%4!=0)thrownewIllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");while(iLen >0&& in[iOff+iLen-1]=='=') iLen--;int oLen =(iLen*3)/4;byte[] out =newbyte[oLen];int ip = iOff;int iEnd = iOff + iLen;int op =0;while(ip < iEnd){int i0 = in[ip++];int i1 = in[ip++];int i2 = ip < iEnd ? in[ip++]:'A';int i3 = ip < iEnd ? in[ip++]:'A';if(i0 >127|| i1 >127|| i2 >127|| i3 >127)thrownewIllegalArgumentException("Illegal character in Base64 encoded data.");int b0 = map2[i0];int b1 = map2[i1];int b2 = map2[i2];int b3 = map2[i3];if(b0 <0|| b1 <0|| b2 <0|| b3 <0)thrownewIllegalArgumentException("Illegal character in Base64 encoded data.");int o0 =( b0 <<2)|(b1>>>4);int o1 =((b1 &0xf)<<4)|(b2>>>2);int o2 =((b2 &3)<<6)| b3;
out[op++]=(byte)o0;if(op<oLen) out[op++]=(byte)o1;if(op<oLen) out[op++]=(byte)o2;}return out;}// Dummy constructor.privateBase64Coder(){}}
MiGBase64 mudah digunakan, dikodekan dengan baik dan sangat cepat. Temuan yang bagus, Imby.
mukama
Menurut tolok ukur ini MiGBase64 bukan implementasi tercepat lagi, dan sekarang tertinggal di belakang Apache Commons dan sun.misc.BASE64Decoder secara signifikan.
Andrea
3
Ini adalah jawaban yang terlambat , tetapi Joshua Bloch melakukan Base64kelasnya (ketika ia bekerja untuk Sun, ahem, Oracle) di bawah java.util.prefspaket. Kelas ini ada sejak JDK 1.4.
Implementasi Java 8 java.util.Base64tidak memiliki dependensi pada kelas khusus Java 8 lainnya.
Saya tidak yakin apakah ini akan berfungsi untuk proyek Java 6, tetapi dimungkinkan untuk menyalin dan menempelkan Base64.javafile ke proyek Java 7 dan mengkompilasinya tanpa modifikasi selain mengimpor java.util.Arrays dan java.util.Objects.
Perhatikan bahwa file Base64.java dicakup oleh GNU GPL2
import java.io.UnsupportedEncodingException;/**
* Utilities for encoding and decoding the Base64 representation of
* binary data. See RFCs <a
* href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a
* href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.
*/publicclassBase64{publicstaticfinalint DEFAULT =0;publicstaticfinalint NO_PADDING =1;publicstaticfinalint NO_WRAP =2;publicstaticfinalint CRLF =4;publicstaticfinalint URL_SAFE =8;publicstaticfinalint NO_CLOSE =16;// --------------------------------------------------------// shared code// --------------------------------------------------------/* package */staticabstractclassCoder{publicbyte[] output;publicint op;publicabstractboolean process(byte[] input,int offset,int len,boolean finish);publicabstractint maxOutputSize(int len);}// --------------------------------------------------------// decoding// --------------------------------------------------------publicstaticbyte[] decode(String str,int flags){return decode(str.getBytes(), flags);}publicstaticbyte[] decode(byte[] input,int flags){return decode(input,0, input.length, flags);}publicstaticbyte[] decode(byte[] input,int offset,int len,int flags){// Allocate space for the most data the input could represent.// (It could contain less if it contains whitespace, etc.)Decoder decoder =newDecoder(flags,newbyte[len*3/4]);if(!decoder.process(input, offset, len,true)){thrownewIllegalArgumentException("bad base-64");}// Maybe we got lucky and allocated exactly enough output space.if(decoder.op == decoder.output.length){return decoder.output;}// Need to shorten the array, so allocate a new one of the// right size and copy.byte[] temp =newbyte[decoder.op];System.arraycopy(decoder.output,0, temp,0, decoder.op);return temp;}staticclassDecoderextendsCoder{privatestaticfinalint DECODE[]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,};/**
* Decode lookup table for the "web safe" variant (RFC 3548
* sec. 4) where - and _ replace + and /.
*/privatestaticfinalint DECODE_WEBSAFE[]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,63,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,};/** Non-data values in the DECODE arrays. */privatestaticfinalint SKIP =-1;privatestaticfinalint EQUALS =-2;privateint state;// state number (0 to 6)privateint value;finalprivateint[] alphabet;publicDecoder(int flags,byte[] output){this.output = output;
alphabet =((flags & URL_SAFE)==0)? DECODE : DECODE_WEBSAFE;
state =0;
value =0;}publicint maxOutputSize(int len){return len *3/4+10;}/**
* Decode another block of input data.
*
* @return true if the state machine is still healthy. false if
* bad base-64 data has been detected in the input stream.
*/publicboolean process(byte[] input,int offset,int len,boolean finish){if(this.state ==6)returnfalse;int p = offset;
len += offset;int state =this.state;int value =this.value;int op =0;finalbyte[] output =this.output;finalint[] alphabet =this.alphabet;while(p < len){if(state ==0){while(p+4<= len &&(value =((alphabet[input[p]&0xff]<<18)|(alphabet[input[p+1]&0xff]<<12)|(alphabet[input[p+2]&0xff]<<6)|(alphabet[input[p+3]&0xff])))>=0){
output[op+2]=(byte) value;
output[op+1]=(byte)(value >>8);
output[op]=(byte)(value >>16);
op +=3;
p +=4;}if(p >= len)break;}int d = alphabet[input[p++]&0xff];switch(state){case0:if(d >=0){
value = d;++state;}elseif(d != SKIP){this.state =6;returnfalse;}break;case1:if(d >=0){
value =(value <<6)| d;++state;}elseif(d != SKIP){this.state =6;returnfalse;}break;case2:if(d >=0){
value =(value <<6)| d;++state;}elseif(d == EQUALS){// Emit the last (partial) output tuple;// expect exactly one more padding character.
output[op++]=(byte)(value >>4);
state =4;}elseif(d != SKIP){this.state =6;returnfalse;}break;case3:if(d >=0){// Emit the output triple and return to state 0.
value =(value <<6)| d;
output[op+2]=(byte) value;
output[op+1]=(byte)(value >>8);
output[op]=(byte)(value >>16);
op +=3;
state =0;}elseif(d == EQUALS){// Emit the last (partial) output tuple;// expect no further data or padding characters.
output[op+1]=(byte)(value >>2);
output[op]=(byte)(value >>10);
op +=2;
state =5;}elseif(d != SKIP){this.state =6;returnfalse;}break;case4:if(d == EQUALS){++state;}elseif(d != SKIP){this.state =6;returnfalse;}break;case5:if(d != SKIP){this.state =6;returnfalse;}break;}}if(!finish){// We're out of input, but a future call could provide// more.this.state = state;this.value = value;this.op = op;returntrue;}switch(state){case0:break;case1:this.state =6;returnfalse;case2:
output[op++]=(byte)(value >>4);break;case3:
output[op++]=(byte)(value >>10);
output[op++]=(byte)(value >>2);break;case4:this.state =6;returnfalse;case5:break;}this.state = state;this.op = op;returntrue;}}// --------------------------------------------------------// encoding// -------------------------------------------------------- publicstaticString encodeToString(byte[] input,int flags){try{returnnewString(encode(input, flags),"US-ASCII");}catch(UnsupportedEncodingException e){// US-ASCII is guaranteed to be available.thrownewAssertionError(e);}}publicstaticString encodeToString(byte[] input,int offset,int len,int flags){try{returnnewString(encode(input, offset, len, flags),"US-ASCII");}catch(UnsupportedEncodingException e){// US-ASCII is guaranteed to be available.thrownewAssertionError(e);}}publicstaticbyte[] encode(byte[] input,int flags){return encode(input,0, input.length, flags);}publicstaticbyte[] encode(byte[] input,int offset,int len,int flags){Encoder encoder =newEncoder(flags,null);// Compute the exact length of the array we will produce.int output_len = len /3*4;// Account for the tail of the data and the padding bytes, if any.if(encoder.do_padding){if(len %3>0){
output_len +=4;}}else{switch(len %3){case0:break;case1: output_len +=2;break;case2: output_len +=3;break;}}// Account for the newlines, if any.if(encoder.do_newline && len >0){
output_len +=(((len-1)/(3*Encoder.LINE_GROUPS))+1)*(encoder.do_cr ?2:1);}
encoder.output =newbyte[output_len];
encoder.process(input, offset, len,true);assert encoder.op == output_len;return encoder.output;}/* package */staticclassEncoderextendsCoder{/**
* Emit a new line every this many output tuples. Corresponds to
* a 76-character line length (the maximum allowable according to
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
*/publicstaticfinalint LINE_GROUPS =19;/**
* Lookup table for turning Base64 alphabet positions (6 bits)
* into output bytes.
*/privatestaticfinalbyte ENCODE[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',};/**
* Lookup table for turning Base64 alphabet positions (6 bits)
* into output bytes.
*/privatestaticfinalbyte ENCODE_WEBSAFE[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_',};finalprivatebyte[] tail;/* package */int tailLen;privateint count;finalpublicboolean do_padding;finalpublicboolean do_newline;finalpublicboolean do_cr;finalprivatebyte[] alphabet;publicEncoder(int flags,byte[] output){this.output = output;
do_padding =(flags & NO_PADDING)==0;
do_newline =(flags & NO_WRAP)==0;
do_cr =(flags & CRLF)!=0;
alphabet =((flags & URL_SAFE)==0)? ENCODE : ENCODE_WEBSAFE;
tail =newbyte[2];
tailLen =0;
count = do_newline ? LINE_GROUPS :-1;}/**
* @return an overestimate for the number of bytes {@code
* len} bytes could encode to.
*/publicint maxOutputSize(int len){return len *8/5+10;}publicboolean process(byte[] input,int offset,int len,boolean finish){// Using local variables makes the encoder about 9% faster.finalbyte[] alphabet =this.alphabet;finalbyte[] output =this.output;int op =0;int count =this.count;int p = offset;
len += offset;int v =-1;// First we need to concatenate the tail of the previous call// with any input bytes available now and see if we can empty// the tail.switch(tailLen){case0:// There was no tail.break;case1:if(p+2<= len){// A 1-byte tail with at least 2 bytes of// input available now.
v =((tail[0]&0xff)<<16)|((input[p++]&0xff)<<8)|(input[p++]&0xff);
tailLen =0;};break;case2:if(p+1<= len){// A 2-byte tail with at least 1 byte of input.
v =((tail[0]&0xff)<<16)|((tail[1]&0xff)<<8)|(input[p++]&0xff);
tailLen =0;}break;}if(v !=-1){
output[op++]= alphabet[(v >>18)&0x3f];
output[op++]= alphabet[(v >>12)&0x3f];
output[op++]= alphabet[(v >>6)&0x3f];
output[op++]= alphabet[v &0x3f];if(--count ==0){if(do_cr) output[op++]='\r';
output[op++]='\n';
count = LINE_GROUPS;}}// At this point either there is no tail, or there are fewer// than 3 bytes of input available.// The main loop, turning 3 input bytes into 4 output bytes on// each iteration.while(p+3<= len){
v =((input[p]&0xff)<<16)|((input[p+1]&0xff)<<8)|(input[p+2]&0xff);
output[op]= alphabet[(v >>18)&0x3f];
output[op+1]= alphabet[(v >>12)&0x3f];
output[op+2]= alphabet[(v >>6)&0x3f];
output[op+3]= alphabet[v &0x3f];
p +=3;
op +=4;if(--count ==0){if(do_cr) output[op++]='\r';
output[op++]='\n';
count = LINE_GROUPS;}}if(finish){if(p-tailLen == len-1){int t =0;
v =((tailLen >0? tail[t++]: input[p++])&0xff)<<4;
tailLen -= t;
output[op++]= alphabet[(v >>6)&0x3f];
output[op++]= alphabet[v &0x3f];if(do_padding){
output[op++]='=';
output[op++]='=';}if(do_newline){if(do_cr) output[op++]='\r';
output[op++]='\n';}}elseif(p-tailLen == len-2){int t =0;
v =(((tailLen >1? tail[t++]: input[p++])&0xff)<<10)|(((tailLen >0? tail[t++]: input[p++])&0xff)<<2);
tailLen -= t;
output[op++]= alphabet[(v >>12)&0x3f];
output[op++]= alphabet[(v >>6)&0x3f];
output[op++]= alphabet[v &0x3f];if(do_padding){
output[op++]='=';}if(do_newline){if(do_cr) output[op++]='\r';
output[op++]='\n';}}elseif(do_newline && op >0&& count != LINE_GROUPS){if(do_cr) output[op++]='\r';
output[op++]='\n';}assert tailLen ==0;assert p == len;}else{// Save the leftovers in tail to be consumed on the next// call to encodeInternal.if(p == len-1){
tail[tailLen++]= input[p];}elseif(p == len-2){
tail[tailLen++]= input[p];
tail[tailLen++]= input[p+1];}}this.op = op;this.count = count;returntrue;}}privateBase64(){}// don't instantiate}
Dalam kode yang dikompilasi dengan Java 7 tetapi berpotensi berjalan dalam versi java yang lebih tinggi, tampaknya berguna untuk mendeteksi keberadaan java.util.Base64 kelas dan menggunakan pendekatan terbaik untuk diberikan JVM yang disebutkan dalam pertanyaan lain di sini.
Jawaban:
Pada v6, Java SE dikirimkan dengan JAXB.
javax.xml.bind.DatatypeConverter
memiliki metode statis yang membuatnya mudah. LihatparseBase64Binary()
danprintBase64Binary()
.sumber
printBase64Binary(..)
metode ini tidak melakukan versi MIME dari Base64 ( en.wikipedia.org/wiki/Base64#MIME ), sementara implementasi private Sun dan the Commons menggunakan ini. Khususnya, untuk String yang lebih besar dari 76 karakter, baris baru ditambahkan. Saya tidak menemukan cara mengkonfigurasi implementasi JAXB untuk perilaku ini ... :-(Pada Java 8 , ada API yang didukung secara resmi untuk encoding dan decoding Base64. Pada waktunya, ini mungkin akan menjadi pilihan default.
API mencakup kelas
java.util.Base64
dan kelas bersarangnya. Ini mendukung tiga rasa berbeda: dasar, URL aman, dan MIME.Kode sampel menggunakan pengkodean "dasar":
The dokumentasi untuk
java.util.Base64
mencakup beberapa metode yang lebih untuk mengkonfigurasi encoders dan decoders, dan untuk menggunakan kelas yang berbeda sebagai input dan output (array byte, string, ByteBuffers, java.io sungai).sumber
final byte[] decoded = Base64.getMimeDecoder().decode(encoded);
sebagai gantinya. Tapi Terimakasih! (Baik dengan commons-ioFileUtils.readFileToByteArray
danFileUtils.writeByteArrayToFile
- terutama ketika Anda menyadariencoded
bisa menjadibyte[]
juga.)Tidak perlu menggunakan commons - Sun mengirimkan encoder base64 dengan Java. Anda dapat mengimpornya seperti:
Dan kemudian gunakan seperti ini:
Dimana
encodedBytes
ajava.lang.String
atau ajava.io.InputStream
. Berhati - hatilah karena itusun.*
kelas tidak "didukung secara resmi" oleh Sun.EDIT: Siapa yang tahu ini akan menjadi jawaban paling kontroversial yang pernah saya posting? Saya tahu bahwa sun. * Paket tidak didukung atau dijamin untuk terus ada, dan saya tahu tentang Commons dan menggunakannya setiap saat. Namun, poster itu meminta kelas yang "disertakan dengan Sun Java 6," dan itulah yang saya coba jawab. Saya setuju bahwa Commons adalah cara terbaik untuk pergi secara umum.
EDIT 2: Seperti yang ditunjukkan amir75 di bawah ini, Java 6+ dikirimkan bersama JAXB, yang berisi kode yang didukung untuk menyandikan / mendekode Base64. Silakan lihat jawaban Jeremy Ross di bawah ini.
sumber
Khususnya di Commons Codec : kelas
Base64
kedecode(byte[] array)
atauencode(byte[] array)
sumber
Guava sekarang memiliki decoding Base64 bawaan.
Gunakan BaseEncoding.base64 (). Decode ()
Adapun untuk menangani spasi mungkin dalam penggunaan input
BaseEncoding.base64().decode(CharMatcher.WHITESPACE.removeFrom(...));
Lihat diskusi ini untuk informasi lebih lanjut
sumber
Solusi saya tercepat dan termudah.
sumber
byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));
// => trueInilah implementasi saya sendiri, jika bisa bermanfaat bagi seseorang:
sumber
Sebagai alternatif
sun.misc.BASE64Decoder
atau pustaka non-inti, lihatjavax.mail.internet.MimeUtility.decode()
.Tautan dengan kode lengkap: Encode / Decode ke / dari Base64
sumber
Jawaban terlambat lainnya, tetapi pembandingan saya menunjukkan bahwa implementasi Jetty dari encoder Base64 cukup cepat. Tidak secepat MiGBase64 tetapi lebih cepat dari iHarder Base64 .
Saya juga melakukan beberapa tolok ukur:
Ini dijalankan / dtk jadi lebih tinggi lebih baik.
sumber
Diberikan contoh uji sandi / dekode javax.xml.bind.DatatypeConverter menggunakan metode parseBase64Binary () dan printBase64Binary () merujuk ke @ jeremy-ross dan @nightfirecat jawaban.
Hasil:
sumber
Jika Anda lebih suka solusi berbasis kinerja maka Anda dapat menggunakan "MiGBase64"
http://migbase64.sourceforge.net/
sumber
Ini adalah jawaban yang terlambat , tetapi Joshua Bloch melakukan
Base64
kelasnya (ketika ia bekerja untuk Sun, ahem, Oracle) di bawahjava.util.prefs
paket. Kelas ini ada sejak JDK 1.4.Misalnya
sumber
java.util.Base64
java.util.Base64
dirilis di JDK 8 (dan lebih tinggi). Itu tidak ada pada rilis sebelumnya.Semoga ini bisa membantu Anda:
Atau:
java.util.prefs.Base64
bekerja di lokalrt.jar
,Tetapi itu tidak ada dalam Daftar Putih Kelas JRE
dan tidak di kelas yang tersedia tidak tercantum dalam daftar putih GAE / J
Sayang sekali!
PS. Di android, itu mudah karena
android.util.Base64
sudah dimasukkan sejak Android API Level 8.sumber
Anda dapat menulis atau mengunduh file dari string Base64 yang disandikan:
Bekerja untuk saya dan semoga juga untuk Anda ...
sumber
Implementasi Java 8
java.util.Base64
tidak memiliki dependensi pada kelas khusus Java 8 lainnya.Saya tidak yakin apakah ini akan berfungsi untuk proyek Java 6, tetapi dimungkinkan untuk menyalin dan menempelkan
Base64.java
file ke proyek Java 7 dan mengkompilasinya tanpa modifikasi selain mengimpor java.util.Arrays danjava.util.Objects
.Perhatikan bahwa file Base64.java dicakup oleh GNU GPL2
sumber
Saya menggunakan
android.util.base64
yang berfungsi cukup baik tanpa ketergantungan:Pemakaian:
paket com.test;
sumber
Menggunakan Java 8 -
sumber
Anda bisa mencoba ini.
"Base64.getDecode ()" mengembalikan Dekoder Base64 yang dapat diterjemahkan. Maka Anda perlu memecahkan kode itu lagi menggunakan ".decode ()"
sumber
Dalam kode yang dikompilasi dengan Java 7 tetapi berpotensi berjalan dalam versi java yang lebih tinggi, tampaknya berguna untuk mendeteksi keberadaan
java.util.Base64
kelas dan menggunakan pendekatan terbaik untuk diberikan JVM yang disebutkan dalam pertanyaan lain di sini.Saya menggunakan kode ini:
sumber
sumber