我使用以下函数来计算文件的校验和:
public static void generateChecksums(String strInputFile, String strCSVFile) {
ArrayList<String[]> outputList = new ArrayList<String[]>();
try {
MessageDigest m = MessageDigest.getInstance("MD5");
File aFile = new File(strInputFile);
InputStream is = new FileInputStream(aFile);
System.out.println(Calendar.getInstance().getTime().toString() +
" Processing Checksum: " + strInputFile);
double dLength = aFile.length();
try {
is = new DigestInputStream(is, m);
// read stream to EOF as normal...
int nTmp;
double dCount = 0;
String returned_content="";
while ((nTmp = is.read()) != -1) {
dCount++;
if (dCount % 600000000 == 0) {
System.out.println(". ");
} else if (dCount % 20000000 == 0) {
System.out.print(". ");
}
}
System.out.println();
} finally {
is.close();
}
byte[] digest = m.digest();
m.reset();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
// Now we need to zero pad it if you actually / want the full 32 chars.
while(hashtext.length() < 32 ){
hashtext = "0" + hashtext;
}
String[] arrayTmp = new String[2];
arrayTmp[0] = aFile.getName();
arrayTmp[1] = hashtext;
outputList.add(arrayTmp);
System.out.println("Hash Code: " + hashtext);
UtilityFunctions.createCSV(outputList, strCSVFile, true);
} catch (NoSuchAlgorithmException nsae) {
System.out.println(nsae.getMessage());
} catch (FileNotFoundException fnfe) {
System.out.println(fnfe.getMessage());
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
}问题是读入文件的循环非常慢:
while ((nTmp = is.read()) != -1) {
dCount++;
if (dCount % 600000000 == 0) {
System.out.println(". ");
} else if (dCount % 20000000 == 0) {
System.out.print(". ");
}
}一个3 GB的文件从一个位置复制到另一个位置只需不到一分钟,但计算起来却需要一个多小时。我是否可以做些什么来加快速度,或者我应该尝试不同的方向,比如使用shell命令?
更新:多亏了ratchet freak的建议,我把代码改成这样,速度快得离谱(我猜快2048倍...):
byte[] buff = new byte[2048];
while ((nTmp = is.read(buff)) != -1) {
dCount += 2048;
if (dCount % 614400000 == 0) {
System.out.println(". ");
} else if (dCount % 20480000 == 0) {
System.out.print(". ");
}
}发布于 2011-05-23 07:41:33
你试过移除println吗?我想所有的字符串操作都会消耗大部分的处理时间!
编辑:我没有看清楚,我现在意识到它们很少被输出,我会收回我的答案,但我猜它并不是完全无价的:-p (对不起!)
发布于 2011-05-23 07:53:55
问题是System.out.print使用得太频繁了。每次调用它时,都必须创建新的String对象,而且开销很大。
请改用StringBuilder类或它的线程安全模拟StringBuffer。
StringBuilder sb = new StringBuilder();每次你需要添加一些东西的时候,调用这个:
sb.append("text to be added");稍后,当您准备打印它时:
system.out.println(sb.toString());发布于 2011-05-23 08:02:02
坦率地说,你的代码中有几个问题使它变得很慢:
read()可能被转换为操作系统IOs调用而没有自动缓冲,所以一个read()就是一个系统调用!如果您使用数组作为缓冲区或BufferedInputStream,操作系统通常会执行得更好。更好的是,你可以使用nio将文件映射到内存中,并以操作系统可以处理的速度读取它。dCount++;计数器可能已经使用了很多周期。我相信即使是最新的英特尔酷睿处理器,也需要几个时钟周期才能完成64位浮点加法。对于这个计数器,你最好使用一个长整型。如果此计数器的唯一目的是显示进度,则可以利用Java整数溢出而不会导致错误的事实,并在char类型换行为0(即每65536次读取)时提前显示进度。StringBuilder或Formatter。while(hashtext.length() < 32 ){ hashtext = "0"+hashtext;}
中的更多效率问题
https://stackoverflow.com/questions/6091544
复制相似问题