tags:

views:

1339

answers:

4

I have a file in Java

FileInputStream in = null;
try{    
in = new FileInputStream("C:\\pic.bmp");
}catch{}

I want to convert pic.bmp to an array of hex values so I can edit and save it as a modified version.

Is there a java class to do this?

+2  A: 

Java has an extensive image reading/writing and editing library. Look at the javax.imageio packages (here's the documentation). You would probably want to create a BufferedImage using ImageIO and then access the image data from the BufferedImage object (there are methods for that).

If you want a generic answer, for any type of binary data (not just images), then I guess you would have to read the contents of the file into a byte array. Something like this:

byte[] bytes = new byte[in.available()];
in.read(bytes);
David Zaslavsky
I want to be able to convert to hex any file whether it be an image or an executable or a zip archive. So isn't there a general way to read the file as a binary or hexadecimal to change the values and save as a new modified file?
Nick
in.read(bytes) is the most general way of doing this. If you want to output number in hex, use System.out.printf("%X", bytes[0]);
tulskiy
A: 

If you want to fiddle with the bytes yourself, get a FileChannel from the FileInputStream, and then allocate a ByteBuffer and then read all the content into it. ByteBuffer also has methods to deal with larger chunks of bytes, in the two different byte orders.

Ken
+4  A: 

You're in luck. I had to do this a couple months ago. Here's a dumbed-down version that takes two parameters from the command line. Both comand line parameters are filenames...the first is the input file and the second is the output file. The input file is read in binary and the output file is written as ASCII hex. Hopefully you can just adapt this to your needs.

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;

public class BinToHex
{
    private final static String[] hexSymbols = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    public final static int BITS_PER_HEX_DIGIT = 4;

    public static String toHexFromByte(final byte b)
    {
     byte leftSymbol = (byte)((b >>> BITS_PER_HEX_DIGIT) & 0x0f);
     byte rightSymbol = (byte)(b & 0x0f);

     return (hexSymbols[leftSymbol] + hexSymbols[rightSymbol]);
    }

    public static String toHexFromBytes(final byte[] bytes)
    {
     if(bytes == null || bytes.length == 0)
     {
      return ("");
     }

     // there are 2 hex digits per byte
     StringBuilder hexBuffer = new StringBuilder(bytes.length * 2);

     // for each byte, convert it to hex and append it to the buffer
     for(int i = 0; i < bytes.length; i++)
     {
      hexBuffer.append(toHexFromByte(bytes[i]));
     }

     return (hexBuffer.toString());
    }

    public static void main(final String[] args) throws IOException
    {
     try
     {
      FileInputStream fis = new FileInputStream(new File(args[0]));
      BufferedWriter fos = new BufferedWriter(new FileWriter(new File(args[1])));

      byte[] bytes = new byte[800];
      int value = 0;
      do
      {
       value = fis.read(bytes);
       fos.write(toHexFromBytes(bytes));

      }while(value != -1);

      fos.flush();
      fos.close();
     }
     catch(Exception e)
     {
      e.printStackTrace();
     }
    }
}
Brent Nash
Thank you! This is exactly what I needed. You rock!
Nick
@Nick: it was far from obvious from the question that this is what you wanted...
David Zaslavsky
if your salary depends on lines of code, you can write 256 if statements :)
tulskiy
You could use `String.format("%x")` instead of your `toHexFromByte` methods.
Josef
String.format() or Java's printf are certainly prettier code-wise, but in my experience they're painfully slow compared to doing byte manipulations and an array lookup directly. That's the only reason I implemented my own toHexFromByte method.
Brent Nash
@Brent: I didn't think about performance, sorry for the previous comment.
tulskiy
If you care about performance, I think you should modify toHexFromByte(byte b) to append to the StringBuilder, rather than return a new 2-char string.
ykaganovich
@Pilgrim No worries, it was a perfectly reasonable point. If performance isn't a major concern, then your way is certainly a lot easier to read/understand.@ykaganovich Yeah, good point. :-D For this particular application, the toHexFromByte(byte) method probably doesn't even need to be a separate function since it's never called outside of toHexFromBytes.
Brent Nash
A: 

If you type "java hexidecimal encoding" into a Google search, the first result is http://commons.apache.org/codec/api-release/org/apache/commons/codec/binary/Hex.html which is what you should use to answer the "I want to convert pic.bmp to an array of hex values" part of your question.

I don't see how it helps you with "so I can edit and save it as a modified version" though. You should probably use a hexidecimal editor for that. eg. ghex2

Lispnik