我在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文件的问题吗?
非常感谢任何建议。
答案 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