使用 FileChannel 和 ByteBuffer 读取 JPEG 幻数

Read JPEG magic number with FileChannel and ByteBuffer

我开始深入研究 Java NIO API,作为第一次尝试,我想读取一个 JPEG 文件幻数。

这是代码

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import java.nio.channels.FileChannel;

import java.nio.charset.Charset;

import java.io.FileInputStream;

public class JpegMagicNumber {
    public static void main(String[] args) throws Exception {
        FileChannel file = new FileInputStream(args[0]).getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(6);
        file.read(buffer);
        buffer.flip();
 System.out.println(Charset.defaultCharset().decode(buffer).toString());
file.close();
buffer.clear(); 
    }
}

我希望取回幻数字符,但我得到的只是终端中的垃圾数据。

我是不是做错了什么?

简答:代码没有特别的缺陷。 JPEG 前面只有 'garbage'。

长答案:JPEG 内部由 一个接一个地组成。这些段以 0xFF 字节开头,后跟标识符字节,然后是可选的 payload/content.

示例开始:

FF D8 FF E0 00 10 4A 46 49 46 00 01 01 00 00 01 00 01 00 00 FF E1

图像以图像开始 (SOI) 段 0xFF 0xD8 开始,它没有有效负载。

下一段是'application specific',0xFF 0xE0。有效负载的长度后跟两个字节(包括这两个字节!)。

0x4A 0x46 0x49 0x46 : JFIF ← 也许你在找什么?

JPEG 没有您可能正在寻找的那种神奇数字,例如 'PK' 用于 zip 或 '‰PNG' 用于 PNG。 (最接近的是 SOI 的 0xFF 0xD8 0xFF 和下一段的第一个字节。)

因此您的代码 确实 正确读取文件的前六个字节,根据您的本机平台将它们解码为字符,并打印出来,但是 JPEG header 看起来就是那样。