题目链接: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

  1. #s2b#
  2. C^$AL6N20)QQ[IKSF;\',^9D>-<&W'>S2-(#[+F?#:
  3. #CaseEnd#
  4. #b2s#
  5. NVA6PV4xRU5XQSJSPD0nVzRFRlYhPSE4WQ==
  6. #CaseEnd#
  7. #exit#

Sample Output

  1. Case #1
  2. Q14kQUw2TjIwKVFRW0lLU0Y7XCcsXjlEPi08JlcnPlMyLSgjWytGPyM6
  3. Case #2
  4. 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,只能自己写。

代码

  1. /**
  2. * Time ms
  3. * @author wowpH
  4. * @version 4.0
  5. * @date 2019年6月28日上午8:48:29
  6. * Environment: Windows 10
  7. * IDE Version: Eclipse 2019-3
  8. * JDK Version: JDK1.8.0_112
  9. */
  10. import java.io.InputStreamReader;
  11. import java.util.Scanner;
  12. public class Main {
  13. private final char[] BASE64_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
  14. 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
  15. 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  16. 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  17. 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
  18. '7', '8', '9', '+', '/' };
  19. private Scanner sc = new Scanner(new InputStreamReader(System.in));
  20. public Main() {
  21. int caseNum = 1;// 用例号
  22. while (sc.hasNext()) {
  23. String operation = sc.nextLine();// 三种操作,编码,解码,退出
  24. if (operation.contentEquals("#s2b#")) { // 编码
  25. String message = input(); // 获取要编码的文本
  26. output(code(message), caseNum); // 编码后输出
  27. } else if (operation.contentEquals("#b2s#")) {// 解码
  28. String message = input(); // 获取要解码的文本
  29. output(decode(message), caseNum); // 解码后输出
  30. } else if (operation.contentEquals("#exit#")) {// 退出
  31. break;
  32. }
  33. ++caseNum;
  34. }
  35. sc.close();
  36. }
  37. private String input() {// 获得需要转换的信息字符串
  38. StringBuffer sb = new StringBuffer();
  39. String temp = sc.nextLine();
  40. while (false == temp.contentEquals("#CaseEnd#")) {
  41. sb.append(temp);
  42. temp = sc.nextLine();
  43. }
  44. return sb.toString();
  45. }
  46. private String code(String message) {// 编码
  47. char[] messArr = message.toCharArray();// 字符串转成字符数组
  48. StringBuffer binarySB = new StringBuffer(messArr.length * 8);// 存储二进制字符串
  49. for (int i = 0; i < messArr.length; ++i) {
  50. String oneByte = Integer.toBinaryString(messArr[i]);// 字符转成二进制字符串
  51. for (int j = 8 - oneByte.length(); j > 0; --j) {
  52. binarySB.append('0');// 不足8位,前面补'0'
  53. }
  54. binarySB.append(oneByte);
  55. }
  56. // 原始文本不是3的倍数,即二进制串长度不是6的倍数,末尾添加冗余的'0'
  57. int remainder = binarySB.length() / 8 % 3;
  58. if (1 == remainder) {
  59. binarySB.append("0000");
  60. } else if (2 == remainder) {
  61. binarySB.append("00");
  62. }
  63. int length = binarySB.length();
  64. StringBuffer ans = new StringBuffer(length / 6);// 存储转换后的字符串
  65. for (int i = 0; i < length; i += 6) {
  66. String indexStr = binarySB.substring(i, i + 6);// 获取6位二进制串
  67. int index = Integer.parseInt(indexStr, 2);// 解析成10进制数
  68. ans.append(BASE64_TABLE[index]);// 查找对照表,添加对应字符
  69. }
  70. // 末尾添加'='
  71. if (1 == remainder) {
  72. ans.append("==");
  73. } else if (2 == remainder) {
  74. ans.append("=");
  75. }
  76. return ans.toString();// 返回编码后的字符串
  77. }
  78. private String decode(String message) {// 解码
  79. char[] messArr = message.toCharArray();// 字符串转成字符数组
  80. StringBuffer binarySB = new StringBuffer(messArr.length * 6);// 存储二进制串
  81. for (int i = 0; i < messArr.length; ++i) {
  82. int index = parse(messArr[i]);// 获取字符的Base64编码的十进制值
  83. String oneByte = Integer.toBinaryString(index);// 转成二进制串
  84. for (int j = 6 - oneByte.length(); j > 0; --j) {
  85. binarySB.append('0');// 不足6位,前面补'0'
  86. }
  87. binarySB.append(oneByte);
  88. }
  89. int length = binarySB.length();
  90. StringBuffer ans = new StringBuffer(length / 8);// 存储解码后的字符串
  91. for (int i = 0; i < length; i += 8) {
  92. String str = binarySB.substring(i, i + 8);// 获取8位二进制串
  93. int number = Integer.parseInt(str, 2);// 解析成十进制数,也就是ASCII码值
  94. ans.append((char) number);// 转成字符
  95. }
  96. if ('=' == messArr[messArr.length - 1]) {
  97. if ('=' == messArr[messArr.length - 2]) {
  98. return ans.substring(0, ans.length() - 2);
  99. }
  100. return ans.substring(0, ans.length() - 1);
  101. }
  102. return ans.toString();// 返回解码后的字符串
  103. }
  104. private int parse(char ch) {// 获取字符的Base64码值,十进制
  105. int index = 64;// 默认越界
  106. if ('+' == ch) {
  107. index = 62;
  108. } else if ('/' == ch) {
  109. index = 63;
  110. } else if ('=' == ch) {
  111. index = 0;
  112. } else if (ch >= 'A' && ch <= 'Z') {
  113. index = ch - 'A' + 0;
  114. } else if (ch >= 'a' && ch <= 'z') {
  115. index = ch - 'a' + 26;
  116. } else if (ch >= '0' && ch <= '9') {
  117. index = ch - '0' + 52;
  118. }
  119. return index;
  120. }
  121. private void output(String string, int caseNum) {// 输出用例caseNum的结果string
  122. System.out.println("Case #" + caseNum);
  123. int quotients = string.length() / 76;// 每行最多76个字符
  124. for (int i = 0; i < quotients; ++i) {
  125. System.out.println(string.substring(i * 76, i * 76 + 76));
  126. }
  127. System.out.println(string.substring(quotients * 76));
  128. }
  129. public static void main(String[] args) {
  130. new Main();
  131. }
  132. }

版权声明

  1. 转载、参考、引用必须在首页添加如下文字:

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

WUSTOJ 1324: Base64 Coding(Java)未解决,求题解的更多相关文章

  1. 记一次未解决的异常:java.lang.NoClassDefFoundError: net/sf/json/JSONObject

    原因:Jetty会导致这个问题,Tomcat可以正常启动   一.异常产生现象 使用json-lib转换实体类/字符串,跑单元测试没问题,但是启动jetty后调用JSONArray.fromObjec ...

  2. oracle,wamp,FZ突然出现问题,求解决方案(未解决,最终系统还原)

    -----背景------- 系统:win7  64位oracle 11g(11.1)每天都用oracle.用toad for oracle .电脑固定IP.未更改任何配置信息.用了几个月,突然出现了 ...

  3. [未解决]Exception in thread "main" java.lang.IllegalArgumentException: offset (0) + length (8) exceed the capacity of the array: 6

    调用这个方法 是报错,未解决 binfo.setTradeAmount(Double.parseDouble(new String(result.getValue(Bytes.toBytes(fami ...

  4. IDEA Error:java: 未结束的字符串文字

    首页 > 编程交流 > 基础篇 > IDEA Error:java: 未结束的字符串文字 201601-25 IDEA Error:java: 未结束的字符串文字   IDEA开发, ...

  5. 报错:(未解决)Opening socket connection to server master/192.168.52.26:2181. Will not attempt to authenticate using SASL (unknown error)

    报错背景: CDH集群中,将kafka和Flume整合,将kafka的数据发送给Flume消费. 启动kafka的时候正常,但是启动Flume的时候出现了报错现象. 报错现象: DH--.cdh5./ ...

  6. WUSTOJ 1285: Factors(Java)

    1285: Factors 参考   hadis_fukan的博客--wustoj 1285 Factors 题目   输入一个数n,找出1~n之间(包括1,n)的质因子最多的数(x)的质因子个数(f ...

  7. OpenCV在ARM-linux上的移植过程遇到的问题3---共享库中嵌套库居然带路径【未解决】

    [Linux开发]OpenCV在ARM-linux上的移植过程遇到的问题3-共享库中嵌套库居然带路径[未解决] 标签(空格分隔): [Linux开发] 移植opencv到tq2440 一.下载open ...

  8. (未解决)flume监控目录,抓取文件内容推送给kafka,报错

    flume监控目录,抓取文件内容推送给kafka,报错: /export/datas/destFile/220104_YT1013_8c5f13f33c299316c6720cc51f94f7a0_2 ...

  9. 面向对象第一单元总结:Java实现表达式求导

    面向对象第一单元总结:Java实现表达式求导 题目要求 输入一个表达式:包含x,x**2,sin(),cos(),等形式,对x求导并输出结果 例:\(x+x**2+-2*x**2*(sin(x**2+ ...

随机推荐

  1. 如何画好ER图

    快速阅读 了解ER图的基本组成,以及如何在viso中画ER图. 什么是ER图 是实体关系图,用矩形表示实体,用椭圆形表示属性,用棱形表示两实体之间的联系.相互用直接联接起来,是一种数据建模工具.用来描 ...

  2. Oracle语法 及 SQL题目(二)

    目录 课例复制 思考题四 解题思路 思考题五 解题思路 课例复制 思考题四 最近,经过你的努力,你得到了一份工作,成为了百货公司的一位经理. 到位后,你发现你的销售数据库中有两张表,一个是商店促销时间 ...

  3. centos sqlite3安装及简单命令

    安装:方法一:wget http://www.sqlite.org/sqlite-autoconf-3070500.tar.gztar xvzf sqlite-autoconf-3070500.tar ...

  4. 真正的能理解CSS中的line-height,height与line-height

    https://blog.csdn.net/a2013126370/article/details/82786681 在最近的项目中,常常用到line-height,只是简单的理解为行高但并没有深层次 ...

  5. flutter Slider滑块组件

    滑块,允许用户通过滑动滑块来从一系列值中选择. import 'package:flutter/material.dart'; class SliderDemo extends StatefulWid ...

  6. 算法习题---4-7RAID技术(UV509)

    一:题目 (一)基础知识补充(RAID和奇偶校验) 磁盘管理—磁盘阵列(RAID)实例详解(本题目常用RAID 5技术实现) 奇偶校验(同行数据中同位上的1的个数,偶校验时:1的个数为偶数则校验结果为 ...

  7. php 验证rsa公钥和私钥是否正确

    <?php /** * RSA加密 * * @param string $data 待加密数据 * @param string $publicKey 公钥 * @return string|fa ...

  8. CentOS7下搭建Redis主从复制

    (1).实验环境 youxi1 192.168.1.6 Master服务器 youxi2 192.168.1.7 Slave服务器 (2).实验 1)两台服务器上yum安装Redis,启动并设置开机自 ...

  9. Python - Django - ORM 不常用字段

    BigAutoField(AutoField): bigint 自增列,必须填入参数 primary_key=True 如果没有写自增列,则会自动创建一个列名为 id 的列 SmallIntegerF ...

  10. LeetCode_231. Power of Two

    231. Power of Two Easy Given an integer, write a function to determine if it is a power of two. Exam ...