Java Base64

问题:

在做Http请求是,将url进行base64编码时结果中有换行,导致请求GetMethod method = new GetMethod(url), 跑出" Invalid query" Exception,

 使用java自带的下面两种转化方法, 本地windows系统测试没有问题,可以正常请求,代码部署到Linux系统上问题出现

String encode = "";
byte[] bytes = StringUtils.getBytesUtf8(code); //将一组字符编码为一个字节序列.
try
{
  encode = new BASE64Encoder().encode(bytes);
//encode = Base64.encodeBase64String(bytes);; //将8位无符号整数数组的子集转换为其等效的,以64为基的数字编码的字符串形式.
}
catch (Exception e) {
encode = code;
}

最后解决方法:

将Base64编码的方法自己封装了一下,代码如下

package com.xb.web.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

public class Base64 {

    private Base64() {
    }

    /**
     * Table of the sixty-four characters that are used as the Base64 alphabet:
     * [A-Za-z0-9+/]
     */
    protected static final byte[] base64Chars = { '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',
            '@', '/', };

    /**
     * Reverse lookup table for the Base64 alphabet. reversebase64Chars[byte]
     * gives n for the nth Base64 character or -1 if a character is not a Base64
     * character.
     */
    protected static final byte[] reverseBase64Chars = new byte[0xff];
    static {
        // Fill in -1 for all characters to start with
        for (int i = 0; i < reverseBase64Chars.length; i++) {
            reverseBase64Chars[i] = -1;
        }
        // For characters that are base64Chars, adjust
        // the reverse lookup table.
        for (byte i = 0; i < base64Chars.length; i++) {
            reverseBase64Chars[base64Chars[i]] = i;
        }
    }

    /**
     * Encodes and decodes each of the arguments. Also check so see if encoding
     * then decoding each of the arguments returns the original argument.
     * 
     * @param args
     *            Command line arguments to encode/decode
     */
    private static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            String encoded = encode(args[i]);
            String decoded = decode(encoded);
            System.out.println(args[i] + ": " + encoded + " " + decode(args[i]));
            if (!decoded.equals(args[i])) {
                System.err.println("Encoding then decoding " + args[i] + " does not work. Decoded: '" + decoded + "'");
            }
        }
    }

    /**
     * Encode a String in Base64. The String is converted to and from bytes
     * according to the platform's default character encoding. No line breaks or
     * other white space are inserted into the encoded data.
     * 
     * @param string
     *            The data to encode.
     * @return An encoded String.
     */
    public static String encode(String string) {
        return new String(encode(string.getBytes()));
    }

    /**
     * Encode a String in Base64. No line breaks or other white space are
     * inserted into the encoded data.
     * 
     * @param string
     *            The data to encode.
     * @param enc
     *            Character encoding to use when converting to and from bytes.
     * @throws UnsupportedEncodingException
     *             if the character encoding specified is not supported.
     * @return An encoded String.
     */
    public static String encode(String string, String enc) throws UnsupportedEncodingException {
        return new String(encode(string.getBytes(enc)), enc);
    }

    /**
     * Encode bytes in Base64. No line breaks or other white space are inserted
     * into the encoded data.
     * 
     * @param bytes
     *            The data to encode.
     * @return Encoded bytes.
     */
    public static byte[] encode(byte[] bytes) {
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        // calculate the length of the resulting output.
        // in general it will be 4/3 the size of the input
        // but the input length must be divisible by three.
        // If it isn't the next largest size that is divisible
        // by three is used.
        int mod;
        int length = bytes.length;
        if ((mod = length % 3) != 0) {
            length += 3 - mod;
        }
        length = length * 4 / 3;
        ByteArrayOutputStream out = new ByteArrayOutputStream(length);
        try {
            encode(in, out, false);
        } catch (IOException x) {
            // This can't happen.
            // The input and output streams were constructed
            // on memory structures that don't actually use IO.
        }
        return out.toByteArray();
    }

    /**
     * Encode data from the InputStream to the OutputStream in Base64.
     * 
     * @param in
     *            Stream from which to read data that needs to be encoded.
     * @param out
     *            Stream to which to write encoded data.
     * @param lineBreaks
     *            Whether to insert line breaks every 76 characters in the
     *            output.
     * @throws IOException
     *             if there is a problem reading or writing.
     */
    public static void encode(InputStream in, OutputStream out, boolean lineBreaks) throws IOException {
        // Base64 encoding converts three bytes of input to
        // four bytes of output
        int[] inBuffer = new int[3];
        int lineCount = 0;

        boolean done = false;
        while (!done && (inBuffer[0] = in.read()) != -1) {
            // Fill the buffer
            inBuffer[1] = in.read();
            inBuffer[2] = in.read();

            // Calculate the out Buffer
            // The first byte of our in buffer will always be valid
            // but we must check to make sure the other two bytes
            // are not -1 before using them.
            // The basic idea is that the three bytes get split into
            // four bytes along these lines:
            // [AAAAAABB] [BBBBCCCC] [CCDDDDDD]
            // [xxAAAAAA] [xxBBBBBB] [xxCCCCCC] [xxDDDDDD]
            // bytes are considered to be zero when absent.
            // the four bytes are then mapped to common ASCII symbols

            // A's: first six bits of first byte
            out.write(base64Chars[inBuffer[0] >> 2]);
            if (inBuffer[1] != -1) {
                // B's: last two bits of first byte, first four bits of second
                // byte
                out.write(base64Chars[((inBuffer[0] << 4) & 0x30) | (inBuffer[1] >> 4)]);
                if (inBuffer[2] != -1) {
                    // C's: last four bits of second byte, first two bits of
                    // third byte
                    out.write(base64Chars[((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6)]);
                    // D's: last six bits of third byte
                    out.write(base64Chars[inBuffer[2] & 0x3F]);
                } else {
                    // C's: last four bits of second byte
                    out.write(base64Chars[((inBuffer[1] << 2) & 0x3c)]);
                    // an equals sign for a character that is not a Base64
                    // character
                    out.write('=');
                    done = true;
                }
            } else {
                // B's: last two bits of first byte
                out.write(base64Chars[((inBuffer[0] << 4) & 0x30)]);
                // an equal signs for characters that is not a Base64 characters
                out.write('=');
                out.write('=');
                done = true;
            }
            lineCount += 4;
            if (lineBreaks && lineCount >= 76) {
                out.write('\n');
                lineCount = 0;
            }
        }
    }

    /**
     * Decode a Base64 encoded String. Characters that are not part of the
     * Base64 alphabet are ignored in the input. The String is converted to and
     * from bytes according to the platform's default character encoding.
     * 
     * @param string
     *            The data to decode.
     * @return A decoded String.
     */
    public static String decode(String string) {
        return new String(decode(string.getBytes()));
    }

    /**
     * Decode a Base64 encoded String. Characters that are not part of the
     * Base64 alphabet are ignored in the input.
     * 
     * @param string
     *            The data to decode.
     * @param enc
     *            Character encoding to use when converting to and from bytes.
     * @throws UnsupportedEncodingException
     *             if the character encoding specified is not supported.
     * @return A decoded String.
     */
    public static String decode(String string, String enc) throws UnsupportedEncodingException {
        return new String(decode(string.getBytes(enc)), enc);
    }

    /**
     * Decode Base64 encoded bytes. Characters that are not part of the Base64
     * alphabet are ignored in the input.
     * 
     * @param bytes
     *            The data to decode.
     * @return Decoded bytes.
     */
    public static byte[] decode(byte[] bytes) {
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        // calculate the length of the resulting output.
        // in general it will be at most 3/4 the size of the input
        // but the input length must be divisible by four.
        // If it isn't the next largest size that is divisible
        // by four is used.
        int mod;
        int length = bytes.length;
        if ((mod = length % 4) != 0) {
            length += 4 - mod;
        }
        length = length * 3 / 4;
        ByteArrayOutputStream out = new ByteArrayOutputStream(length);
        try {
            decode(in, out, false);
        } catch (IOException x) {
            // This can't happen.
            // The input and output streams were constructed
            // on memory structures that don't actually use IO.
        }
        return out.toByteArray();
    }

    /**
     * Reads the next (decoded) Base64 character from the input stream. Non
     * Base64 characters are skipped.
     * 
     * @param in
     *            Stream from which bytes are read.
     * @param throwExceptions
     *            Throw an exception if an unexpected character is encountered.
     * @return the next Base64 character from the stream or -1 if there are no
     *         more Base64 characters on the stream.
     * @throws IOException
     *             if an IO Error occurs or if an unexpected character is
     *             encountered.
     */
    private static final int readBase64(InputStream in, boolean throwExceptions) throws IOException {
        int read;
        do {
            read = in.read();
            if (read == -1)
                return -1;
            if (throwExceptions && reverseBase64Chars[(byte) read] == -1 && read != ' ' && read != '\n' && read != '\r' && read != '\t' && read != '\f' && read != '=') {
                throw new IOException("Unexpected Base64 character: " + read);
            }
            read = reverseBase64Chars[(byte) read];
        } while (read == -1);
        return read;
    }

    /**
     * Decode Base64 encoded data from the InputStream to the OutputStream.
     * Characters in the Base64 alphabet, white space and equals sign are
     * expected to be in urlencoded data. The presence of other characters could
     * be a sign that the data is corrupted.
     * 
     * @param in
     *            Stream from which to read data that needs to be decoded.
     * @param out
     *            Stream to which to write decoded data.
     * @param throwExceptions
     *            Whether to throw exceptions when unexpected data is
     *            encountered.
     * @throws IOException
     *             if an IO occurs or unexpected data is encountered.
     */
    public static void decode(InputStream in, OutputStream out, boolean throwExceptions) throws IOException {
        // Base64 decoding converts four bytes of input to three bytes of output
        int[] inBuffer = new int[4];

        // read bytes unmapping them from their ASCII encoding in the process
        // we must read at least two bytes to be able to output anything
        boolean done = false;
        while (!done && (inBuffer[0] = readBase64(in, throwExceptions)) != -1 && (inBuffer[1] = readBase64(in, throwExceptions)) != -1) {
            // Fill the buffer
            inBuffer[2] = readBase64(in, throwExceptions);
            inBuffer[3] = readBase64(in, throwExceptions);

            // Calculate the output
            // The first two bytes of our in buffer will always be valid
            // but we must check to make sure the other two bytes
            // are not -1 before using them.
            // The basic idea is that the four bytes will get reconstituted
            // into three bytes along these lines:
            // [xxAAAAAA] [xxBBBBBB] [xxCCCCCC] [xxDDDDDD]
            // [AAAAAABB] [BBBBCCCC] [CCDDDDDD]
            // bytes are considered to be zero when absent.

            // six A and two B
            out.write(inBuffer[0] << 2 | inBuffer[1] >> 4);
            if (inBuffer[2] != -1) {
                // four B and four C
                out.write(inBuffer[1] << 4 | inBuffer[2] >> 2);
                if (inBuffer[3] != -1) {
                    // two C and six D
                    out.write(inBuffer[2] << 6 | inBuffer[3]);
                } else {
                    done = true;
                }
            } else {
                done = true;
            }
        }
    }
}
View Code

代码貌似是老外写的,问题解决,原因待分析

推荐文章: Base64编码简介

               关于base64编码的原理及实现

 

posted on 2016-01-02 19:50  Venetian  阅读(299)  评论(0)    收藏  举报