Java:将文件转换为十六进制?

10

我在Java中有一个文件

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

我想将pic.bmp转换为十六进制值的数组,以便我可以编辑并保存修改后的版本。

有没有Java类可以做到这一点?


2
使用类似于 hexdumphexedit 或者在 Vim 中直接使用 :%!xxd 这样的工具不是更容易吗? - Josef Pfleger
4个回答

20

你很幸运,我几个月前也需要做这件事。这是一个简化版本,它从命令行获取了两个参数。两个命令行参数都是文件名...第一个是输入文件,第二个是输出文件。输入文件以二进制形式读取,输出文件以ASCII十六进制形式写入。希望你可以根据自己的需求进行修改。

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();
        }
    }
}

如果你的薪水取决于代码行数,那么你可以写256个if语句 :) - Denis Tulskiy
2
你可以使用 String.format("%x") 代替你的 toHexFromByte 方法。 - Josef Pfleger
1
String.format() 或 Java 的 printf 从代码角度来看肯定更漂亮,但根据我的经验,与直接进行字节操作和数组查找相比,它们非常慢。这就是我实现自己的 toHexFromByte 方法的唯一原因。 - Brent Writes Code
@Brent:我没有考虑到性能问题,之前的评论有些抱歉。 - Denis Tulskiy
1
如果您关心性能,我认为您应该修改 toHexFromByte(byte b) 方法中的代码,改为将结果追加到 StringBuilder 中,而不是返回一个新的二字符串。 - ykaganovich
@Pilgrim 别担心,你的观点完全合理。如果性能不是主要问题,那么你的方法肯定更容易阅读和理解。@ykaganovich 是的,说得对。:-D 对于这个特定的应用程序来说,toHexFromByte(byte) 方法可能甚至不需要作为一个单独的函数,因为它从未在 toHexFromBytes 之外被调用过。 - Brent Writes Code

3
Java有一个广泛的图像读取/写入和编辑库。查看javax.imageio包(这里是文档)。您可能希望使用ImageIO创建BufferedImage,然后从BufferedImage对象访问图像数据(有相应的方法)。
如果您想要一个通用答案,适用于任何类型的二进制数据(不仅限于图像),那么我想您需要将文件内容读入字节数组中。类似于这样:
byte[] bytes = new byte[in.available()];
in.read(bytes);

我想能够将任何文件转换为十六进制,无论是图像、可执行文件还是压缩文件。那么难道没有一种通用的方法可以将文件作为二进制或十六进制读取,更改值并保存为新的修改后的文件吗? - BinRoot
2
in.read(bytes) 是最常用的方法。如果你想以十六进制形式输出数字,请使用System.out.printf("%X", bytes[0]); - Denis Tulskiy

1

更新的 URL: http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Hex.html - Jose Miguel Ordax

0
如果你想自己操作字节,可以从FileInputStream获取一个FileChannel,然后分配一个ByteBuffer并将所有内容读入其中。ByteBuffer还有处理更大字节块的方法,以两种不同的字节顺序进行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接