【问题标题】:Bitwise-and with Hex and Character in JavaJava中的按位与十六进制和字符
【发布时间】:2015-09-04 17:41:54
【问题描述】:

我需要将给定的整数(我的整数总是小于 30000)转换为其对应的十六进制值,然后获取该值的字符。输出的长度应为 2 个字节。

Ex1:

  • 整数值 = 25135(十进制值)
  • 对应的十六进制值 = 622f (2 Bytes)
  • 十六进制字符的对应字符 = b/(hex 62 = char b and hex 2f = char /)

Ex2:

  • 整数值 = 207(十进制值)
  • 对应的十六进制值=CF(1字节)
  • 对应的十六进制值(填充两个字节后)= 00CF(2字节)
  • 十六进制字符的对应字符 = 一些不可打印的 2 个字符(在日志文件中它看起来像 ^@ 和我用破折号)

以下 C++ 代码在上述两种情况下都能正常工作。

void WriteBinaryTag(char* _zBuf, int _iValue)
{
    unsigned short usValue = (unsigned short)_iValue;

    ((unsigned char*)_zBuf)[1] = (unsigned char)usValue & 0x00FF;
    usValue >>= 8;
    ((unsigned char*)_zBuf)[0] = (unsigned char)usValue & 0x00FF;
}

现在我需要在 Java 中做同样的事情,我是通过以下方式完成的。

public static char[] writeBinaryTag (int iTag) {
    char[] data = new char[2];
    data[1]= (char) (iTag & 0x00FF);
    iTag >>= 8;
    data[0]= (char) (iTag & 0x00FF);
    return data;
}

问题: 我测试了上面的java方法如下。

char[] temp = writeBinaryTag(207);
StringBuilder frame = new StringBuilder();
frame.append(temp);
System.out.println("OUT1:"+207+":"+frame.toString()+"|");

char[] temp2 = writeBinaryTag(25135);
StringBuilder frame2 = new StringBuilder();
frame2.append(temp2);
System.out.println("OUT2:"+25135+":"+frame2.toString()+"|");

使用 StringBuilder 是因为我需要将几个变量附加到除上述二进制标签之外的同一帧。最后我打印上面的帧值。然后我使用 binaryviewer 分析打印的日志文件以查看相应的十六进制值。 问题是上面的 java 代码仅适用于上面的示例 1(Value 25135 ) 。对于它产生的示例二(值 207):

  • 对应的十六进制值是 00C38F(看起来是 3 个字节),而不是由 c++ 代码生成的 00CF。

谁能帮我找出java代码的问题。

【问题讨论】:

    标签: java


    【解决方案1】:

    您没有在此处转换为十六进制。看来您想将 16 位值转换为两个字节。 (char 是 Java 中的 16 位值)

    相当于

    void writeBinaryTag(byte[] zBuf, int _iValue) {
        zBuf[1] = (byte) _iValue;
        zBuf[0] = (byte) (_iValue >> 8);
    }
    

    创建一个 byte[] 只是为了做到这一点是低效的,而且几乎可以肯定不是你想要写的,而是有一个 API 可以做到这一点。

    ByteBuffer bb = ....order(ByteOrder.LITTLE_ENDIAN);
    bb.writeShort((short) _iValue);
    
    // later to read an unsigned short
    int iValue = bb.readShort() & 0xFFFF;
    

    【讨论】:

    • 非常感谢您的回复。我尝试了您建议的第一种方法。(出于测试目的,我刚刚在方法中创建了字节数组)public static byte[] writeBinaryTag3( int _iValue) { byte[] zBuf = new byte[2]; zBuf[1] = (byte) _iValue; zBuf[0] = (byte) (_iValue >> 8); return zBuf; } 但它产生的东西很长。例如:对于 207:打印值:[B@13cd9466 使用二进制文件分析器分析时的十六进制值:5B 42 40 31 33 63 64 39 34 36 36 对于 25125:打印值:[B@1dc9beb2 ex 使用二进制文件分析器分析时的值: 5B 42 40 31 64 63 39 63 65 62 32
    • @user1308004 不幸的是,这就是byte[].toString() 所做的。如果你想打印十进制数字,你需要使用Arrays.toString(zBuf) 如果你想打印十六进制,你需要编写自己的例程。
    • 非常感谢您的解释。您能告诉我为什么我之前的代码适用于较大的数字(例如 25135)而不适用于较小的数字(例如 207)吗?
    • @user1308004 在这两种情况下,您只能有两个字符。它同样有效。对于一个或两个字节值。能说一下是什么问题吗?
    • 对于 25135 java 方法工作正常。这意味着对应的十六进制值 = 622f 和十六进制字符的对应字符 = b/(十六进制 62 = char b 和十六进制 2f = char /)。但是对于 207,它的生产方式不同。 207 对应的十六进制值是 CF。这些十六进制字符的对应字符是一些不可打印的 2 个字符,带有 c++ 代码(在日志文件中,它看起来像 ^@,而 I 带有破折号)但是在分析日志文件时使用 java 代码,我可以看到 00C38F 表示 00CF 的 207。这就是我遇到的问题
    【解决方案2】:

    看到我正在处理一些硬件交互,当时我在 util.xml 中编写了不同的方法。它也有助于所有不同的转化。

     private static String binaryToHex(String bin) {
         return String.format("%X", Long.parseLong(bin,2)) ;
     }
    

    public static String hexToBinary16Bit(String hex16bit) {
        int i = Integer.parseInt(hex16bit, 16);
        String bin = toBinary(i);
        return String.format("%0d", Integer.parseInt(bin));
    }
    

    private static String hexToBinary(String hex) {
        int i = Integer.parseInt(hex, 16);
        String bin = Integer.toBinaryString(i);
        return String.format("%08d", Integer.parseInt(bin));
    }
    

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                        + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
    

    private static String hexBin(String hex) {
        int a = Integer.parseInt(hex, 16);
        System.out.println(a);
        String finalBin = null;
        int bit=1;
        for(int i=0; i<16; i++) {
    
            sBuilder.append((((a&bit)==0)?0:1));
            finalBin = sBuilder.toString();
            bit*=2;
        }
    return finalBin;
    }
    

     public static String[] customSplit(String src) {
                String [] output = src.replaceAll("\\[","").replaceAll("   \\]","").split(",");
    
            for (String element : output) {
                    System.out.println(element);
            }
        return output;
      }
    

        private static String hexToASCII(String hexValue) {
            StringBuilder output = new StringBuilder("");
            for (int i = 0; i < hexValue.length(); i += 2) {
                    String str = hexValue.substring(i, i + 2);
                    output.append((char) Integer.parseInt(str, 16));
            }
        return output.toString();
       }
    

     public static String hexBin8bit(String hex) {
            StringBuilder sBuilder = new StringBuilder();
            int a = Integer.parseInt(hex, 16);
            System.out.println(a);
            String finalBin = null;
            int bit=1;
            for(int i=0; i<8; i++) {
    
                sBuilder.append((((a&bit)==0)?0:1));
                finalBin = sBuilder.toString();
                bit*=2;
            }
        return finalBin;
        }
    

    public static int toInt32(byte[] bytes, int index) throws Exception {
                if (bytes.length != 4)
                    throw new Exception("The length of the byte array must be at least 4 bytes long.");
                return (int) ((int) (0xff & bytes[index]) << 56 | (int) (0xff & bytes[index + 1]) << 48 | (int) (0xff & bytes[index + 2]) << 40 | (int) (0xff & bytes[index + 3]) << 32);
            }
    

    public static byte[][] split(byte [] arrayIn, int len) {

        if (arrayIn == null) {
            return null;
        }
    
        boolean even = arrayIn.length % len == 0;
    
        int totalLength = arrayIn.length / len;
    
        if (!even)
            totalLength++;
    
        byte[][] newArray = new byte[totalLength][];
    
        for (int i = 0; i < totalLength; ++i) {
            int allocLength = len;
            if (!even && i == totalLength - 1)
                allocLength = arrayIn.length % len;
            newArray[i] = new byte[allocLength];
            System.arraycopy(arrayIn, i * len, newArray[i], 0, allocLength);
        }
    
        return newArray;
    }
    

    public static byte[][] split1dArray1(byte[] arr1D, int columnSize) {
                byte[][] arr2D = null;
                int rowSize = arr1D.length/columnSize;
    
                for(int i = 0; i < rowSize; i++){
                    for(int j = 0; j < columnSize; j++){
                        arr2D[i][j] = arr1D[i+j];
                    }
                }
    
                return arr2D;
    

    }

    public static byte[][] split1dArray2(byte[] arr1D, int columnSize) {
                int len=arr1D.length;
    
                if(len%512 !=0) {
                    len= len/columnSize +1;
                } else {
                    len=len/columnSize;
                }
    
                byte [][] arr2D= new byte [len][columnSize];
    
                int k=0;
                for(int i=0; i<=len-1; i++) {
                    for(int j=0; j<=columnSize-1; i++) {
                        arr2D[i][j]=arr1D[k];
                        k++;
                    }   
                }
                return arr2D;
            }
    

    public static String toHexString(byte[] hexByte) {
                StringBuilder str = new StringBuilder();
                for(int i = 0; i < hexByte.length; i++)
                    str.append(String.format("%x", hexByte[i]));
                return str.toString();
            }
    

    private static byte [] test() {
        // Command String
        String hex = "84";
    
        //Creates the command byte array (Function #1)
        int NumberChars = hex.length();
        byte[] bytes = new byte[NumberChars / 2];
        for (int i = 0; i < NumberChars; i += 2) {
            int x = i+2;
            bytes[i / 2] = new BigInteger(hex.substring(i, x),16).byteValue();
        }
        return bytes;
    } 
    

    【讨论】:

    • 这里有很多方法,但我看不到与问题相关的方法。
    • @Vid : 你能告诉我这些函数中的哪一个可以解决我的问题吗?
    • @user1308004 他们都没有。 -1
    猜你喜欢
    • 2015-01-14
    • 2019-07-27
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 2012-11-20
    • 2012-03-25
    • 1970-01-01
    相关资源
    最近更新 更多