1. Descripción general
1. ¿Qué es Base64?
Base64 es uno de los métodos de codificación más comunes para transmitir códigos de bytes de 8 bits en Internet. Puede consultar RFC2045~RFC2049, que tiene especificaciones detalladas para MIME. La codificación Base64 se puede utilizar para pasar información de identificación más larga en un entorno HTTP. Por ejemplo, en el sistema Hibernate de Java Persistence, Base64 se usa para codificar un identificador único largo (generalmente un UUID de 128 bits) en una cadena, que se usa como parámetros en formularios HTTP y URL GET HTTP. En otras aplicaciones, a menudo es necesario codificar datos binarios en un formato adecuado para colocarlos en una URL (incluidos los campos de formulario ocultos). En este momento, el uso de la codificación Base64 no solo es más corto, sino también ilegible, es decir, los datos codificados no serán directamente visibles a simple vista.
2. Introducción:
El Base64 estándar no es adecuado para la transmisión directamente en la URL, porque el codificador de URL cambiará los caracteres "/" y "+" en el Base64 estándar al formato "%XX", y estos caracteres "%" existen al ingresar a la base de datos. , se requiere una conversión adicional porque el signo "%" se ha utilizado como carácter comodín en ANSI SQL.
Para resolver este problema, se puede utilizar una codificación Base64 mejorada para URL, que no rellena el signo '=' al final y cambia "+" y "/" en Base64 estándar a "*" y "-" respectivamente. Esto elimina la necesidad de conversión durante la codificación, decodificación y almacenamiento de bases de datos de URL, evita el aumento en la longitud de la información codificada en el proceso y unifica el formato de los identificadores de objetos en bases de datos, formularios, etc.
También hay una variante Base64 mejorada para expresiones regulares, que cambia "+" y "/" por "!" y "-" porque "+", "*" y " Ambos [" y "]" pueden tener significados especiales en expresiones regulares.
También hay variantes que cambian "+/" a "_-" o "._" (usados como nombres de identificadores en lenguajes de programación) o ".-" (usados para Nmtokens en XML) o incluso "_ :" (para Nombre en XML).
Base64 requiere convertir cada tres bytes de 8 bits en cuatro bytes de 6 bits (3 * 8 = 4 * 6 = 24) y luego agregar dos 0 de bits altos a los 6 bits para formar cuatro bytes de 8 bits, es decir, la cadena convertida teóricamente será 1/3 más largo que el original.
3. Reglas:
Reglas sobre esta codificación:
①.Convierte 3 caracteres en 4 caracteres.
②.Agregue un carácter de nueva línea cada 76 caracteres.
③.El terminador final también debe procesarse.
¿No es eso demasiado abstracto? No te preocupes, veamos un ejemplo:
Antes de la conversión: aaaaaabb ccccdddd eeffffff
Después de la conversión: 00aaaaaa 00bbcccc 00ddddee 00ffffff
Debería quedar claro, ¿verdad? Los tres bytes superiores son el texto original y los cuatro bytes inferiores son la codificación Base64 convertida, siendo los dos primeros bits 0.
Después de la conversión, usamos una tabla de códigos para obtener la cadena que queremos (es decir, la codificación Base64 final)
2. Ejemplo de código de implementación de Java:
clase final pública Base64 { int final privado estático BASELENGTH = 255; int final privado estático LOOKUPLENGTH = 64; int final privado estático SIXTEENBIT = 16; = 6; final privado estático int FOURBYTE = 4; int SIGN = -128; carácter final privado estático PAD = '='; carácter privado final estático fDebug = false; byte privado final estático [] base64Alphabet = nuevo byte [BASELENGTH]; ]; estático { para (int i = 0; i < LONGITUD DE BASE; i++) { base64Alphabet[i] = -1; } for (int i = 'Z'; i >= 'A'; i--) { base64Alphabet[i] = (byte) (i - 'A'); i = 'z'; i >= 'a'; i--) { base64Alphabet[i] = (byte) (i - 'a' + 26); >= '0'; i--) { base64Alphabet[i] = (byte) (i - '0' + 52 } base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; int i = 0; i <= 25; i++) lookUpBase64Alphabet[i] = (char) ('A' + i); 26, j = 0; i <= 51; i++, j++) lookUpBase64Alphabet[i] = (char) ('a' + j) para (int i = 52, j = 0; i <= 61; i++, j++); ) lookUpBase64Alphabet[i] = (char) ('0' + j); lookUpBase64Alphabet[62] = (char) '+'; lookUpBase64Alphabet[63] = (char) '/'; } booleano estático protegido isWhiteSpace(char octect) { return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); isPad booleano estático (char octect) { return (octect == PAD); } isData booleano estático protegido (char octect) { return (base64Alphabet[octect]! = -1); } isBase64 booleano estático protegido (char octect) { return (isWhiteSpace(octect) || isPad(octect) || isData(octect) ); } /** * Codifica octectos hexadecimales en Base64 * * @param binarioData * Matriz que contiene binarioData * @return Matriz Base64 codificada */ codificación de cadena estática pública (byte[] binarioData) { if (binaryData == null) return null; int lengthDataBits = binarioData.length * EIGHTBIT; } int lessThan24bits = lengthDataBits % TWENTYFOURBITGROUP int numberTriplets = lengthDataBits /; TWENTYFOURBITGROUP; int numberQuartet = lessThan24bits! = 0? numberTriplets + 1: numberTriplets; int numberQuartet - 1) / 19 + 1; char codificadoDatos = nulo; = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int codificadoIndex = 0; int dataIndex = 0; int i = 0; if (fDebug) { System.out.println("número de trillizos = " + númeroTripletes); 0; línea < número de líneas - 1; línea++) { for (int cuarteto = 0; cuarteto < 19; cuarteto++) { b1 = datos binarios[índice de datos++]; b2 = datos binarios[índice de datos++]; b3 = datos binarios[índice de datos++]; if (fDebug) { System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3); } l = (byte) (b2 y 0x0f); k = (byte) (b1 y 0x03; byte val1); ((b1 y SIGNO) == 0) ? (byte) (b1 >> 2): (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 y SIGNO) == 0) ? byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6): (byte) ((b3) >> 6 ^ 0xfc); if (fDebug) { System.out.println("val2 = " + val2); println("k4 = " + (k << 4)); System.out.println("vak = " + (val2 | (k << 4))); datos codificados[índice codificado++] = lookUpBase64Alphabet[val1]; datos codificados[índice codificado++] = lookUpBase64Alphabet[val2 | (k << 4)]; datos codificados[índice codificado++] = lookUpBase64Alphabet[b3 & 0x3f]; i++; } datos codificados[índice de datos++] = 0xa; (fDebug) { System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3); } l = (byte) (b2 & 0x0f); k = (byte) (b1 & 0x03 byte val1 = ((b1 & SIGN) = = 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0 byte val2); ((b2 y SIGNO) == 0) ? (byte) (b2 >> 4): (byte) ((b2) >> 4 ^ 0xf0); byte val3 = ((b3 y SIGNO) == 0) ? 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))); } datos codificados[índice codificado++] = lookUpBase64Alphabet[val1]; lookUpBase64Alphabet[val2 | (k << 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) } // forma el número entero de 6-; grupos de bits si (menos de 24 bits == OCHO BITS) { b1 = datos binarios[índice de datos]; k = (byte) (b1 y 0x03); si (fDebug) { System.out.println("b1=" + b1) " + (b1 >> 2)); } byte val1 = ((b1 & SIGN) == 0)? (byte) (b1 >> 2): (byte) ((b1) >> 2 ^ 0xc0); datos codificados [índice codificado ++] = datos codificados [índice codificado ++] = datos codificados [índice codificado ++] = PAD; si (menos de 24 bits == SEISBIT) { b1 = datos binarios[índice de datos]; b2 = datos binarios[índice de datos + 1]; l = (byte) (b2 y 0x0f); k = (byte) (b1 y 0x03; byte val1); == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); byte val2 = ((b2 y SIGN) == 0) ? (byte) (b2 >> 4): (byte) ((b2) >> 4 ^ 0xf0); datos codificados[índice codificado++] = lookUpBase64Alphabet[val1] ; datos codificados[índice codificado++] = lookUpBase64Alphabet[val2 | 4)]; encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex++] = PAD; encodedData[encodedIndex] = 0xa return new String(encodedData) * @param binarioData * Matriz de bytes que contiene datos Base64 * @return Matriz que contiene datos decodificados. */ byte estático público[] decode(Cadena codificada) { if (codificado == nulo) return null; char[] base64Data = encoded.toCharArray() // eliminar espacios en blanco int len = removeWhiteSpace(base64Data) ); if (len % FOURBYTE != 0) { return null;// debe ser divisible por cuatro } int numberQuadruple = (len / FOURBYTE); si (númeroCuádruple == 0) devuelve nuevo byte[0]; byte decodedData[] = nulo; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marcador0 = 0, marcador1 = 0; d1 = 0, d2 = 0, d3 = 0, d4 = 0; int i = 0; = 0; int dataIndex = 0; decodedData = nuevo byte[(númeroCuádruple) * 3]; para (; i < númeroCuádruple - 1; i++) { if (!isData((d1 = base64Data[dataIndex++])) || !isData ((d2 = base64Data[dataIndex++])) || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) return null;// si no se encuentran datos, simplemente devuelva null b1 = base64Alphabet[d1]; = Alfabeto base64[d3]; b4 = Alfabeto base64[d4]; = (byte) (b1 << 2 | b2 >> 4); datos decodificados[índice codificado++] = (byte) (((b2 y 0xf) << 4) | ((b3 >> 2) y 0xf)); codificadoIndex++] = (byte) (b3 << 6 | b4 } if (!isData((d1 =); base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) { return null;// si no se encuentran datos, simplemente devuelve null } b1 = base64Alphabet[d1]; ; d3 = base64Data[dataIndex++]; d4 = base64Data[dataIndex++]; (!isData((d3)) || !isData((d4))) {// Compruebe si son caracteres PAD if (isPad(d3) && isPad(d4)) { // Dos PAD, por ejemplo, 3c[Pad][ Pad] if ((b2 & 0xf) != 0)// los últimos 4 bits deben ser cero return byte nulo[] tmp = nuevo byte[i * 3 +; 1]; System.arraycopy(decodedData, 0, tmp, 0, i * 3); tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); d3) && isPad(d4)) { // Un PAD, por ejemplo, 3cQ[Pad] b3 = base64Alphabet[d3]; if ((b3 & 0x3) != 0)// los últimos 2 bits deben ser cero return null; byte[] tmp = new byte[i * 3 + 2]; tmp, 0, i * 3); tmp[índice codificado++] = (byte) (b1 << 2 | b2 >> 4); tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); return tmp; 3c[Pad]r", "3cdX", "3cXd", "3cXX" // donde X no son datos } } else { // Sin PAD, por ejemplo 3cQl b3 = base64Alphabet[d3]; b4 = base64Alphabet[d4]; decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); } return decodedData; } /** * elimina WhiteSpace de MIME que contiene datos Base64 codificados * * @param datos * la matriz de bytes de datos base64 (con WS). ) * @return the new length */ protected static int removeWhiteSpace(char[] data) { if (data == null) return 0 // cuenta los caracteres que no son; espacio en blanco 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 de China".getBytes()));