将十六进制字符串转换为图像文件

时间:2011-12-24 11:20:06

标签: java hex

我需要从收到的xml文件中读取带有前导零的十六进制字符串,该前导零表示JPEG文件并将其另存为图像文件。图像数据看起来像

0000005000000050FF191818FF151715FF111413FF0E1...........................FF2A2322FF292221

在xml文件中标签之间的字符串长度是51216我在Photo标签中读取Hex数据作为字符串并将其转换为byte [],并使用FileOutputStream我写入一份文件。但是,当我尝试打开图像文件时,它告诉“文件似乎已损坏,损坏或文件太大”我尝试了许多方法来保存图像,但没有成功。我列出了下面使用的方法。请帮帮我。

String photo="0000005000000050FF191818FF15"; //this is just a sample.The photo String actually contains the full Hex String which is 51216 long
//METHOD 1
    String[] v = photo.split(" ");
    byte[] arr = new byte[v.length];
    int x = 0;
    for(String val: v) {
        arr[x++] =  Integer.decode("0x" + val).byteValue();

    }
     FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(arr);
    fos.flush();
    fos.close();


  //METHOD 2
    byte[] arr = new byte[photo.length()/2];
    for ( int start = 0; start < photo.length(); start += 2 )
    {
        String thisByte = photo.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(arr);
    fos.flush();
    fos.close();


  //METHOD 3
    if ((photo.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[photo.length()/2];
    final char enc[] = photo.toCharArray();
    for (int x = 0; x < enc.length; x += 2) 
    {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[x]).append(enc[x + 1]);
        result[x/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(result);
    fos.flush();
    fos.close();


  //METHOD 4
    byte result[] = new byte[photo.length()/2];
    char enc[] = photo.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int x = 0; x < enc.length; x += 2) 
    {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[x]));
        curr.append(String.valueOf(enc[x + 1]));
        result[x] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(result);
    fos.flush();
    fos.close();


  //METHOD 5
    int len = photo.length();
    byte[] data = new byte[len / 2];
    for (int x = 0; x < len; x += 2)
    {
        data[x / 2] = (byte) ((Character.digit(photo.charAt(x), 16) << 4)
                             + Character.digit(photo.charAt(x+1), 16));
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(data);
    fos.flush();
    fos.close();


  //METHOD 6
    byte[] bytes=new BigInteger(photo, 16).toByteArray();
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(bytes);
    fos.flush();
    fos.close();


  //METHOD 7
    byte[] bytes =DatatypeConverter.parseHexBinary(photo);
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(bytes);
    fos.flush();
    fos.close();


  //METHOD 8
     HexBinaryAdapter adapter = new HexBinaryAdapter();
    byte[] bytes = adapter.unmarshal(photo);
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.png");
    fos.write(bytes);
    fos.flush();
    fos.close();


  //METHOD 9
    byte data[] = new byte[photo.length()/2];
    for(int x=0;i < photo.length();x+=2) {
        data[x/2] = (Integer.decode("0x"+photo.charAt(x)+photo.charAt(x+1))).byteValue();
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(data);
    fos.flush();
    fos.close();


  //METHOD 10
    byte[] data = new byte[photo.length()/2];
    for (int x=0;i<photo.length()/2;x++) 
    {
        data[x] = (Integer.decode(
                "0x"+photo.substring(x*2, (x+1)*2))).byteValue();
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(data);
    fos.flush();
    fos.close();


  //METHOD 11
    String hexVal ="0000005000000050FF";
    //String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[photo.length() / 2];
    int n = photo.length();
    for( int x = 0; x < n; x += 2 ) {
        int hn = hexVal.indexOf( photo.charAt( x ) );
        int ln = hexVal.indexOf( photo.charAt( x + 1 ) );

        out[x/2] = (byte)( ( hn << 4 ) | ln );
    }
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(out);
    fos.flush();
    fos.close();



    //METHOD 12
     byte[] array=photo.getBytes();
     FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(array);
    fos.flush();
    fos.close();


    //METHOD 13
    byte[] array=photo.getBytes();
    byte[] bytes = Base64.decode(array);
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(bytes);
    fos.flush();
    fos.close();


    //METHOD 14
    byte[] array=photo.getBytes();
    Charset csets = Charset.forName("UTF-8");
    ByteBuffer bb=ByteBuffer.wrap(array);
    csets.decode(bb);
    bb.rewind();
    byte[] array1=bb.array();
    FileOutputStream fos=new FileOutputStream("D:/Images/image6.jpg");
    fos.write(array1);
    fos.flush();
    fos.close();

4 个答案:

答案 0 :(得分:0)

最短的方式可能是这个。

String photo = "0000005000000050FF191818FF151715FF111413FF0E100FF2A2322FF292221";

// adds a dummy byte at the start to avoid truncation of leading zeros.
byte[] bytes = new BigInteger("10" + photo, 16).toByteArray();

System.out.println(Arrays.toString(bytes));

打印

[1,0,0,0,5,0,0,0,5,15,-15,-111,-127,-113,-15,81,113,95,-15,17, 65,63,-16,-31,0,-1,42,35,34,-1,41,34,33]

答案 1 :(得分:0)

public class test {

    static String HEX_STRING = "0123456789ABCDEF";

    public static byte[] convertHexadecimal2Binary(byte[] hex) {
        int block = 0;
        byte[] data = new byte[hex.length / 2];
        int index = 0;
        boolean next = false;
        for (int i = 0; i < hex.length; i++) {
            block <<= 4;
            int pos = HEX_STRING.indexOf(Character.toUpperCase((char) hex[i]));
            if (pos > -1) {
                block += pos;
            }
            if (next) {
                data[index] = (byte) (block & 0xff);
                index++;
                next = false;
            } else {
                next = true;
            }
        }
        return data;
    }

    public static void main(String args[]) {
        String line = "";
        String line_final = "";
        try {
            String sCurrentLine;
            BufferedReader br = new BufferedReader(new FileReader("D:\\test.txt"));//test.txt hex code string
            DataOutputStream os = new DataOutputStream(new FileOutputStream("D:\\mohit.jpg"));
            while ((sCurrentLine = br.readLine()) != null) {
                line = StringUtils.deleteWhitespace(sCurrentLine);
                byte[] temp = convertHexadecimal2Binary(line.getBytes());
                os.write(temp);
            }
            os.close();
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

答案 2 :(得分:0)

当你检索文件时,会在十六进制字符串的开头附加一个空格,所以删除空格并将其存储在另一个字节数组中,它可以正常工作:

这是删除起始空间的代码

byte a3[] = new BigInteger(str, 16).toByteArray();  
byte a[] = new byte[a3.length - 1];
for (int i = 1; i < a3.length; i++)
    a[i - 1] = a3[i];

此处a3包含检索到的字节数据;
 a1包含实际的字节流

答案 3 :(得分:0)

方法2看起来正确(尚未检查所有其他方法) - 您的问题可能在其他地方。您确定从XML中提取的字符串是否完整?你使用哪种解析器?也许它会在多个部分返回长字符串(我认为这可能是SAX解析器的情况),而你只提取第一部分?

以下是我将如何实现解码部分(通过substringBigIntegerchar[]等避免不需要的额外分配...;为了提高性能,您可能需要使用BufferedOutputStream虽然):

String photo = "0000005000000050FF191818FF15"; 
FileOutputStream fos = new FileOutputStream("D:/Images/image6.jpg");
for (int i = 0; i < photo.length; i += 2) {
  int byte = Character.digit(photo.charAt(i), 16) * 16 + 
             Character.digit(photo.charAt(i + 1), 16);
  fos.write(byte);
}
fos.close();