📄 base64.java
字号:
}
break;
}
}// end for
if ( cycle != 0 )
{
throw new ArrayIndexOutOfBoundsException(
"Input to decode not an even multiple of 4 characters; pad with "
+ spec3 );
}
j -= dummies;
if ( b.length != j )
{
byte[] b2 = new byte[j];
System.arraycopy( b, 0, b2, 0, j );
b = b2;
}
return b;
}// end decode
/**
* Encode an arbitrary array of bytes as Base64 printable ASCII. It will be broken into lines of 72 chars each. The
* last line is not terminated with a line separator. The output will always have an even multiple of data
* characters, exclusive of \n. It is padded out with =.
*
* @param b byte array to encode, typically produced by a ByteArrayOutputStream.
* @return base-64 encoded String, not char[] or byte[].
* @noinspection WeakerAccess,CanBeFinal
*/
public String encode( byte[] b )
{
// Each group or partial group of 3 bytes becomes four chars
// covered quotient
int outputLength = ( ( b.length + 2 ) / 3 ) * 4;
// account for trailing newlines, on all but the very last line
if ( lineLength != 0 )
{
int lines = ( outputLength + lineLength - 1 ) / lineLength - 1;
if ( lines > 0 )
{
outputLength += lines * lineSeparator.length();
}
}
// must be local for recursion to work.
StringBuffer sb = new StringBuffer( outputLength );
// must be local for recursion to work.
int linePos = 0;
// first deal with even multiples of 3 bytes.
int len = ( b.length / 3 ) * 3;
int leftover = b.length - len;
for ( int i = 0; i < len; i += 3 )
{
// Start a new line if next 4 chars won't fit on the current line
// We can't encapsulete the following code since the variable need
// to
// be local to this incarnation of encode.
linePos += 4;
if ( linePos > lineLength )
{
if ( lineLength != 0 )
{
sb.append( lineSeparator );
}
// linePos = 4;
}
// get next three bytes in unsigned form lined up,
// in big-endian order
int combined = b[ i ] & 0xff;
combined <<= 8;
combined |= b[ i + 1 ] & 0xff;
combined <<= 8;
combined |= b[ i + 2 ] & 0xff;
// break those 24 bits into a 4 groups of 6 bits,
// working LSB to MSB.
int c3 = combined & 0x3f;
combined >>>= 6;
int c2 = combined & 0x3f;
combined >>>= 6;
int c1 = combined & 0x3f;
combined >>>= 6;
int c0 = combined & 0x3f;
// Translate into the equivalent alpha character
// emitting them in big-endian order.
sb.append( valueToChar[ c0 ] );
sb.append( valueToChar[ c1 ] );
sb.append( valueToChar[ c2 ] );
sb.append( valueToChar[ c3 ] );
}
// deal with leftover bytes
switch ( leftover )
{
case 0:
default:
// nothing to do
break;
case 1:
// One leftover byte generates xx==
// Start a new line if next 4 chars won't fit on the current
// line
linePos += 4;
if ( linePos > lineLength )
{
if ( lineLength != 0 )
{
sb.append( lineSeparator );
}
// linePos = 4;
}
// Handle this recursively with a faked complete triple.
// Throw away last two chars and replace with ==
sb.append( encode( new byte[] { b[ len ], 0, 0 } ).substring( 0,
2 ) );
sb.append( spec3 );
sb.append( spec3 );
break;
case 2:
// Two leftover bytes generates xxx=
// Start a new line if next 4 chars won't fit on the current
// line
linePos += 4;
if ( linePos > lineLength )
{
if ( lineLength != 0 )
{
sb.append( lineSeparator );
}
// linePos = 4;
}
// Handle this recursively with a faked complete triple.
// Throw away last char and replace with =
sb.append( encode( new byte[] {
b[ len ], b[ len + 1 ], 0 } ).substring( 0, 3 ) );
sb.append( spec3 );
break;
}// end switch;
if ( outputLength != sb.length() )
{
System.out
.println(
"oops: minor program flaw: output length mis-estimated" );
System.out.println( "estimate:" + outputLength );
System.out.println( "actual:" + sb.length() );
}
return sb.toString();
}// end encode
/**
* determines how long the lines are that are generated by encode. Ignored by decode.
*
* @param length 0 means no newlines inserted. Must be a multiple of 4.
* @noinspection WeakerAccess
*/
public final void setLineLength( int length )
{
this.lineLength = ( length / 4 ) * 4;
}
/**
* How lines are separated. Ignored by decode.
*
* @param lineSeparator may be "" but not null. Usually contains only a combination of chars \n and \r. Could be any
* chars not in set A-Z a-z 0-9 + /.
*/
public final void setLineSeparator( String lineSeparator )
{
this.lineSeparator = lineSeparator;
}
// -------------------------- OTHER METHODS --------------------------
/**
* Initialise both static and instance table.
*/
private void initTables()
{
/* initialise valueToChar and charToValue tables */
if ( vc == null )
{
// statics are not initialised yet
vc = new char[64];
cv = new int[256];
// build translate valueToChar table only once.
// 0..25 -> 'A'..'Z'
for ( int i = 0; i <= 25; i++ )
{
vc[ i ] = ( char ) ( 'A' + i );
}
// 26..51 -> 'a'..'z'
for ( int i = 0; i <= 25; i++ )
{
vc[ i + 26 ] = ( char ) ( 'a' + i );
}
// 52..61 -> '0'..'9'
for ( int i = 0; i <= 9; i++ )
{
vc[ i + 52 ] = ( char ) ( '0' + i );
}
vc[ 62 ] = spec1;
vc[ 63 ] = spec2;
// build translate charToValue table only once.
for ( int i = 0; i < 256; i++ )
{
cv[ i ] = IGNORE;// default is to ignore
}
for ( int i = 0; i < 64; i++ )
{
cv[ vc[ i ] ] = i;
}
cv[ spec3 ] = PAD;
}
valueToChar = vc;
charToValue = cv;
}
// --------------------------- main() method ---------------------------
/**
* test driver.
*
* @param args not used
* @noinspection ConstantConditions
*/
public static void main( String[] args )
{
if ( DEBUGGING )
{
byte[] a = { ( byte ) 0xfc, ( byte ) 0x0f, ( byte ) 0xc0 };
byte[] b = { ( byte ) 0x03, ( byte ) 0xf0, ( byte ) 0x3f };
byte[] c = { ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00 };
byte[] d = { ( byte ) 0xff, ( byte ) 0xff, ( byte ) 0xff };
byte[] e = { ( byte ) 0xfc, ( byte ) 0x0f, ( byte ) 0xc0, ( byte ) 1 };
byte[] f =
{ ( byte ) 0xfc, ( byte ) 0x0f, ( byte ) 0xc0, ( byte ) 1, ( byte ) 2 };
byte[] g = {
( byte ) 0xfc,
( byte ) 0x0f,
( byte ) 0xc0,
( byte ) 1,
( byte ) 2,
( byte ) 3 };
byte[] h = "AAAAAAAAAAB".getBytes();
show( a );
show( b );
show( c );
show( d );
show( e );
show( f );
show( g );
show( h );
Base64 b64 = new Base64();
show( b64.decode( b64.encode( a ) ) );
show( b64.decode( b64.encode( b ) ) );
show( b64.decode( b64.encode( c ) ) );
show( b64.decode( b64.encode( d ) ) );
show( b64.decode( b64.encode( e ) ) );
show( b64.decode( b64.encode( f ) ) );
show( b64.decode( b64.encode( g ) ) );
show( b64.decode( b64.encode( h ) ) );
b64.setLineLength( 8 );
show( ( b64.encode( h ) ).getBytes() );
}
}// end main
}// end Base64
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -