JavaSDK解析乱码问题

使用citaj 调用合约查询接口,
接口返回hex数据
通过java解析把数据解析成UTF-8普通字符串时,出现乱码

查询方法1结果:
0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008f62616e6b5472616e736665725061797c2b7c307c2b7c307c2b7c3130303030307c2b7c3130303030307c2b7c307c2b7c3130303030307c2b7c50592d32643062663662662d313937302d343330362d383161382d3361343334663463356534377c2b7c7c2b7c323031392d30382d32382031353a32313a30377c2b7c317c2b7ce8aea2e58d95e5b7b2e7a1aee8aea40000000000000000000000000000000000

字符串结果1:
�bankTransferPay|+|0|+|0|+|100000|+|100000|+|0|+|100000|+|PY-2d0bf6bf-1970-4306-81a8-3a434f4c5e47|+||+|2019-08-28 15:21:07|+|1|+|订单已确认

查询方法2结果:
0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000457c2b7c7c2b7c7c2b7c7c2b7c323031392d30382d32382031353a32353a35327c2b7c7c2b7c7c2b7c7c2b7c323031392d30382d32382031353a32353a30387c2b7c357c2b7c000000000000000000000000000000000000000000000000000000

字符串结果2:
E|+||+||+||+|2019-08-28 15:25:52|+||+||+||+|2019-08-28 15:25:08|+|5|+|

JAVA 代码:

//hex转字符串

//16进制转换成为string类型字符串
private static String hexStringToString(String s) {
    if (s == null || s.equals("")) {
        return null;
    }
    s = s.replace(" ", "");
    byte[] baKeyword = new byte[s.length() / 2];
    for (int i = 0; i < baKeyword.length; i++) {
        try {
            if (s.substring(i * 2, i * 2 + 2).equals("00")) {
                continue;
            }
            baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    try {
        s = new String(baKeyword, "UTF-8");
        new String();
    } catch (Exception e1) {
        e1.printStackTrace();
    }

    return s;
}

//把前导0的字符串转为正常字符串
private static String hexStringToStringOne(String hexStr) {
    String bigInt = new BigInteger(hexStr, 16).toString(16);
    return bigInt;
}


//链上取出的十六进制字符串转为普通字符串
private String hexToString(String hexStr) {
    String BigIntToString = hexStringToStringOne(hexStr.substring(2));
    String orderInfo = hexStringToString(BigIntToString).replace("\u0000", "").replace("\u0001", "").replace("\t", "");
    return orderInfo;
}


//调用合约查询方法获取结果
public String callContractFunc() {
    Call call = new Call('from', contractAddress, callData);
    //该结果有乱码(多余字符)
    String hexStr = citaJService.appCall(call, DefaultBlockParameterName.LATEST).send().getValue();
    return hexToString(hexStr);
}

另外,采用Cita JS sdk 调用合约查询接口,会直接返回正确的字符串数据

代码如下:

(async () => {
    var contractInstance = new citaSDK.base.Contract(abi, contractAddress);
    var queryRes = await contractInstance.methods['myQueryFunc'](params).call();

    //打印查询结果,该结果正确,不包含乱码(多余字符)
    console.log('query res', queryRes);
})();

使用如下方法解决问题:


private static Type getAppCallResult(String addr, Function func)
            throws IOException {
        String funcData = FunctionEncoder.encode(func);
        Call call = new Call(fromAddress, addr, funcData);
        String result = service.appCall(call, DefaultBlockParameterName.PENDING)
                .send().getValue();
        return FunctionReturnDecoder.decode(result, func.getOutputParameters()).get(0);
    }

private static String getName() throws Exception {
        Function func = new Function(
                "userName",
                Collections.emptyList(),
                Collections.singletonList(new TypeReference<DynamicBytes>() {}));

        DynamicBytes dynamicBytes = (DynamicBytes) getAppCallResult(contractAddr, func);
        String hexString = ConvertStrByte.bytesToHexString(dynamicBytes.getValue());
        return ConvertStrByte.hexStringToString(hexString);
    }

来自SDK的测试代码。

1赞