我有一个应用程序,我正在基于Java“源”类生成“目标文件”。我想在源更改时重新生成目标。我已经决定最好的方法是获取类内容的byte []并计算byte []的校验和。
我正在寻找获得类的byte []的最佳方法。此byte []将等同于已编译的.class文件的内容。使用ObjectOutputStream 不工作。下面的代码生成一个byte [],它比类文件的字节内容小得多。
// Incorrect function to calculate the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try( ObjectOutputStream stream = new ObjectOutputStream(buffer) ) {
stream.writeObject(myClass);
}
// This byte array is much smaller than the contents of the *.class file!!!
byte[] contents = buffer.toByteArray();
return contents;
}
有没有办法让byte []具有* .class文件的相同内容?计算校验和是很容易的部分,困难的部分是获取用于计算MD5或CRC32校验和的byte []内容。
答案 0 :(得分:4)
这是我最终使用的解决方案。我不知道它是否是最有效的实现,但是下面的代码使用类加载器来获取* .class文件的位置并读取其内容。为简单起见,我跳过了缓冲读取。
// Function to obtain the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
String path = myClass.getName().replace('.', '/');
String fileName = new StringBuffer(path).append(".class").toString();
URL url = myClass.getClassLoader().getResource(fileName);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try (InputStream stream = url.openConnection().getInputStream()) {
int datum = stream.read();
while( datum != -1) {
buffer.write(datum);
datum = stream.read();
}
}
return buffer.toByteArray();
}
答案 1 :(得分:0)
我不明白你的意思,但我认为你正在寻找这个,MD5。
要检查文件的MD5,您可以使用此代码
public String getMd5(File file)
{
DigestInputStream stream = null;
try
{
stream = new DigestInputStream(new FileInputStream(file), MessageDigest.getInstance("MD5"));
byte[] buffer = new byte[65536];
read = stream.read(buffer);
while (read >= 1) {
read = stream.read(buffer);
}
}
catch (Exception ignored)
{
int read;
return null;
}
return String.format("%1$032x", new Object[] { new BigInteger(1, stream.getMessageDigest().digest()) });
}
然后,您可以以任何方式存储文件的md5以用于exmaple XML。 MD5的例子是49e6d7e2967d1a471341335c49f46c6c
,因此一旦文件名和大小发生变化,md5就会改变。您可以以XML格式存储每个文件的md5,下次运行代码以检查md5并比较xml文件中每个文件的md5。
答案 2 :(得分:0)
如果你真的想要.class文件的内容,你应该读取.class文件的内容,而不是内存中的byte []表示。像
这样的东西import java.io.*;
public class ReadSelf {
public static void main(String args[]) throws Exception {
Class classInstance = ReadSelf.class;
byte[] bytes = readClass(classInstance);
}
public static byte[] readClass(Class classInstance) throws Exception {
String name = classInstance.getName();
name = name.replaceAll("[.]", "/") + ".class";
System.out.println("Reading this: " + name);
File file = new File(name);
System.out.println("exists: " + file.exists());
return read(file);
}
public static byte[] read(File file) throws Exception {
byte[] data = new byte[(int)file.length()]; // can only read a file of size INT_MAX
DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new FileInputStream(file)));
int total = 0;
int nRead = 0;
try {
while((nRead = inputStream.read(data)) != -1) {
total += nRead;
}
}
finally {
inputStream.close();
}
System.out.println("Read " + total
+ " characters, which should match file length of "
+ file.length() + " characters");
return data;
}
}