我已经设法使十六进制转换为十六进制,但您可以从输出中看到,当我尝试将Base64转换回十六进制时,有一个轻微的异常(例如,将Base64的最后四个值与十六进制输出进行比较)。
十六进制到基64:
应打印:SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t实际打印:SSDTIGTPBGXPBMCGEW91CIBICMFPBMCGEW91CIBICMFPBIBSAWTLIGEGCG9PC29UB3VZIG11C2HYB29T
Base64到十六进制:
应打印:49276D206B696C6C696E6720796F757220627261696E206C696B6520612070F6E6F7573206D757368726F6F6D
实际打印:49276D206B696C6C696E6720796E717220627261696E206C696B65206120706E69732E6E6F3573206C717328726F2E6D
我使用https://conv.darkbyte.ru/检查我的一些值,假设该站点上的代码是正确的,看来我的问题是如何从Base64获得Base10表示,而不是Base10到十六进制:
十进制等价
我的输出:
73,39,109,32,107,105,108,108,108,105,110,103,103,121,110,113,114,32,98,114,97,105,110,108,107,101,32,97,112,110,115,115,46,110,111,53,115,32,108,113,115,40,114,111,46,109
站点的输出:
73,39,109,32,107,105,108,108,108,105,110,103,32,121,111,117,114,32,98,114,97,105,110,32,108,107,101,32,112,111,111,111,111,111,111,111,111,111,111,117,115,117,115,117,117,115,104,114,111,111,109
似乎所有有错误的值都聚集在40-60和100-120附近,但我不确定从那里到底该往哪里走。我猜我正在处理某种边缘案件,但我不确定那会是什么。
相关代码:
private static final Character[] base64Order = new Character[] { '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 static final Character[] hexOrder = new Character[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
'b', 'c', 'd', 'e', 'f' };
public static String base64ToHex(String base64) throws Exception {
if (base64.length() % 4 != 0 || base64.contains("[^a-zA-Z0-9\\+/]"))
throw new Exception("InputNotBase64");
else {
int charValue = 0;
int index = 0;
String hex = "";
BitSet bits = new BitSet();
for (int i = 0; i < base64.length(); i++) {
charValue = base64.charAt(i);
// get actual value from ASCII table
if (charValue > 64 && charValue < 91)
charValue -= 65;
if (charValue > 96 && charValue < 123)
charValue -= 71;
/// loop that adds to the BitSet reads right-to-left, so reverse
// the bits and then shift
charValue = Integer.reverse(charValue << 24) & 0xff;
charValue >>= 2;
// append binary values to the BitSet
while (charValue != 0L) {
if (charValue % 2 != 0) {
bits.set(index);
}
index++;
charValue >>= 1;
}
// account for trailing 0s
while (index % 6 != 0) {
index++;
}
}
// read 8-bit integer value for hex-value lookup
String temp;
int remainder;
for (int i = 0; i < index; i++) {
charValue = (charValue | (bits.get(i) ? 1 : 0));
if ((i + 1) % 8 == 0) {
temp = "";
while (charValue != 0L) {
remainder = charValue % 16;
temp = hexOrder[remainder] + temp;
charValue /= 16;
}
hex += temp;
}
charValue <<= 1;
}
return hex;
}
}
您忘记在代码中处理以下字符:“0”、“1”、“2”、“3”、“4”、“5”、“6”、“7”、“8”、“9”、“+”、“/”(如果替换以下代码
if (charValue > 64 && charValue < 91)
charValue -= 65;
if (charValue > 96 && charValue < 123)
charValue -= 71;
由
charValue = getPositionInBase64(charValue);
哪里
public static int getPositionInBase64(int n)
{
for (int p = 0; p < base64Order.length; p++)
{
if (n == base64Order[p])
{
return p;
}
}
return -1;
}
if (charValue >= 'A' && charValue <= 'Z')
charValue -= 'A';
...
在这种情况下,发现问题更容易
因为你要求我提出可能的改进来加速计算。
准备下表并初始化一次
// index = character, value = index of character from base64Order
private static final int[] base64ToInt = new int[128];
public static void initBase64ToIntTable()
{
for (int i = 0; i < base64Order.length; i++)
{
base64ToInt[base64Order[i]] = i;
}
}
charValue = base64ToInt[base64.charAt(i)];
private static String intToHex(int n)
{
return String.valueOf(new char[] { hexOrder[n/16], hexOrder[n%16] });
}
public static String base64ToHexVer2(String base64) throws Exception
{
StringBuilder hex = new StringBuilder(base64.length()*3/4); //capacity could be 3/4 of base64 string length
if (base64.length() % 4 != 0 || base64.contains("[^a-zA-Z0-9\\+/]"))
{
throw new Exception("InputNotBase64");
}
else
{
for (int i = 0; i < base64.length(); i += 4)
{
int n0 = base64ToInt[base64.charAt(i)];
int n1 = base64ToInt[base64.charAt(i+1)];
int n2 = base64ToInt[base64.charAt(i+2)];
int n3 = base64ToInt[base64.charAt(i+3)];
// in descriptions I treat all 64 base chars as 6 bit
// all 6 bites from 0 and 1st 2 from 1st (00000011 ........ ........)
hex.append(intToHex(n0*4 + n1/16));
// last 4 bites from 1st and first 4 from 2nd (........ 11112222 ........)
hex.append(intToHex((n1%16)*16 + n2/4));
// last 2 bites from 2nd and all from 3rd (........ ........ 22333333)
hex.append(intToHex((n2%4)*64 + n3));
}
}
return hex.toString();
}
要测试速度,可以使用以下结构
String b64 = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
try
{
Base64ToHex.initBase64ToIntTable();
System.out.println(Base64ToHex.base64ToHex(b64));
System.out.println(Base64ToHex.base64ToHexVer2(b64));
int howManyIterations = 100000;
Date start, stop;
long period;
start = new Date();
for (int i = 0; i < howManyIterations; i++)
{
Base64ToHex.base64ToHexVer2(b64);
}
stop = new Date();
period = stop.getTime() - start.getTime();
System.out.println("Ver2 taken " + period + " ms");
start = new Date();
for (int i = 0; i < howManyIterations; i++)
{
Base64ToHex.base64ToHex(b64);
}
stop = new Date();
period = stop.getTime() - start.getTime();
System.out.println("Ver1 taken " + period + " ms");
}
catch (Exception ex)
{
}
示例结果为
49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
Ver2 taken 300 ms
Ver1 taken 2080 ms
但这只是近似值。当您首先检查Ver1,然后检查Ver2时,结果可能会有一点不同。此外,对于不同的java(6、7、8)和用于启动java的不同设置,结果也可能不同
问题内容: 我想将十六进制字符串转换为二进制字符串。例如,十六进制2是0010。下面是代码: 但是,这仅适用于十六进制0-9;它不适用于十六进制A-F,因为它使用。谁能增强它? 问题答案: 您需要告诉Java int是十六进制的,如下所示:
问题内容: 要将String转换为十六进制,我正在使用: 在此处投票最高的答案中对此进行了概述:在Java中将 字符串转换为十六进制 我该如何反向执行,即将十六进制转换为字符串? 问题答案: 您可以从转换后的字符串中进行重构,这是一种实现方法: 另一种方法是使用,从包: 单元测试以验证: 注:领先剥离的仅仅是必要的,因为的你的填充方法。如果您不介意将其替换为简单的,则可以将此行放在:
问题内容: 我发现将十六进制转换为二进制的方式如下: 尽管此方法适用于较小的十六进制数,但以下十六进制数 抛出一个 因此,我编写了以下似乎可行的方法: 上面的方法基本上接受十六进制字符串中的每个字符,并在必要时将其转换为等价的二进制零,然后将其连接到返回值。这是执行转换的正确方法吗?还是我忽略了一些可能导致我的方法失败的事情? 在此先感谢您的协助。 问题答案: 会做你想要的。只需传递2的基数即可。
问题内容: 我需要将二进制字符串转换为十六进制字符串,但是我有问题。我通过这种方法将二进制字符串转换为十六进制字符串: 没关系!但是我丢失了字符串左侧的零。例如: 该方法返回此:123456789ABCDEF,但我想返回此: 00000123456789ABCDEF 问题答案: 而不是我将使用解析值,然后以所需的宽度(在您的示例中为21)输出值:
问题内容: 我也想将我的二进制(在字符串中)转换为十六进制字符串,这只是一个程序片段,因为该程序只是另一个更大程序的一部分: 问题是我不知道填充是否有效,但是我确定该程序返回了二进制字符串的错误十六进制转换,我正在尝试这样做: http://www.wikihow.com/Convert-Binary-to- Hexadecimal PS:我需要实现它(不使用任何内置函数) 问题答案: 如果您不必
问题内容: 我编写了一个简单的程序,用于在Java中向串行端口发送和接收数据。我通过回送测试(Rx到Tx)连接串行端口设备。它工作正常。但我无法发送和接收十六进制数据到串行端口和接收串行端口。在我的设备中使用了FT232BL芯片,因此是否需要任何dll或其他库来将十六进制数据发送和接收到串行端口设备。我的代码如下。 问题答案: 十六进制: 十六进制为: