关于JPG雕刻的Java正则表达式

时间:2011-07-16 19:01:10

标签: java regex bytearray

我在Java中使用正则表达式时遇到一些问题。我正在尝试搜索ISO文件,并将所有JPG图像分割出来(如果有的话)。

目前,我在使用以下正则表达式在JPG中查找EXIF信息方面取得了成功:

Pattern imageRegex = Pattern.compile("\\x45\\x78\\x69\\x66"); //Exif regex

这样可以正常工作,然后我可以将文件分割出EXIF信息。

但是,如果我使用这个正则表达式:

Pattern imageRegex = Pattern.compile("\\xff\\xd8\\xff"); //JPG header regex

Java无法找到任何匹配项。我可以确认ISO文件中存在JPG。

我一次将200字节的文件读入字节数组,然后将其转换为字符串以进行正则表达式。

任何人都可以建议为什么会这样,因为它相当令人困惑。

或者任何人都可以建议更好的方法来解决使用Java中的正则表达式编写JPG文件的问题吗?

非常感谢任何建议。

3 个答案:

答案 0 :(得分:0)

  

我一次将200字节的文件读入字节数组,然后将其转换为字符串以进行正则表达式。

也许所有的JPEG标题都是在N * 200边框上分割的。

无论如何,这是一种搜索二进制数据的非常规(且效率低)的方式。你找到标题之前为什么不经过input stream

答案 1 :(得分:0)

如果您正在读取字节数组并将其转换为字符串,则字符串编码问题可能会让您陷入困境。碰巧你正在寻找的EXIF模式都是ASCII兼容的:

0x45 0x78 0x69 0x66
E    x    i    f

但JPEG标题不是:

0xff 0xd8 0xff

你最好接受Jakub的建议并跳过正则表达式。

答案 2 :(得分:0)

使用正则表达式匹配二进制序列很少适合;我想知道你是否很清楚Java中二进制数据和字符串之间的概念差异(而不是C)。

JPEG文件是二进制数据( bytes 的序列),要在模式正则表达式中使用,必须在Java中将它作为String(一系列字符) ),它们基本上是不同的实体,并且要从一个转换为另一个,必须指定一些字符集编码。此外,当您在模式中指定文字\x45或作为文字字符串时,您并不意味着(如您所知)“二进制值为0x45的字节”(这没有意义,因为我们是不处理字节)但是,“Unicode中的字符点编号0x45”。

确实,在几种常见的字符集编码中(特别是在UTF-8和ISO-8859-1及其变体中),“ascii范围”(小于127)中的字节序列将转换为代码点用那个字节值。但对于其他编码(如UTF-16)或其他值(在128-255范围内),这不是必然的。特别是,对于UTF-8来说并非如此 - 对于ISO-8859-1来说也是如此,但你不应该依赖这种“巧合”(如果你这是巧合)。

在您的场景中,我会说如果您指定ISO-8859-1编码,您可能会得到您所期望的。但它仍然会闻起来很糟糕。

练习:尝试预测/理解此代码打印的内容:

public static void main(String[] args) throws Exception {
    byte[] b = { 0x30, (byte) 0xb2 };
    String x = new String(b, "ISO-8859-1");
    System.out.println(x.matches(".*\\x30.*"));
    System.out.println(x.matches(".*\\xb2.*"));
    String x2 = new String(b, "UTF-8");
    System.out.println(x2.matches(".*\\x30.*"));
    System.out.println(x2.matches(".*\\xb2.*"));
}

将鼠标放在下方以查看答案。

  

true true true false