public static byte [ ] decode ( String chars ) { if ( chars == null || chars . length ( ) == 0 ) { throw new IllegalArgumentException ( "You must provide a non-zero length input" ) ; } //By using five ASCII characters to represent four bytes of binary data the encoded size ¹⁄₄ is larger than the original BigDecimal decodedLength = BigDecimal . valueOf ( chars . length ( ) ) . multiply ( BigDecimal . valueOf ( 4 ) ) . divide ( BigDecimal . valueOf ( 5 ) ) ; ByteBuffer bytebuff = ByteBuffer . allocate ( decodedLength . intValue ( ) ) ; //1. Whitespace characters may occur anywhere to accommodate line length limitations. So lets strip it. chars = REMOVE_WHITESPACE . matcher ( chars ) . replaceAll ( "" ) ; //Since Base85 is an ascii encoder, we don't need to get the bytes as UTF-8. byte [ ] payload = chars . getBytes ( StandardCharsets . US_ASCII ) ; byte [ ] chunk = new byte [ 5 ] ; int chunkIndex = 0 ; for ( int i = 0 ; i < payload . length ; i ++ ) { byte currByte = payload [ i ] ; //Because all-zero data is quite common, an exception is made for the sake of data compression, //and an all-zero group is encoded as a single character "z" instead of "!!!!!". if ( currByte == ' ' ) { if ( chunkIndex > 0 ) { throw new IllegalArgumentException ( "The payload is not base 85 encoded." ) ; } chunk [ chunkIndex ++ ] = ' ' ; chunk [ chunkIndex ++ ] = ' ' ; chunk [ chunkIndex ++ ] = ' ' ; chunk [ chunkIndex ++ ] = ' ' ; chunk [ chunkIndex ++ ] = ' ' ; } else { chunk [ chunkIndex ++ ] = currByte ; } if ( chunkIndex == 5 ) { bytebuff . put ( decodeChunk ( chunk ) ) ; Arrays . fill ( chunk , ( byte ) 0 ) ; chunkIndex = 0 ; } } //If we didn't end on 0, then we need some padding if ( chunkIndex > 0 ) { int numPadded = chunk . length - chunkIndex ; Arrays . fill ( chunk , chunkIndex , chunk . length , ( byte ) ' ' ) ; byte [ ] paddedDecode = decodeChunk ( chunk ) ; for ( int i = 0 ; i < paddedDecode . length - numPadded ; i ++ ) { bytebuff . put ( paddedDecode [ i ] ) ; } } bytebuff . flip ( ) ; return Arrays . copyOf ( bytebuff . array ( ) , bytebuff . limit ( ) ) ; }
This is a very simple base85 decoder . It respects the z optimization for empty chunks and strips whitespace between characters to respect line limits .