1. Visão geral
1.O que é Base64:
Base64 é um dos métodos de codificação mais comuns para transmissão de códigos de bytes de 8 bits na Internet. Você pode verificar RFC2045 ~ RFC2049, que possui especificações detalhadas para MIME. A codificação Base64 pode ser usada para transmitir informações de identificação mais longas em um ambiente HTTP. Por exemplo, no sistema Java Persistence Hibernate, Base64 é usado para codificar um identificador exclusivo longo (geralmente um UUID de 128 bits) em uma string, que é usada como parâmetro em formulários HTTP e URLs HTTP GET. Em outras aplicações, muitas vezes é necessário codificar dados binários em um formato adequado para colocação em uma URL (incluindo campos de formulário ocultos). Neste momento, o uso da codificação Base64 não é apenas mais curto, mas também ilegível, ou seja, os dados codificados não serão diretamente visíveis a olho nu.
2. Introdução:
O Base64 padrão não é adequado para transmissão diretamente na URL, porque o codificador de URL alterará os caracteres "/" e "+" no Base64 padrão para a forma de "%XX", e esses caracteres "%" existem ao entrar no banco de dados , será necessária uma conversão adicional porque o sinal "%" foi usado como caractere curinga no SQL ANSI.
Para resolver este problema, uma codificação Base64 aprimorada para URLs pode ser usada, que não preenche o sinal '=' no final e altera o "+" e "/" no Base64 padrão para "*" e "-" respectivamente. , Isso elimina a necessidade de conversão durante a codificação de URL, decodificação e armazenamento de banco de dados, evita o aumento no comprimento das informações codificadas no processo e unifica o formato dos identificadores de objetos em bancos de dados, formulários, etc.
Há também uma variante Base64 aprimorada para expressões regulares, que altera "+" e "/" para "!" e "-" porque "+", "*" e " Ambos [" e "]" podem ter significados especiais em expressões regulares.
Existem também variantes que mudam "+/" para "_-" ou "._" (usado como nomes identificadores em linguagens de programação) ou ".-" (usado para Nmtokens em XML) ou ainda "_ :" (para Nome em XML).
Base64 requer a conversão de cada três bytes de 8 bits em quatro bytes de 6 bits (3 * 8 = 4 * 6 = 24) e, em seguida, a adição de dois 0s de bits altos ao 6 bits para formar quatro bytes de 8 bits, ou seja, a string convertida será teoricamente 1/3 mais longo que o original.
3. Regras:
Regras sobre esta codificação:
①.Converta 3 caracteres em 4 caracteres.
②.Adicione um caractere de nova linha a cada 76 caracteres.
③.O terminador final também deve ser processado.
Isso não é muito abstrato? Não se preocupe, vejamos um exemplo:
Antes da conversão: aaaaaabb ccccdddd eeffffff
Após a conversão: 00aaaaaa 00bbcccc 00ddddee 00ffffff
Deveria ficar claro, certo? Os três bytes superiores são o texto original e os quatro bytes inferiores são a codificação Base64 convertida, sendo os dois primeiros bits 0.
Após a conversão, usamos uma tabela de códigos para obter a string desejada (ou seja, a codificação Base64 final)
2. Exemplo de código de implementação Java:
classe final pública Base64 { static final privado int BASELENGTH = 255; final estático privado int SEXTEENBIT = 16; = 6 final privado estático int FOURBYTE = 4; int SIGN = -128; char final privado estático PAD = '='; char final privado estático fDebug = false; byte privado final estático [] base64Alphabet = novo byte [BASELENGTH]; ]; estático { for (int i = 0; i < COMPRIMENTO BASE; i++) { base64Alphabet[i] = -1 } para (int i = 'Z'; i >= 'A'; i--) { base64Alphabet[i] = (byte) (i - 'A' }); i = 'z'; i >= 'a'; >= '0'; i--) { base64Alfabeto[i] = (byte) (i - '0' + 52); int i = 0; i <= 25; lookUpBase64Alphabet[i] = (char) ('A' + i); 26, j = 0; i <= 51; ) lookUpBase64Alphabet[i] = (char) ('0' + j); lookUpBase64Alphabet[62] = (char) '+'; lookUpBase64Alphabet[63] = (char) '/' } protegido estático booleano isWhiteSpace(char octect) { return (occtect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9 } protegido); booleano estático isPad (char octect) { return (occtect == PAD); } protegido estático booleano isData(char octect) { return (base64Alphabet[occtect] != -1); protegido estático booleano isBase64(char octect) { return (isWhiteSpace(occtect) || isPad(occtect) || isData(occtect) ); } /** * Codifica octetos hexadecimais em Base64 * * @param binaryData * Array contendo binárioData * @return Matriz Base64 codificada */ public static String encode(byte[] binaryData) { if (binaryData == null) return null; int lengthDataBits = binaryData.length * EIGHTBIT; ; } int lessThan24bits = lengthDataBits % TWENTYFOURBITGROUP; VINTEQUATROBITGROUP; int númeroQuarteto = menos de 24 bits! = 0? númeroTriplets + 1: númeroTriplets = (númeroQuarteto - 1) / 19 + 1; = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; 0; linha < númeroLinhas - 1; linha++) { for (int quarteto = 0; quarteto < 19; quarteto++) { b1 = dadosbinários[dadosIndex++]; b2 = dadosbinários[dadosIndex++]; b3 = dadosbinários[dadosIndex++]; + b3); } l = (byte) (b2 & 0x0f = (byte) (b1 & 0x03); ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte) (b2 >> 4): (byte) ((b2) >> 4 ^ 0xf0 byte val3 = ((b3 & SIGN) ==); 0) ? (byte) (b3 >> 6): (byte) ((b3) >> 6 ^ 0xfc); println("k4 = " + (k << 4)); System.out.println("vak = " + (val2 | (k << 4))); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; lookUpBase64Alphabet[b3 & 0x3f]; i++; } encodedData[encodedIndex++] = 0xa; (fDebug) { System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3); = 0) ? (byte) (b1 >> 2): (byte) ((b1) >> 2 ^ 0xc0); ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte) (b3 >> 6): (byte) ((b3) >> 6 ^ 0xfc); System.out.println("val2 = " + val2); System.out.println("k4 = " + (k << 4)); System.out.println("vak = " + (val2 | (k << 4)); < 4))); } encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; grupos de bits se (menos que 24 bits == OITO BITS) { b1 = dadosbinários[dataIndex]; k = (byte) (b1 & 0x03); if (fDebug) { System.out.println("b1=" + b1); " + (b1 >> 2)); } byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); encodedData[encodedIndex++] = encodedData[encodedIndex++] = encodedData[encodedIndex++] = PAD; if (menos que 24 bits == SEISTENBIT) { b1 = dados binários[dataIndex]; b2 = dados binários[dataIndex + 1]; == 0) ? (byte) (b1 >> 2): (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4): (byte) ((b2) >> 4 ^ 0xf0); ; encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex++] = PAD; * @param binaryData * Matriz de bytes contendo dados Base64 * @return Matriz contendoind dados decodificados. */ public static byte[] decode(String encoded) { if (encoded == null) return null; base64Data = encoded.toCharArray(); ); if (len % FOURBYTE != 0) { return null;// deve ser divisível por quatro } int numberQuadruple = (len / FOURBYTE); if (númeroQuadruple == 0) retornar novo byte[0]; byte decodificado[] = null; d1 = 0, d2 = 0, d3 = 0, d4 = 0 int i = 0; = 0; int dataIndex = 0; decodedData = new byte[(numberQuadruple) * 3]; for (; i < numberQuadruple - 1; i++) { if (!isData((d1 = base64Data[dataIndex++])) || !isData ((d2 = base64Data[dataIndex++])) || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) return null;// se for encontrado "nenhum dado" apenas retorne null b1 = base64Alphabet[d1]; = base64Alfabeto[d3]; b4 = base64Alfabeto[d4]; = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); encodedIndex++] = (byte) (b3 << 6 | b4 } if (!isData((d1 =); base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) { return null;// se for encontrado "nenhum dado" apenas retorne null } b1 = base64Alphabet[d1]; ;d3 = base64Data[dataIndex++]; d4 = base64Data[dataIndex++]; (!isData((d3)) || !isData((d4))) {// Verifique se eles são caracteres PAD if (isPad(d3) && isPad(d4)) { // Dois PAD, por exemplo, 3c[Pad][ Pad] if ((b2 & 0xf) != 0)// últimos 4 bits devem ser zero return byte[] tmp = new byte[i * 3 +; 1]; System.arraycopy(decodedData, 0, tmp, 0, i * 3); tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); d3) && isPad(d4)) { // Um PAD, por exemplo, 3cQ[Pad] b3 = base64Alphabet[d3]; if ((b3 & 0x3) != 0)// últimos 2 bits devem ser zero return null; tmp, 0, i * 3); tmp[índice codificado++] = (byte) (b1 << 2 | b2 >> 4); tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 3c[Pad]r", "3cdX", "3cXd", "3cXX" // onde X não é dado } } else { // Sem PAD, por exemplo 3cQl b3 = base64Alphabet[d3]; b4 = base64Alphabet[d4]; << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); return decodedData } /** * remove WhiteSpace do MIME contendo dados Base64 codificados. ) * @return o novo comprimento */ protected static int removeWhiteSpace(char[] data) { if (data == null) return 0; espaço em branco int newSize = 0; int len = data.length; for (int i = 0; i < len; i++) { if (!isWhiteSpace(data[i])) data[newSize++] = data[i]; } return newSize; } public static void main(String[] args) { System.out.println(encode("República Popular da China".getBytes()));