所以,如果你经常这样做,file.io 会变得非常昂贵......如我的屏幕截图和原始代码getFileContentsAsList
中所见,包含 file.io 调用的,被调用了很多(18.425 次)。VisualVM 是一个真正的工具,可以指出这些瓶颈!
在考虑了各种提高性能的方法后,我突然意识到,最好的方法可能是尽可能少地调用 file.io。因此,我决定使用私有静态变量来保存文件内容,并且只在静态初始化程序中和写入文件时执行 file.io。由于我的应用程序(幸运的是)没有过度写入(但过度阅读),这使得应用程序性能更好。
这是包含该getFileContentsAsList
方法的整个类的源代码。我拍摄了该方法的快照,它现在运行时间为 57.2 毫秒(低于 3116 毫秒)。此外,这是我运行时间最长的方法,现在是我运行时间第四长的方法。前 5 个运行时间最长的方法现在总共运行了 498.8 毫秒,而原始屏幕截图中的那些方法总共运行了 3812.9 毫秒。这是大约 85% [100 * (498.8 - 3812.9) / 3812.9] 的百分比下降。
package com.mbc.receiptprinter.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import com.mbc.receiptprinter.constant.FileDelimiters;
import com.mbc.receiptprinter.constant.FilePaths;
/*
* Various File utility functions. This class uses the Apache Commons FileUtils class.
*/
public class ReceiptPrinterFileUtils {
private static Map<String, String> fileContents = new HashMap<String, String>();
private static Map<String, Boolean> fileHasBeenUpdated = new HashMap<String, Boolean>();
static {
for (FilePaths fp : FilePaths.values()) {
File f = new File(fp.getPath());
try {
FileUtils.touch(f);
fileHasBeenUpdated.put(fp.getPath(), false);
fileContents.put(fp.getPath(), FileUtils.readFileToString(f));
} catch (IOException e) {
ReceiptPrinterLogger.logMessage(ReceiptPrinterFileUtils.class,
Level.SEVERE,
"IOException while performing FileUtils.touch in static block of ReceiptPrinterFileUtils", e);
}
}
}
public static String getFileContents(String filePath) throws IOException {
if (ReceiptPrinterStringUtils.isNullOrEmpty(filePath)) throw new IllegalArgumentException("File path must not be null or empty");
File f = new File(filePath);
if (fileHasBeenUpdated.get(filePath)) {
fileContents.put(filePath, FileUtils.readFileToString(f));
fileHasBeenUpdated.put(filePath, false);
}
return fileContents.get(filePath);
}
public static List<String> convertFileContentsToList(String fileContents) {
List<String> records = new ArrayList<String>();
if (fileContents.contains(FileDelimiters.RECORD)) {
records = Arrays.asList(fileContents.split(FileDelimiters.RECORD));
}
return records;
}
public static void writeStringToFile(String filePath, String data) throws IOException {
fileHasBeenUpdated.put(filePath, true);
FileUtils.writeStringToFile(new File(filePath), data);
}
public static void writeStringToFile(String filePath, String data, boolean append) throws IOException {
fileHasBeenUpdated.put(filePath, true);
FileUtils.writeStringToFile(new File(filePath), data, append);
}
}