Golang代码转Java时数据类型范围的问题如何解决
Golang代码转Java时数据类型范围的问题如何解决 你好!,
我尝试将一段代码翻译成Java,但在数据类型范围和位操作方面遇到了问题,有人能帮忙吗?
两段代码都可以编译运行,但得到了不同的结果 😦
如果有人能帮忙,我将不胜感激!!! Go代码:
package main
import (
"encoding/binary"
"fmt"
"strconv"
)
func crc32v(idx int) int {
POLY := 0x04c11db7
c := idx << 24 & 0xFFFFFFFF
for i := 0; i < 8; i++ {
k:= c&0x80000000
if k > 0 {
c = c<<1 ^ POLY
} else {
c = c << 1 & 0xFFFFFFFF
}
}
return c
}
func adler32(bs []byte) int {
s1 := 4
s2 := 0
for _, x := range bs {
s1 = (s1 + int(x)) % 65521
s2 = (s2 + s1) % 65521
}
res := (s2 << 16) | s1
return res
}
func prepareSubs(key []int) [][]int {
table1 := make([]int, 256)
for i := range table1 {
table1[i] = i
}
s := 0
for i := range table1 {
s += table1[i]
s += key[i%len(key)]
s &= 0xFF
table1[i] = table1[s]
}
table2 := make([]int, 256)
for i, v := range table1 {
table2[i] = v
}
s = 0
for i := range table2 {
if i > 0 {
s = (table2[i] + s) & 0xFF
table2[i] = table2[s]
}
}
out := [][]int{table1, table2}
return out
}
func Reverse(s string) (result string) {
for _, v := range s {
result = string(v) + result
}
return
}
func rbit(x int, width int) int {
x2 := strconv.FormatInt(int64(x), 2)
orig := len(x2)
for i := 0; i < width-orig; i++ {
x2 = fmt.Sprintf("0%s", x2)
}
x3, _ := strconv.ParseInt(Reverse(x2), 2, 32)
return int(x3)
}
func hashFunction(srcData []byte, timestamp int) string {
ldsBytes := []byte{0x0D, 0xC0, 0xA0, 0xE1, 0xF0, 0x00, 0x2D, 0xE9, 0xE9, 0x00, 0x40, 0xE2, 0x00, 0x70, 0xA0, 0xE1, 0x01, 0x00, 0xA0, 0xE1, 0x02, 0x10, 0xA0, 0xE1, 0x03, 0x20, 0xA0, 0xE1, 0x78, 0x00, 0x9C, 0xE8}
stackCrc := crc32v(0x63)
inpbs := make([]byte, 0)
for i := 0; i < 4; i++ {
next := srcData[i*16 : i*16+4]
for _, b := range next {
inpbs = append(inpbs, b)
}
}
// Append timestamp bytes to inpbs
tsBytes := make([]byte, 4)
binary.BigEndian.PutUint32(tsBytes, uint32(timestamp))
for _, b := range tsBytes {
inpbs = append(inpbs, b)
}
ldsChecksum := adler32(ldsBytes)
crcbs := 0
for i := 0; i < 4; i++ {
crcbs = (crcbs << 4) + (ldsChecksum & 0xff)
ldsChecksum >>= 8
}
crcbs = (crc32v(crcbs&0xFF) ^ crc32v((crcbs>>8)&0xFF))
key := []int{
crcbs & 0xFF,
0,
(crcbs >> 8) & 0xFF,
(stackCrc >> 8) & 0xFF,
(crcbs >> 16) & 0xFF,
(crcbs >> 24) & 0xFF,
0,
stackCrc & 0xFF,
}
// Returns multi-dimensional int array
sbox := prepareSubs(key)
result := make([]int, len(inpbs)) // It prepends like 6 bytes before the return
for r, i := range inpbs {
result[r] = int(i)
}
for i := range result {
result[i] ^= sbox[0][(sbox[1][i+1]<<1)&0xFF]
}
for i := range result {
x := ((result[i] << 4) & 0xF0) | ((result[i] >> 4) & 0xF)
x ^= result[(i+1)%len(result)]
x = rbit(x, 8)
x ^= 0xFF
x ^= 0x14
result[i] = x
}
pre := make([]int, len(result)+6)
pre[0] = 0x03
pre[1] = 0x6F
pre[2] = key[7]
pre[3] = key[3]
pre[4] = 0
pre[5] = 0
for r, v := range result {
pre[r+6] = v
}
str := ""
for _, p := range pre {
str = fmt.Sprintf("%s%02x", str, p)
}
fmt.Println("As []int: \t", pre)
fmt.Printf("As hex:\t\t%02x\n", pre)
fmt.Printf("As hex string:\t%v\n", str)
return str
}
func main() {
var favicon = []byte{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x5d, 0x52, 0x1c, 0x00, 0x00, 0x00, 0x0f, 0x50,
0x4c, 0x54, 0x45, 0x7a, 0xdf, 0xfd, 0xfd, 0xff, 0xfc, 0x39, 0x4d, 0x52, 0x19, 0x16, 0x15, 0xc3, 0x8d, 0x76, 0xc7,
0x36, 0x2c, 0xf5, 0x00, 0x00, 0x00, 0x40, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x95, 0xc9, 0xd1, 0x0d, 0xc0, 0x20,
0x0c, 0x03, 0xd1, 0x23, 0x5d, 0xa0, 0x49, 0x17, 0x20, 0x4c, 0xc0, 0x10, 0xec, 0x3f, 0x53, 0x8d, 0xc2, 0x02, 0x9c,
0xfc, 0xf1, 0x24, 0xe3, 0x31, 0x54, 0x3a, 0xd1, 0x51, 0x96, 0x74, 0x1c, 0xcd, 0x18, 0xed, 0x9b, 0x9a, 0x11, 0x85,
0x24, 0xea, 0xda, 0xe0, 0x99, 0x14, 0xd6, 0x3a, 0x68, 0x6f, 0x41, 0xdd, 0xe2, 0x07, 0xdb, 0xb5, 0x05, 0xca, 0xdb,
0xb2, 0x9a, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
}
hashFunction(favicon,1)
}
Java代码:
import java.nio.ByteBuffer;
import java.util.Arrays;
public class Lev {
public static long crc32v(long idx) {
int POLY = 0x04c11db7;
long c = (idx << 24) & 0xFFFFFFFF;
long k;
for (int i = 0; i < 8; i++) {
k = c&0x80000000;
if (k > 0) {
c = (c << 1) ^ POLY;
} else {
c = (c << 1) & 0xFFFFFFFF;
}
}
return c;
}
public static long adler32(int[] bs) {
long s1 = 4;
long s2 = 0;
for (int i = 0; i < bs.length; i++) {
s1 = (s1 + (int) bs[i]) % 65521;
s2 = (s2 + s1) % 65521;
}
long res = (s2 << 16) | s1;
return res;
}
public static long[][] prepareSubs(long[] key) {
long[] table1 = new long[256];
for (int i = 0; i < table1.length; i++) {
table1[i] = i;
}
int s = 0;
for (int i = 0; i < table1.length; i++) {
s += table1[i];
s += key[i % key.length];
s &= 0xFF;
table1[i] = table1[s];
}
long[] table2 = new long[256];
for (int i = 0; i < table1.length; i++) {
table2[i] = table1[i];
}
s = 0;
for (int i = 0; i < table2.length; i++) {
if (i > 0) {
s = (int) ((table2[i] + s) & 0xFF);
table2[i] = table2[s];
}
}
long[][] out = new long[][]{
table1, table2
};
return out;
}
// Reverse a string
static String Reverse(String s) {
StringBuilder sb = new StringBuilder(s);
return sb.reverse().toString();
}
public static int rbit(int x, int width) {
String x2 = Long.toString((long) x, 2);
int orig = x2.length();
for (int i = 0; i < width - orig; i++) {
x2 = String.format("0%s", x2);
}
int x3 = Integer.parseInt(Reverse(x2), 2);
return x3;
}
public static String hashFunction(int[] srcData, int timestamp) {
int[] ldsBytes = new int[]{
0x0D, 0xC0, 0xA0, 0xE1, 0xF0, 0x00, 0x2D, 0xE9, 0xE9, 0x00, 0x40, 0xE2, 0x00, 0x70, 0xA0, 0xE1, 0x01, 0x00, 0xA0, 0xE1, 0x02, 0x10, 0xA0, 0xE1, 0x03, 0x20, 0xA0, 0xE1, 0x78, 0x00, 0x9C, 0xE8
};
long stackCrc = crc32v(0x63);
byte[] inpbs = new byte[0];
for (int i = 0; i < 4; i++) {
int[] next = Arrays.copyOfRange(srcData, i * 16, i * 16 + 4);
for (int f = 0; f < next.length; f++) {
inpbs = append(inpbs, next[f]);
}
}
// Append timestamp bytes to inpbs
byte[] tsBytes = new byte[4];
tsBytes = ByteBuffer.allocate(4).putInt(timestamp).array();
//binary.BigEndian.PutUint32(tsBytes, uint32(timestamp))
for (int i = 0; i < tsBytes.length; i++) {
inpbs = append(inpbs, tsBytes[i]);
}
long ldsChecksum = adler32(ldsBytes);
long crcbs = 0;
for (int i = 0; i < 4; i++) {
crcbs = (crcbs << 4) + (ldsChecksum & 0xff);
ldsChecksum >>= 8;
}
crcbs = (crc32v(crcbs & 0xFF) ^ crc32v((crcbs >> 8) & 0xFF));
long[] key = new long[]{
crcbs & 0xFF,
0,
(crcbs >> 8) & 0xFF,
(stackCrc >> 8) & 0xFF,
(crcbs >> 16) & 0xFF,
(crcbs >> 24) & 0xFF,
0,
stackCrc & 0xFF,
};
// Returns multi-dimensional int array
long[][] sbox = prepareSubs(key);
int[] result = new int[inpbs.length]; // It prepends like 6 bytes before the return
for (int i = 0; i < inpbs.length; i++) {
result[i] = inpbs[i];
}
for(int i = 0; i < result.length;i++){
result[i] ^= sbox[0][(int) ((sbox[1][i + 1] << 1) & 0xFF)];
}
for(int i = 0; i < result.length;i++){
int x =((result[i] << 4) & 0xF0) | ((result[i] >> 4) & 0xF);
x ^= result[(i + 1) % result.length];
x = rbit(x, 8);
x ^= 0xFF;
x ^= 0x14;
result[i] = x;
}
long[] pre =new long[result.length + 6];
pre[0] = 0x03;
pre[1] = 0x6F;
pre[2] = key[7];
pre[3] = key[3];
pre[4] = 0;
pre[5] = 0;
for (int i = 0; i < result.length; i++) {
pre[i + 6] = result[i];
}
String str="";
for(int i = 0; i < pre.length; i++){
str = str.format("%s%02x", str, pre[i]);
}
System.out.println(str);
return str;
}
public static void main(String[] args) {
int[] favicon = new int[]{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x5d, 0x52, 0x1c, 0x00, 0x00, 0x00, 0x0f, 0x50,
0x4c, 0x54, 0x45, 0x7a, 0xdf, 0xfd, 0xfd, 0xff, 0xfc, 0x39, 0x4更多关于Golang代码转Java时数据类型范围的问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我的问题是我无法修改Go代码,只能修改Java代码以防止结果发生变化。您能告诉我需要在Java中做哪些更改吗?
此致 Joost
JoostCore: 我对数据类型的范围有疑问。
既然你提到了范围,那么只看adler32,Go版本中的输入数组使用的是byte(范围0到255),而Java版本使用的是int(32位整数)。
你可能还需要指定int数据类型的大小,例如int64、int32,以便直接对应Java的long和int。
builtin package - builtin - Go Packages
Package builtin provides documentation for Go’s predeclared identifiers.
Primitive Data Types (The Java™ Tutorials > Learning…)
This beginner Java tutorial describes fundamentals of programming in the Java programming language
问题不在于范围,而在于Java要求你指定一个数字是否为长整型。差异出现在crc32v函数中,唯一需要做的修改是在0x80000000和0xFFFFFFFF后面加上L。
public static long crc32v(long idx) {
int POLY = 0x04c11db7;
long c = (idx << 24) & 0xFFFFFFFFL;
long k;
for (int i = 0; i < 8; i++) {
k = c&0x80000000L;
if (k > 0) {
c = (c << 1) ^ POLY;
} else {
c = (c << 1) & 0xFFFFFFFFL;
}
}
return c;
}
如果不加L,Java会将该数字视为32位整数,并将其符号扩展为64位。
问题出在Java的int类型是有符号的32位整数,而Go的int在64位系统上是64位。在Java中,位操作超过32位时会溢出,需要特别注意无符号处理。
以下是修复后的Java代码:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
public class Lev {
public static long crc32v(long idx) {
long POLY = 0x04c11db7L;
long c = (idx << 24) & 0xFFFFFFFFL;
for (int i = 0; i < 8; i++) {
long k = c & 0x80000000L;
if (k != 0) {
c = ((c << 1) ^ POLY) & 0xFFFFFFFFL;
} else {
c = (c << 1) & 0xFFFFFFFFL;
}
}
return c & 0xFFFFFFFFL;
}
public static long adler32(byte[] bs) {
long s1 = 4;
long s2 = 0;
for (byte b : bs) {
s1 = (s1 + (b & 0xFF)) % 65521;
s2 = (s2 + s1) % 65521;
}
return ((s2 << 16) | s1) & 0xFFFFFFFFL;
}
public static int[][] prepareSubs(int[] key) {
int[] table1 = new int[256];
for (int i = 0; i < 256; i++) {
table1[i] = i;
}
int s = 0;
for (int i = 0; i < 256; i++) {
s = (s + table1[i] + key[i % key.length]) & 0xFF;
table1[i] = table1[s];
}
int[] table2 = Arrays.copyOf(table1, 256);
s = 0;
for (int i = 0; i < 256; i++) {
if (i > 0) {
s = (table2[i] + s) & 0xFF;
table2[i] = table2[s];
}
}
return new int[][]{table1, table2};
}
public static int rbit(int x, int width) {
int result = 0;
for (int i = 0; i < width; i++) {
result = (result << 1) | ((x >> i) & 1);
}
return result;
}
public static String hashFunction(byte[] srcData, int timestamp) {
byte[] ldsBytes = new byte[]{
0x0D, (byte)0xC0, (byte)0xA0, (byte)0xE1, (byte)0xF0, 0x00, 0x2D, (byte)0xE9,
(byte)0xE9, 0x00, 0x40, (byte)0xE2, 0x00, 0x70, (byte)0xA0, (byte)0xE1,
0x01, 0x00, (byte)0xA0, (byte)0xE1, 0x02, 0x10, (byte)0xA0, (byte)0xE1,
0x03, 0x20, (byte)0xA0, (byte)0xE1, 0x78, 0x00, (byte)0x9C, (byte)0xE8
};
long stackCrc = crc32v(0x63);
byte[] inpbs = new byte[4 * 4 + 4];
for (int i = 0; i < 4; i++) {
System.arraycopy(srcData, i * 16, inpbs, i * 4, 4);
}
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(timestamp);
System.arraycopy(buffer.array(), 0, inpbs, 16, 4);
long ldsChecksum = adler32(ldsBytes);
long crcbs = 0;
for (int i = 0; i < 4; i++) {
crcbs = (crcbs << 4) + (ldsChecksum & 0xFF);
ldsChecksum >>= 8;
}
crcbs = crc32v(crcbs & 0xFF) ^ crc32v((crcbs >> 8) & 0xFF);
int[] key = new int[]{
(int)(crcbs & 0xFF),
0,
(int)((crcbs >> 8) & 0xFF),
(int)((stackCrc >> 8) & 0xFF),
(int)((crcbs >> 16) & 0xFF),
(int)((crcbs >> 24) & 0xFF),
0,
(int)(stackCrc & 0xFF)
};
int[][] sbox = prepareSubs(key);
int[] result = new int[inpbs.length];
for (int i = 0; i < inpbs.length; i++) {
result[i] = inpbs[i] & 0xFF;
}
for (int i = 0; i < result.length; i++) {
int idx = (sbox[1][i + 1] << 1) & 0xFF;
result[i] ^= sbox[0][idx];
}
for (int i = 0; i < result.length; i++) {
int x = ((result[i] << 4) & 0xF0) | ((result[i] >> 4) & 0x0F);
x ^= result[(i + 1) % result.length];
x = rbit(x, 8);
x ^= 0xFF;
x ^= 0x14;
result[i] = x & 0xFF;
}
int[] pre = new int[result.length + 6];
pre[0] = 0x03;
pre[1] = 0x6F;
pre[2] = key[7];
pre[3] = key[3];
pre[4] = 0;
pre[5] = 0;
System.arraycopy(result, 0, pre, 6, result.length);
StringBuilder str = new StringBuilder();
for (int p : pre) {
str.append(String.format("%02x", p & 0xFF));
}
return str.toString();
}
public static void main(String[] args) {
byte[] favicon = new byte[]{
(byte)0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x5d, 0x52,
0x1c, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c, 0x54, 0x45, 0x7a, (byte)0xdf, (byte)0xfd, (byte)0xfd,
(byte)0xff, (byte)0xfc, 0x39, 0x4d, 0x52, 0x19, 0x16, 0x15, (byte)0xc3, (byte)0x8d, 0x76, (byte)0xc7,
0x36, 0x2c, (byte)0xf5, 0x00, 0x00, 0x00, 0x40, 0x49, 0x44, 0x41, 0x54, 0x08, (byte)0xd7, (byte)0x95,
(byte)0xc9, (byte)0xd1, 0x0d, (byte)0xc0, 0x20, 0x0c, 0x03, (byte)0xd1, 0x23, 0x5d, (byte)0xa0, 0x49,
0x17, 0x20, 0x4c, (byte)0xc0, 0x10, (byte)0xec, 0x3f, 0x53, (byte)0x8d, (byte)0xc2, 0x02, (byte)0x9c,
(byte)0xfc, (byte)0xf1, 0x24, (byte)0xe3, 0x31, 0x54, 0x3a, (byte)0xd1, 0x51, (byte)0x96, 0x74, 0x1c,
(byte)0xcd, 0x18, (byte)0xed, (byte)0x9b, (byte)0x9a, 0x11, (byte)0x85, 0x24, (byte)0xea, (byte)0xda,
(byte)0xe0, (byte)0x99, 0x14, (byte)0xd6, 0x3a, 0x68, 0x6f, 0x41, (byte)0xdd, (byte)0xe2, 0x07,
(byte)0xdb, (byte)0xb5, 0x05, (byte)0xca, (byte)0xdb, (byte)0xb2, (byte)0x9a, (byte)0xdd, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, (byte)0xae, 0x42, 0x60, (byte)0x82
};
String result = hashFunction(favicon, 1);
System.out.println("Result: " + result);
}
}
主要修改:
- 使用
long类型处理32位无符号整数,并在所有位操作后添加& 0xFFFFFFFFL掩码 - 将
adler32参数改为byte[],读取时使用b & 0xFF确保无符号 - 重写
rbit函数使用位操作而非字符串转换 - 所有数组访问确保索引在有效范围内
- 使用
ByteBuffer处理大端序整数转换 - 输出时使用
& 0xFF确保字节值正确格式化

