У меня есть изображение в кодировке Base64. Каков лучший способ расшифровать это в Java? Надеемся использовать только библиотеки, включенные в Sun Java 6.
Независимо от того, какое приложение вы используете (экспериментальное или нет), это так же просто, как создать отдельный файл Base64.java в вашем пакете утилит, используя следующий код: migbase64.sourceforge.net Посмотрите на графики производительности и обратите внимание на разницу: В 4-5 раз быстрее.
Javacoder
К вашему сведению: JEP 135 предлагает ввести стандартный, обнаруживаемый API для этого на платформе Java.
Однако, похоже, что printBase64Binary(..)метод не поддерживает MIME-версию Base64 ( en.wikipedia.org/wiki/Base64#MIME ), в то время как частные реализации Sun и Commons используют это. В частности, для строки длиной более 76 символов добавляются новые строки. Я не нашел, как настроить реализацию JAXB для этого поведения ... :-(
KLE
7
Однако реализация Sun будет игнорировать переводы строки. Так что они совместимы.
Эсбен Сков Педерсен
9
Предупреждение! parseBase64Binary автоматически пропустит недопустимые символы и не проверит правильность base64. Лучше использовать Commons Codec или Guava Base64. Обратите внимание, что Guava отклоняет символы новой строки и пробельные символы, поэтому вам необходимо проанализировать строки с пропущенными пробелами: BaseEncoding.base64 (). Decode (s.replaceAll ("\\ s", ""))
Мартин Висны,
9
Быть осторожен. Эта функция не работает с данными, длина которых превышает 65000. (Java версия 1.6)
Hüseyin Yağlı
5
Не используйте его, потому что вы получите проблемы в jdk 9: java.lang.NoClassDefFoundError (javax / xml / bind / DatatypeConverter)
rupashka
381
Начиная с Java 8 , существует официально поддерживаемый API для кодирования и декодирования Base64. Со временем это, вероятно, станет выбором по умолчанию.
API включает в себя класс java.util.Base64 и его вложенные классы. Он поддерживает три различных варианта: базовый, безопасный URL и MIME.
Документацияjava.util.Base64 включает в себя еще несколько способов для настройки кодеров и декодеров, а также для использования различных классов в качестве входов и выходов (байтовых массивов, строк, ByteBuffers, java.io потоков).
Я использую Java 8. Является ли это рекомендуемым подходом при использовании Java 8?
ДжонМерлино
4
@JohnMerlino, если совместимость со старыми версиями Java не требуется, я бы рекомендовал использовать этот API, поскольку JRE имеет более строгую политику совместимости, чем большинство библиотек. Кроме того, будучи включенным в JRE, это никак не ограничивает ваши зависимости.
Андреа
4
Java 7 EOLed, Java 9 идет, это правильный ответ для меня!
eskatos
1
Почти хорошо: он принимает только необработанные потоки base64, а не файлы base64. Я должен был использовать final byte[] decoded = Base64.getMimeDecoder().decode(encoded);вместо этого. Но все равно спасибо! (Хорошо с обыкновенными FileUtils.readFileToByteArrayи FileUtils.writeByteArrayToFile- особенно, когда ты понимаешь, что encodedможет быть byte[]также.)
mirabilos
101
Нет необходимости использовать обыкновенные - Sun поставляет кодировщик base64 с Java. Вы можете импортировать его как таковой:
Где encodedBytesили java.lang.Stringили java.io.InputStream. Просто знайте, что sun.*Sun не «официально поддерживает» эти классы.
РЕДАКТИРОВАТЬ: Кто знал, что это будет самый спорный ответ, который я когда-либо отправлять? Я знаю, что пакеты sun. * Не поддерживаются и не гарантированно продолжают существовать, и я знаю о Commons и использую их постоянно. Тем не менее, автор попросил класс, который был «включен в Sun Java 6», и я пытался ответить на него. Я согласен, что Commons - лучший способ пойти в общем.
РЕДАКТИРОВАТЬ 2: Как amir75 указывает ниже, Java 6+ поставляется с JAXB, который содержит поддерживаемый код для кодирования / декодирования Base64. Пожалуйста, смотрите ответ Джереми Росса ниже.
-1 - это внутренний код Sun, НЕ являющийся частью J2SE (он не является переносимым) и может исчезнуть в любое время - Sun прямо говорит НЕ использовать свои внутренние библиотеки в коде пользователя
kdgregory
59
Правда, поэтому мой отказ от ответственности в конце.
MattK
20
Это для краткосрочного проекта, это всего лишь эксперимент, и мы не хотим проходить процесс утверждения новой библиотеки. Так что это правильный ответ на этот вопрос.
Райан П
44
Bzzt. В профессиональной среде использование неподдерживаемых недокументированных функций никогда не является правильным решением. А в корпоративной среде «эксперименты» превращаются в «производственный код» без возможности исправить взломы.
kdgregory
29
В научно-исследовательском отделе, где этот код помечен как эксперимент, а когда он помечен, всегда отбрасывается, это правильное решение.
Райан П
55
В частности , в Commons Codec : класс Base64к decode(byte[] array)илиencode(byte[] array)
Вы можете связать текст «Commons Codec» со страницей проекта. Таким образом, этот ответ будет лучше, чем у Кевина :)
mmutilva
1
Я знаю, что это старый вопрос, но почему это не принятый ответ? Разве кодек общего достояния не включен в большинство установок Java и требует гораздо меньше строк кода, чем ваша собственная версия?
Ли Хаои
2
@LiHaoyi Вопрос задавался для библиотек, которые поставлялись с JDK от Sun, который не содержит ничего от Commons.
Ti Strga
1
Ложная дорожка. Этих методов не существует!
Николас Барбулеско
36
Гуава теперь имеет встроенное декодирование Base64.
Guava 14 по-прежнему является кандидатом на релиз, но это по-прежнему вызывает мое одобрение - к тому моменту, когда оно достигает какой-либо достойной позиции, оно должно быть золотым :-)
Peter Becker
1
Guava base64 декодер отклоняет символы новой строки и пробела, поэтому вы должны удалить их заранее.
Мартин Высный
34
Мое решение самое быстрое и простое.
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;}}
это не глючит! - читать комментарии javadoc ... параметр decode (..) - это base64 String, а не просто String. byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));// => true
GeorgeK
9
Самый быстрый и легкий ?? Изобретая колесо ?!
Николас Барбулеско
7
Я провел несколько тестов, сравнивая этот класс с commons-codec, и, похоже, он работает нормально. Мне нужно что-то простое, как это, потому что мне нужно было только кодирование base64, и я не хотел всех дополнительных вещей, которые предоставляет commons-codec, спасибо.
Майкл
2
Это доверчиво? Это кажется самым простым, если вы не хотите импортировать внешние библиотеки.
Фелипе
2
он не работает с байтами, полученными из алгоритма AES
shontauro
11
Вот моя собственная реализация, если она может быть кому-то полезна:
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 прост в использовании, хорошо закодирован и быстро работает. Хорошая находка, Имби.
Мукама
Согласно этому тесту, MiGBase64 больше не является самой быстрой реализацией, и теперь он значительно отстает от Apache Commons и sun.misc.BASE64Decoder.
Андреа
3
Это поздний ответ, но Джошуа Блох посвятил свой Base64класс (когда он работал в Sun, гм, Oracle) в рамках java.util.prefsпакета. Этот класс существует с JDK 1.4.
Реализация Java 8 java.util.Base64не имеет зависимостей от других специфических классов Java 8.
Я не уверен, будет ли это работать для проекта Java 6, но возможно скопировать и вставить Base64.javaфайл в проект Java 7 и скомпилировать его без изменений, кроме импорта java.util.Arrays иjava.util.Objects .
Обратите внимание, что файл Base64.java защищен 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}
В коде, скомпилированном с Java 7, но потенциально работающем в более высокой версии Java, кажется полезным обнаружить наличие java.util.Base64 класса и использовать подход, наилучший для данной JVM, упомянутый в других вопросах здесь.
Ответы:
Начиная с версии 6, Java SE поставляется с JAXB.
javax.xml.bind.DatatypeConverter
есть статические методы, которые делают это легко. СмотритеparseBase64Binary()
иprintBase64Binary()
.источник
printBase64Binary(..)
метод не поддерживает MIME-версию Base64 ( en.wikipedia.org/wiki/Base64#MIME ), в то время как частные реализации Sun и Commons используют это. В частности, для строки длиной более 76 символов добавляются новые строки. Я не нашел, как настроить реализацию JAXB для этого поведения ... :-(Начиная с Java 8 , существует официально поддерживаемый API для кодирования и декодирования Base64. Со временем это, вероятно, станет выбором по умолчанию.
API включает в себя класс
java.util.Base64
и его вложенные классы. Он поддерживает три различных варианта: базовый, безопасный URL и MIME.Пример кода с использованием «базовой» кодировки:
Документация
java.util.Base64
включает в себя еще несколько способов для настройки кодеров и декодеров, а также для использования различных классов в качестве входов и выходов (байтовых массивов, строк, ByteBuffers, java.io потоков).источник
final byte[] decoded = Base64.getMimeDecoder().decode(encoded);
вместо этого. Но все равно спасибо! (Хорошо с обыкновеннымиFileUtils.readFileToByteArray
иFileUtils.writeByteArrayToFile
- особенно, когда ты понимаешь, чтоencoded
может бытьbyte[]
также.)Нет необходимости использовать обыкновенные - Sun поставляет кодировщик base64 с Java. Вы можете импортировать его как таковой:
И затем используйте это так:
Где
encodedBytes
илиjava.lang.String
илиjava.io.InputStream
. Просто знайте, чтоsun.*
Sun не «официально поддерживает» эти классы.РЕДАКТИРОВАТЬ: Кто знал, что это будет самый спорный ответ, который я когда-либо отправлять? Я знаю, что пакеты sun. * Не поддерживаются и не гарантированно продолжают существовать, и я знаю о Commons и использую их постоянно. Тем не менее, автор попросил класс, который был «включен в Sun Java 6», и я пытался ответить на него. Я согласен, что Commons - лучший способ пойти в общем.
РЕДАКТИРОВАТЬ 2: Как amir75 указывает ниже, Java 6+ поставляется с JAXB, который содержит поддерживаемый код для кодирования / декодирования Base64. Пожалуйста, смотрите ответ Джереми Росса ниже.
источник
В частности , в Commons Codec : класс
Base64
кdecode(byte[] array)
илиencode(byte[] array)
источник
Гуава теперь имеет встроенное декодирование Base64.
Используйте BaseEncoding.base64 (). Decode ()
Что касается борьбы с возможными пробелами при использовании ввода
BaseEncoding.base64().decode(CharMatcher.WHITESPACE.removeFrom(...));
Смотрите это обсуждение для получения дополнительной информации
источник
Мое решение самое быстрое и простое.
источник
byte[] b1 = {1,2,3}; byte[] b2 = decode(encode(b1)); System.out.println(Arrays.equals( b1, b2 ));
// => trueВот моя собственная реализация, если она может быть кому-то полезна:
источник
В качестве альтернативы
sun.misc.BASE64Decoder
или неосновных библиотек, посмотрите наjavax.mail.internet.MimeUtility.decode()
.Ссылка с полным кодом: кодировать / декодировать в / из Base64
источник
Еще один поздний ответ, но мой сравнительный анализ показывает, что реализация кодера Base64 в Jetty довольно быстрая. Не так быстро, как MiGBase64, но быстрее, чем iHarder Base64 .
Я также сделал несколько тестов:
Это пробеги в секунду, так что чем выше, тем лучше.
источник
Приведен пример тестового кодирования / декодирования javax.xml.bind.DatatypeConverter с использованием методов parseBase64Binary () и printBase64Binary () со ссылкой на ответы @ jeremy-ross и @nightfirecat.
Результат:
источник
Если вы предпочитаете решение на основе производительности, вы можете использовать «MiGBase64»
http://migbase64.sourceforge.net/
источник
Это поздний ответ, но Джошуа Блох посвятил свой
Base64
класс (когда он работал в Sun, гм, Oracle) в рамкахjava.util.prefs
пакета. Этот класс существует с JDK 1.4.Например
источник
java.util.Base64
java.util.Base64
был выпущен в JDK 8 (и выше). Это не существует в более ранних выпусках.Надеюсь, это поможет вам:
Или:
java.util.prefs.Base64
работает на местномrt.jar
,Но его нет в белом списке класса JRE
и не в доступных классах, не перечисленных в белом списке GAE / J
Какая жалость!
PS. В Android это легко, потому что
android.util.Base64
это было включено с Android API Level 8.источник
Вы можете написать или скачать файл из закодированной строки Base64:
Работал для меня и, надеюсь, для вас также ...
источник
Реализация Java 8
java.util.Base64
не имеет зависимостей от других специфических классов Java 8.Я не уверен, будет ли это работать для проекта Java 6, но возможно скопировать и вставить
Base64.java
файл в проект Java 7 и скомпилировать его без изменений, кроме импорта java.util.Arrays иjava.util.Objects
.Обратите внимание, что файл Base64.java защищен GNU GPL2.
источник
Я использовал
android.util.base64
это работает довольно хорошо без каких-либо зависимостей:Применение:
пакет com.test;
источник
Используя Java 8 -
источник
Вы можете просто попробовать это.
«Base64.getDecode ()» возвращает декодер Base64, который можно декодировать. Затем вам нужно декодировать это снова, используя ".decode ()"
источник
В коде, скомпилированном с Java 7, но потенциально работающем в более высокой версии Java, кажется полезным обнаружить наличие
java.util.Base64
класса и использовать подход, наилучший для данной JVM, упомянутый в других вопросах здесь.Я использовал этот код:
источник
источник