问题
I have a requirement to read a Hex String with leading zeros which represents a JPEG file, from an xml file received and save it as an image file. The image data looks like
0000005000000050FF191818FF151715FF111413FF0E1...........................FF2A2322FF292221
In xml file The length of String between the tag is 51216 I read the Hex data in between the Photo tag as a String and Converted it to a byte[], and the using a FileOutputStream
I am writing to a file. But when I try to open the image file it tells "the file appears to be damaged,corrupted or file is too large" I have tried many methods to save the image, but no success. I am listing the methods used below. Please help me out from this.
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();
回答1:
The shortest way might be this.
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));
prints
[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]
回答2:
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();
}
}
}
回答3:
When you retrieve a file a space will be appended at the beginning of the hex string so remove the space and store it in another byte array and it works fine:
here is code for removing starting space
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];
Here a3
contains retrieved byte data;
a1
contains actual byte stream
回答4:
Method 2 looks correct (haven't checked all others) -- your problem is probably elsewhere. Are you sure the string extracted from the XML is complete? Which parser are you using? Perhaps it returns long strings in multiple parts (I think this might be the case for SAX parsers), and you are extracting only the first part?
Here is how I would implement the decoding part (avoiding unneeded extra allocations via substring
, BigInteger
, char[]
etc...; for performance, you may want to use a BufferedOutputStream though):
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();
来源:https://stackoverflow.com/questions/8624203/converting-a-hex-string-to-an-image-file