zoukankan      html  css  js  c++  java
  • WUSTOJ 1324: Base64 Coding(Java)未解决,求题解

    题目链接:1324: Base64 Coding
    资料:ASCII码表
    原文是英文,而且篇幅较长。因此下面不粘贴原文,只写中文大意。

    Description

    Base64是一种编码算法。它的工作原理是将 ASCII 码在 0x00 和 0xFF 之间的字符转换成只有小写字母、大写字母和数字组成的字符串,从而避免了编码的歧义问题。

    让我们看一个简单的例子。

    转换前:10101101 10111010 01110110
    转换后:00101011 00011011 00101001 00110110

    它们在转换后的十进制的值分别为 43、27、41 和 54,对应的字符分别为 “r”、“b”、“p” 和 “2”。查看对照表。所以我们说 24 位二进制字符串的 Base64 编码是 ‘rbp2’ 。解码算法是简单地删除每个字节的两个前缀 0 ,然后将它们连接在一起。

    但是,如果原始文本的字节数不是 3 的倍数,应该怎么办?解决方案是我们将添加冗余的 0 ,Base64 编码将使用 ‘=’ 来表示这些 0 。这就是为什么有些 Base64 编码的字符串以一两个 ‘=’ 结尾。

    如果结果字符串太长,每行放置76个字符。

    想想托马斯霍布斯(Thomas Hobbes)的《利维坦》(Leviathan)中的那句名言吧。
    人之所以与众不同,不仅因为他的理性,还因为他与其他动物的这种独特的激情,那就是一种精神上的欲望,因为他对持续不断的、不知疲倦的知识的创造所表现出来的喜悦的毅力,超过了任何肉体上短暂的强烈的快乐。

    Base64 编码后,如下所示。
    TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
    IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
    dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
    dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
    ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=

    现在,您要对消息进行编码或解码。

    Input

    有多个测试用例。测试用例以 “#exit#” 结束,不应该处理它。

    每个测试用例都以包含 “#b2s#” 或 “#s2b#” 的行开始,表示要对输入字符串执行解码或编码操作。每个测试用例都以 “#CaseEnd#” 结束。中间的字符串是要处理的字符。字符串的长度小于106

    Output

    在单行中打印 “Case #id”,其中 “id” 是从 1 开始编号的用例号,然后输出结果字符串。

    Sample Input

    #s2b#
    C^$AL6N20)QQ[IKSF;',^9D>-<&W'>S2-(#[+F?#:
    #CaseEnd#
    #b2s#
    NVA6PV4xRU5XQSJSPD0nVzRFRlYhPSE4WQ==
    #CaseEnd#
    #exit#
    

    Sample Output

    Case #1
    Q14kQUw2TjIwKVFRW0lLU0Y7XCcsXjlEPi08JlcnPlMyLSgjWytGPyM6
    Case #2
    5P:=^1ENWA"R<='W4EFV!=!8Y
    

    HINT

    在 “#b2s#” 或 “#s2b#” 之后和 “#CaseEnd#” 之前的换行字符不需要处理。其他字符则被视为普通字符。

    Base64 编码表:

    十进制 字符 十进制 字符 十进制 字符
    0 A 26 a 52 0
    1 B 27 b 53 1
    2 C 28 c 54 2
    3 D 29 d 55 3
    4 E 30 e 56 4
    5 F 31 f 57 5
    6 G 32 g 58 6
    7 H 33 h 59 7
    8 I 34 i 60 8
    9 J 35 j 61 9
    10 K 36 k 62 +
    11 L 37 l 63 /
    12 M 38 m
    13 N 39 n
    14 O 40 o
    15 P 41 p
    16 Q 42 q
    17 R 43 r
    18 S 44 s
    19 T 45 t
    20 U 46 u
    21 V 47 v
    22 W 48 w
    23 X 49 x
    24 Y 50 y
    25 Z 51 z

    分析

    import java.util.Base64这个类,OJ目前不支持,所以不能用API,只能自己写。

    代码

    /**
     * Time ms
     * @author wowpH
     * @version 4.0
     * @date 2019年6月28日上午8:48:29
     * Environment:	Windows 10
     * IDE Version:	Eclipse 2019-3
     * JDK Version:	JDK1.8.0_112
     */
    
    import java.io.InputStreamReader;
    import java.util.Scanner;
    
    public class Main {
    	private final char[] BASE64_TABLE = { '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', '+', '/' };
    	private Scanner sc = new Scanner(new InputStreamReader(System.in));
    
    	public Main() {
    		int caseNum = 1;// 用例号
    		while (sc.hasNext()) {
    			String operation = sc.nextLine();// 三种操作,编码,解码,退出
    			if (operation.contentEquals("#s2b#")) { // 编码
    				String message = input(); // 获取要编码的文本
    				output(code(message), caseNum); // 编码后输出
    			} else if (operation.contentEquals("#b2s#")) {// 解码
    				String message = input(); // 获取要解码的文本
    				output(decode(message), caseNum); // 解码后输出
    			} else if (operation.contentEquals("#exit#")) {// 退出
    				break;
    			}
    			++caseNum;
    		}
    		sc.close();
    	}
    
    	private String input() {// 获得需要转换的信息字符串
    		StringBuffer sb = new StringBuffer();
    		String temp = sc.nextLine();
    		while (false == temp.contentEquals("#CaseEnd#")) {
    			sb.append(temp);
    			temp = sc.nextLine();
    		}
    		return sb.toString();
    	}
    
    	private String code(String message) {// 编码
    		char[] messArr = message.toCharArray();// 字符串转成字符数组
    		StringBuffer binarySB = new StringBuffer(messArr.length * 8);// 存储二进制字符串
    		for (int i = 0; i < messArr.length; ++i) {
    			String oneByte = Integer.toBinaryString(messArr[i]);// 字符转成二进制字符串
    			for (int j = 8 - oneByte.length(); j > 0; --j) {
    				binarySB.append('0');// 不足8位,前面补'0'
    			}
    			binarySB.append(oneByte);
    		}
    
    		// 原始文本不是3的倍数,即二进制串长度不是6的倍数,末尾添加冗余的'0'
    		int remainder = binarySB.length() / 8 % 3;
    		if (1 == remainder) {
    			binarySB.append("0000");
    		} else if (2 == remainder) {
    			binarySB.append("00");
    		}
    
    		int length = binarySB.length();
    		StringBuffer ans = new StringBuffer(length / 6);// 存储转换后的字符串
    		for (int i = 0; i < length; i += 6) {
    			String indexStr = binarySB.substring(i, i + 6);// 获取6位二进制串
    			int index = Integer.parseInt(indexStr, 2);// 解析成10进制数
    			ans.append(BASE64_TABLE[index]);// 查找对照表,添加对应字符
    		}
    
    		// 末尾添加'='
    		if (1 == remainder) {
    			ans.append("==");
    		} else if (2 == remainder) {
    			ans.append("=");
    		}
    		return ans.toString();// 返回编码后的字符串
    	}
    
    	private String decode(String message) {// 解码
    		char[] messArr = message.toCharArray();// 字符串转成字符数组
    		StringBuffer binarySB = new StringBuffer(messArr.length * 6);// 存储二进制串
    		for (int i = 0; i < messArr.length; ++i) {
    			int index = parse(messArr[i]);// 获取字符的Base64编码的十进制值
    			String oneByte = Integer.toBinaryString(index);// 转成二进制串
    			for (int j = 6 - oneByte.length(); j > 0; --j) {
    				binarySB.append('0');// 不足6位,前面补'0'
    			}
    			binarySB.append(oneByte);
    		}
    
    		int length = binarySB.length();
    		StringBuffer ans = new StringBuffer(length / 8);// 存储解码后的字符串
    		for (int i = 0; i < length; i += 8) {
    			String str = binarySB.substring(i, i + 8);// 获取8位二进制串
    			int number = Integer.parseInt(str, 2);// 解析成十进制数,也就是ASCII码值
    			ans.append((char) number);// 转成字符
    		}
    
    		if ('=' == messArr[messArr.length - 1]) {
    			if ('=' == messArr[messArr.length - 2]) {
    				return ans.substring(0, ans.length() - 2);
    			}
    			return ans.substring(0, ans.length() - 1);
    		}
    		return ans.toString();// 返回解码后的字符串
    	}
    
    	private int parse(char ch) {// 获取字符的Base64码值,十进制
    		int index = 64;// 默认越界
    		if ('+' == ch) {
    			index = 62;
    		} else if ('/' == ch) {
    			index = 63;
    		} else if ('=' == ch) {
    			index = 0;
    		} else if (ch >= 'A' && ch <= 'Z') {
    			index = ch - 'A' + 0;
    		} else if (ch >= 'a' && ch <= 'z') {
    			index = ch - 'a' + 26;
    		} else if (ch >= '0' && ch <= '9') {
    			index = ch - '0' + 52;
    		}
    		return index;
    	}
    
    	private void output(String string, int caseNum) {// 输出用例caseNum的结果string
    		System.out.println("Case #" + caseNum);
    		int quotients = string.length() / 76;// 每行最多76个字符
    		for (int i = 0; i < quotients; ++i) {
    			System.out.println(string.substring(i * 76, i * 76 + 76));
    		}
    		System.out.println(string.substring(quotients * 76));
    	}
    
    	public static void main(String[] args) {
    		new Main();
    	}
    }
    

    版权声明

    1. 转载、参考、引用必须在首页添加如下文字:
      [WUSTOJ 1324: Base64 Coding(Java)未解决,欢迎大家讨论——wowpH](https://blog.csdn.net/pfdvnah/article/details/93536467)
    2. 代码原创,公开引用不能删除首行注释(作者,版本号,时间等信息);
    3. 如果有疑问欢迎评论区留言,尽量解答;
    4. 如果有错误,还望大侠评论区指正。

  • 相关阅读:
    获取多个checkbox的选中值
    谷歌57版本设置浏览器编码
    MySQL Date 函数
    easyui combobox下拉列表的多选值
    Maven_3 如何从Maven远程存储库下载
    Maven_2 本地资源库 中央存储库
    Maven_1 安装配置
    com.netflix.client.ClientException: Load balancer does not have available server for client xxxx
    spring cloud Eureka server 问题 Spring Cloud java.lang.TypeNotPresentException
    DotNet 资源大全中文版(Awesome最新版)
  • 原文地址:https://www.cnblogs.com/wowpH/p/11687481.html
Copyright © 2011-2022 走看看