Ich habe ein Bild, das Base64-codiert ist. Was ist der beste Weg, um das in Java zu dekodieren? Hoffentlich werden nur die in Sun Java 6 enthaltenen Bibliotheken verwendet.
Unabhängig davon, welche Art von App Sie verwenden (experimentieren oder nicht), ist es genauso einfach wie das Erstellen einer einzelnen Base64.java-Datei in Ihrem Utils-Paket mit dem folgenden Code: migbase64.sourceforge.net Sehen Sie sich die Leistungsdiagramme an und stellen Sie den Unterschied fest: 4-5 mal so schnell.
Javacoder
Zu Ihrer Information: JEP 135 schlägt vor, eine standardmäßige, erkennbare API dafür in die Java-Plattform einzuführen.
Es scheint jedoch, dass die printBase64Binary(..)Methode die MIME-Version von Base64 ( en.wikipedia.org/wiki/Base64#MIME ) nicht ausführt , während die privaten Sun- und Commons-Implementierungen dies verwenden. Insbesondere für Zeichenfolgen mit mehr als 76 Zeichen werden Zeilenumbrüche hinzugefügt. Ich habe nicht gefunden, wie ich die Implementierung von JAXB für dieses Verhalten konfigurieren kann ... :-(
KLE
7
Die Sun-Implementierung ignoriert jedoch Zeilenumbrüche. Sie sind also kompatibel.
Esben Skov Pedersen
9
Warnung! parseBase64Binary überspringt stillschweigend ungültige Zeichen und überprüft nicht die Gültigkeit von base64. Es ist besser, Commons Codec oder Guava Base64 zu verwenden. Beachten Sie, dass Guava Zeilenumbrüche und Leerzeichen ablehnt. Daher müssen Sie Zeichenfolgen mit ausgelassenen Leerzeichen analysieren: BaseEncoding.base64 (). Decode (s.replaceAll ("\\ s", ""))
Martin Vysny
9
Achtung. Diese Funktion funktioniert nicht mit Daten, die länger als 65000 sind. (Java Version 1.6)
Hüseyin Yağlı
5
Verwenden Sie es nicht, da in jdk 9 Probleme auftreten: java.lang.NoClassDefFoundError (javax / xml / bind / DatatypeConverter)
rupashka
381
Ab Java 8 gibt es eine offiziell unterstützte API für die Base64-Codierung und -Decodierung. Mit der Zeit wird dies wahrscheinlich die Standardauswahl sein.
Die API enthält die Klasse java.util.Base64und ihre verschachtelten Klassen. Es werden drei verschiedene Varianten unterstützt: Basic, URL Safe und MIME.
Die Dokumentation fürjava.util.Base64 enthält mehrere weitere Methoden zum Konfigurieren von Encodern und Decodern sowie zum Verwenden verschiedener Klassen als Ein- und Ausgänge (Byte-Arrays, Strings, ByteBuffers, java.io-Streams).
Ich verwende Java 8. Ist dies der empfohlene Ansatz, wenn Sie Java 8 verwenden?
John Merlino
4
@ JohnMerlino Wenn keine Kompatibilität mit älteren Java-Versionen erforderlich ist, würde ich die Verwendung dieser API empfehlen, da die JRE eine strengere Kompatibilitätsrichtlinie aufweist als die meisten Bibliotheken. Durch die Aufnahme in die JRE werden Ihre Abhängigkeiten in keiner Weise eingeschränkt.
Andrea
4
Java 7 ist EOLed, Java 9 kommt, das ist die richtige Antwort für mich!
Eskatos
1
Fast gut: Dies akzeptiert nur rohe Base64-Streams, keine Base64-Dateien. Ich musste final byte[] decoded = Base64.getMimeDecoder().decode(encoded);stattdessen verwenden. Danke trotzdem! (Schön mit Commons-Io FileUtils.readFileToByteArrayund FileUtils.writeByteArrayToFile- besonders wenn Sie erkennen, encodeddass es auch ein sein kann byte[].)
Mirabilos
101
Keine Notwendigkeit, Commons zu verwenden - Sun liefert einen Base64-Encoder mit Java aus. Sie können es als solches importieren:
Wo encodedBytesist entweder ein java.lang.Stringoder ein java.io.InputStream. Beachten Sie nur, dass die sun.*Klassen von Sun nicht "offiziell unterstützt" werden.
EDIT: Wer wusste, dass dies die umstrittenste Antwort sein würde, die ich jemals posten würde? Ich weiß, dass sun. * -Pakete nicht unterstützt werden oder garantiert weiterhin existieren, und ich kenne Commons und verwende sie ständig. Das Poster fragte jedoch nach einer Klasse, die "in Sun Java 6 enthalten" war, und das versuchte ich zu beantworten. Ich stimme zu, dass Commons der beste Weg im Allgemeinen ist.
EDIT 2: Wie amir75 weiter unten ausführt, wird Java 6+ mit JAXB ausgeliefert, das unterstützten Code zum Codieren / Decodieren von Base64 enthält. Bitte sehen Sie die Antwort von Jeremy Ross unten.
-1 - Dies ist interner Sun-Code, ist NICHT Teil von J2SE (es ist nicht portabel) und kann jederzeit verschwinden. - Sun sagt ausdrücklich, dass ihre internen Bibliotheken NICHT im Benutzercode verwendet werden sollen
kdgregory
59
Richtig, daher mein Haftungsausschluss am Ende.
MattK
20
Dies ist ein kurzfristiges Projekt und nur ein Experiment. Sie möchten den Genehmigungsprozess für eine neue Bibliothek nicht durchlaufen. Das ist also die richtige Antwort auf diese Frage.
Ryan P
44
Bzzt. In einem professionellen Umfeld ist die Verwendung einer nicht unterstützten, nicht dokumentierten Funktion niemals die richtige Entscheidung. Und in einer Unternehmensumgebung werden "Experimente" zu "Produktionscode", ohne dass die Möglichkeit besteht, die Hacks zu beheben.
kdgregory
29
In einer Forschungsabteilung, in der dieser Code als Experiment markiert ist und wenn er markiert wird, immer verschrottet wird, ist dies die richtige Entscheidung.
Ryan P
55
Speziell im Commons Codec : Klasse Base64zu decode(byte[] array)oderencode(byte[] array)
Sie können den Text 'Commons Codec' mit der Projektseite verknüpfen. Auf diese Weise wäre diese Antwort besser als die von Kevin :)
mmutilva
1
Ich weiß, dass dies eine alte Frage ist, aber warum ist dies nicht die akzeptierte Antwort? Ist der Commons-Codec nicht in den meisten Java-Installationen enthalten und es sind weit weniger Codezeilen zu verwenden als beim Rollen Ihrer eigenen Version?
Li Haoyi
2
@LiHaoyi Die Frage wurde nach Bibliotheken gestellt, die mit Suns JDK ausgeliefert wurden, das nichts von Commons enthält.
Ti Strga
1
Falsche Spur. Diese Methoden existieren nicht!
Nicolas Barbulesco
36
In Guava ist jetzt die Base64-Dekodierung integriert.
Guava 14 ist immer noch ein Release-Kandidat, aber dies wird immer noch positiv bewertet - wenn es eine anständige Position erreicht, sollte es golden sein :-)
Peter Becker
1
Der Guava Base64-Decoder lehnt Zeilenumbrüche und Leerzeichen ab, sodass Sie sie vorher entfernen müssen.
Martin Vysny
34
Meine Lösung ist am schnellsten und einfachsten.
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;}}
es ist nicht fehlerhaft! - Lesen Sie die Javadoc-Kommentare ... Der Parameter von decode (..) ist base64 String, nicht irgendein String. byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));// => true
GeorgeK
9
Am schnellsten und einfachsten? Das Rad neu erfinden ?!
Nicolas Barbulesco
7
Ich habe einige Tests durchgeführt, in denen diese Klasse mit dem Commons-Codec verglichen wurde, und es scheint in Ordnung zu sein. Ich brauchte so etwas Einfaches, weil ich nur Base64-Codierung brauchte und nicht all die zusätzlichen Dinge wollte, die Commons-Codec bietet, danke.
Michael
2
Ist das vertrauenswürdig? Es scheint am einfachsten zu sein, wenn Sie keine externen Bibliotheken importieren möchten.
Felipe
2
es funktioniert nicht mit Bytes, die vom AES-Algorithmus erhalten wurden
Shontauro
11
Hier ist meine eigene Implementierung, wenn sie für jemanden nützlich sein könnte:
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 ist einfach zu bedienen, gut codiert und blitzschnell. Schöner Fund, Imby.
Mukama
Nach diesem Benchmark ist MiGBase64 nicht mehr die schnellste Implementierung und liegt nun deutlich hinter Apache Commons und sun.misc.BASE64Decoder zurück.
Andrea
3
Dies ist eine späte Antwort, aber Joshua Bloch hat seine Base64Klasse (als er für Sun, ahem, Oracle arbeitete) unter derjava.util.prefs Paket verpflichtet. Diese Klasse existiert seit JDK 1.4.
Die Java 8-Implementierung von java.util.Base64 hat keine Abhängigkeiten von anderen Java 8-spezifischen Klassen.
Ich bin nicht sicher, ob dies für Java 6-Projekte funktioniert, aber es ist möglich, die Base64.javaDatei zu kopieren, in ein Java 7-Projekt einzufügen und sie ohne andere Änderungen als das Importieren von java.util.Arrays und zu kompilierenjava.util.Objects .
Beachten Sie, dass die Base64.java-Datei von der GNU GPL2 abgedeckt wird
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}
In einem Code, der mit Java 7 kompiliert wurde, aber möglicherweise in einer höheren Java-Version ausgeführt wird, scheint es nützlich zu sein, das Vorhandensein von zu erkennen java.util.Base64 Klassen und den Ansatz zu verwenden, der für die in anderen Fragen erwähnte JVM am besten geeignet ist.
Antworten:
Ab Version 6 wird Java SE mit JAXB ausgeliefert.
javax.xml.bind.DatatypeConverter
hat statische Methoden, die dies einfach machen. SieheparseBase64Binary()
undprintBase64Binary()
.quelle
printBase64Binary(..)
Methode die MIME-Version von Base64 ( en.wikipedia.org/wiki/Base64#MIME ) nicht ausführt , während die privaten Sun- und Commons-Implementierungen dies verwenden. Insbesondere für Zeichenfolgen mit mehr als 76 Zeichen werden Zeilenumbrüche hinzugefügt. Ich habe nicht gefunden, wie ich die Implementierung von JAXB für dieses Verhalten konfigurieren kann ... :-(Ab Java 8 gibt es eine offiziell unterstützte API für die Base64-Codierung und -Decodierung. Mit der Zeit wird dies wahrscheinlich die Standardauswahl sein.
Die API enthält die Klasse
java.util.Base64
und ihre verschachtelten Klassen. Es werden drei verschiedene Varianten unterstützt: Basic, URL Safe und MIME.Beispielcode mit der "grundlegenden" Codierung:
Die Dokumentation für
java.util.Base64
enthält mehrere weitere Methoden zum Konfigurieren von Encodern und Decodern sowie zum Verwenden verschiedener Klassen als Ein- und Ausgänge (Byte-Arrays, Strings, ByteBuffers, java.io-Streams).quelle
final byte[] decoded = Base64.getMimeDecoder().decode(encoded);
stattdessen verwenden. Danke trotzdem! (Schön mit Commons-IoFileUtils.readFileToByteArray
undFileUtils.writeByteArrayToFile
- besonders wenn Sie erkennen,encoded
dass es auch ein sein kannbyte[]
.)Keine Notwendigkeit, Commons zu verwenden - Sun liefert einen Base64-Encoder mit Java aus. Sie können es als solches importieren:
Und dann benutze es so:
Wo
encodedBytes
ist entweder einjava.lang.String
oder einjava.io.InputStream
. Beachten Sie nur, dass diesun.*
Klassen von Sun nicht "offiziell unterstützt" werden.EDIT: Wer wusste, dass dies die umstrittenste Antwort sein würde, die ich jemals posten würde? Ich weiß, dass sun. * -Pakete nicht unterstützt werden oder garantiert weiterhin existieren, und ich kenne Commons und verwende sie ständig. Das Poster fragte jedoch nach einer Klasse, die "in Sun Java 6 enthalten" war, und das versuchte ich zu beantworten. Ich stimme zu, dass Commons der beste Weg im Allgemeinen ist.
EDIT 2: Wie amir75 weiter unten ausführt, wird Java 6+ mit JAXB ausgeliefert, das unterstützten Code zum Codieren / Decodieren von Base64 enthält. Bitte sehen Sie die Antwort von Jeremy Ross unten.
quelle
Speziell im Commons Codec : Klasse
Base64
zudecode(byte[] array)
oderencode(byte[] array)
quelle
In Guava ist jetzt die Base64-Dekodierung integriert.
Verwenden Sie BaseEncoding.base64 (). Decode ()
Bezüglich des Umgangs mit möglichen Leerzeichen bei der Verwendung von Eingaben
BaseEncoding.base64().decode(CharMatcher.WHITESPACE.removeFrom(...));
Weitere Informationen finden Sie in dieser Diskussion
quelle
Meine Lösung ist am schnellsten und einfachsten.
quelle
byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));
// => trueHier ist meine eigene Implementierung, wenn sie für jemanden nützlich sein könnte:
quelle
sun.misc.BASE64Decoder
Schauen Sie sich als Alternative zu oder als Nicht-Kernbibliotheken anjavax.mail.internet.MimeUtility.decode()
.Link mit vollständigem Code: Codieren / Decodieren zu / von Base64
quelle
Eine weitere späte Antwort, aber mein Benchmarking zeigt, dass Jettys Implementierung des Base64- Encoders ziemlich schnell ist. Nicht so schnell wie MiGBase64, aber schneller als iHarder Base64 .
Ich habe auch einige Benchmarks gemacht:
Dies sind Läufe / Sek., Daher ist höher besser.
quelle
Bei einem Test Encoder / Decoder Beispiel javax.xml.bind.DatatypeConverter unter Verwendung von Methoden parseBase64Binary () und printBase64Binary () mit Bezug auf @ jeremy-ross und @nightfirecat Antwort.
Ergebnis:
quelle
Wenn Sie eine leistungsbasierte Lösung bevorzugen, können Sie "MiGBase64" verwenden.
http://migbase64.sourceforge.net/
quelle
Dies ist eine späte Antwort, aber Joshua Bloch hat seine
Base64
Klasse (als er für Sun, ahem, Oracle arbeitete) unter derjava.util.prefs
Paket verpflichtet. Diese Klasse existiert seit JDK 1.4.Z.B
quelle
java.util.Base64
java.util.Base64
es in JDK 8 (und höher) veröffentlicht wurde. Es existiert nicht in früheren Versionen.Hoffe das hilft dir:
Oder:
java.util.prefs.Base64
arbeitet auf lokalrt.jar
,Aber es ist nicht in der weißen Liste der JRE-Klasse
und nicht in Verfügbare Klassen, die nicht in der GAE / J-Whitelist aufgeführt sind
Was für eine Schande!
PS. In Android ist es einfach, weil das
android.util.Base64
seit Android API Level 8 enthalten ist.quelle
Sie können eine Datei aus einer codierten Base64-Zeichenfolge schreiben oder herunterladen:
Arbeitete für mich und hoffentlich auch für dich ...
quelle
Die Java 8-Implementierung von
java.util.Base64
hat keine Abhängigkeiten von anderen Java 8-spezifischen Klassen.Ich bin nicht sicher, ob dies für Java 6-Projekte funktioniert, aber es ist möglich, die
Base64.java
Datei zu kopieren, in ein Java 7-Projekt einzufügen und sie ohne andere Änderungen als das Importieren von java.util.Arrays und zu kompilierenjava.util.Objects
.Beachten Sie, dass die Base64.java-Datei von der GNU GPL2 abgedeckt wird
quelle
Ich habe das benutzt
android.util.base64
, das ohne Abhängigkeiten ziemlich gut funktioniert:Verwendungszweck:
Paket com.test;
quelle
Verwenden von Java 8 -
quelle
Sie können dies einfach versuchen.
"Base64.getDecode ()" gibt einen Base64-Decoder zurück, der decodiert werden kann. Dann müssen Sie das erneut mit ".decode ()" dekodieren.
quelle
In einem Code, der mit Java 7 kompiliert wurde, aber möglicherweise in einer höheren Java-Version ausgeführt wird, scheint es nützlich zu sein, das Vorhandensein von zu erkennen
java.util.Base64
Klassen und den Ansatz zu verwenden, der für die in anderen Fragen erwähnte JVM am besten geeignet ist.Ich habe diesen Code verwendet:
quelle
quelle