这可能是一个非常基本的问题,但我正在尝试创建一个执行进程的Java方法,并读取从该进程创建的输入流并写入新文件。我正在使用Runtime.getRuntime()。exec(cmd []),我想为特定的索引使用不同的参数,例如cmd [3] =“某事物”或cmd [3] =“其他东西”。我使用for循环来执行此操作,但对于cmd [3]的参数数组中的第一个索引,我希望它使用PrintWriter打印到新文件,因此我在顶部初始化后在if语句中初始化它for循环。如果我只是显示代码,那么你可能会更容易:
public static synchronized void myMethod(String [] argument3, File file) throws IOException{
String[] cmd = {"command", "argument 1", "argument 2"};
PrintWriter fileWriter = null;
Scanner fileScanner = null;
int i;
for(i = 0; i < argument3.length; i++){
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));;
cmd[3] = argument3[i];
if(i == 0){
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
}
Process p = Runtime.getRuntime().exec(cmd);
fileScanner = new Scanner(p.getInputStream());
while(fileScanner.hasNextLine()){
fileWriter.println(fileScanner.nextLine());
}
fileWriter.close();
fileScanner.close();
}
}
所有这一切都运行正常,但在eclipse中我得到一个警告说我有资源泄漏我在if语句中初始化我的PrintWriter所以我只是好奇为什么那是因为我关闭它们在底部for循环?我知道它并没有太大的区别,因为无论如何我只是想尝试正确地清理我的代码。 提前致谢
答案 0 :(得分:-1)
需要注意的重要事项是
throws IOException
这可以抛出,如果抛出,您的资源将不会被关闭。您应确保在任何情况下都关闭资源,即使抛出异常也是如此。使用...
try { ... } finally { ... close here... }
......为此。想象一下,当您的文件被读取时,会发生一些不好的事情。抛出IOException并且永远不会调用close()
语句,这将是eclipse提到的可怕的资源泄漏。
答案 1 :(得分:-1)
我收到一条警告,说我有资源泄漏,我在if语句中初始化了我的PrintWriter。
问题在于:
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));
if (i == 0) {
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
}
fileWriter.close();
第一次循环,当该条件成立时,你创建了两个PrintWriters
,只有第二个被关闭。你只是放弃了第一个。相反,你可以像这样初始化它:
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file, i != 0)));
但这提出了一个问题,为什么每次循环都会重新创建PrintWriter
?只需在循环外创建一次。
另一个问题是,如果抛出异常,则不会实际执行任何清理代码。你需要的是一个try-catch-finally块,你可以保证你的清理代码被执行。如果您至少使用Java 7,则可以使用try-with-resources,它会自动为您完成所有清理工作:
void myMethod(String [] argument3, File file) throws IOException {
String[] cmd = {"command", "argument 1", "argument 2"};
try (PrintWriter fileWriter = new PrintWriter (file)) {
for (int i = 0; i < argument3.length; i++) {
Process process = Runtime.getRuntime().exec(cmd);
try (Scanner fileScanner = new Scanner(process.getInputStream())) {
cmd[3] = argument3[i];
while (fileScanner.hasNextLine()) {
fileWriter.println(fileScanner.nextLine());
}
}
}
}
}
答案 2 :(得分:-1)
基本上,VM正在抱怨,因为两个内部对象永远不会关闭。
for(i = 0; i < argument3.length; i++){
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));;
cmd[3] = argument3[i];
if(i == 0){
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
}
Process p = Runtime.getRuntime().exec(cmd);
fileScanner = new Scanner(p.getInputStream());
while(fileScanner.hasNextLine()){
fileWriter.println(fileScanner.nextLine());
}
fileWriter.close();
fileScanner.close();
}
你应该基本上将元素定义分开:
for (i = 0; i < argument3.length; i++) {
FileOutputStream fos;
if (i == 0)
fos = new FileOutputStream(file, false);
else
fos = new FileOutputStream(file, true);
OutputStreamWriter osw = new OutputStreamWriter(osw);
fileWriter = new PrintWriter(osw);
// do the rest
// and then...
fileWriter.close();
fileScanner.close();
osw.close();
fos.close();
}
这将删除警告。
P.S。:正如之前的回答所示,将.close方法移动到finally
块会被认为是最好的。
答案 3 :(得分:-1)
使用try catch finally阻止并关闭finally块中的Scanner
和PrintWriter
,因为最终总是执行:
public static synchronized void myMethod(String[] argument3, File file) {
String[] cmd = { "command", "argument 1", "argument 2" };
PrintWriter fileWriter = null;
Scanner fileScanner = null;
try {
for (int i = 0; i < argument3.length; i++) {
fileWriter = new PrintWriter(new OutputStreamWriter(
new FileOutputStream(file, true)));
cmd[3] = argument3[i];
if (i == 0) {
fileWriter = new PrintWriter(new OutputStreamWriter(
new FileOutputStream(file, false)));
}
Process p = Runtime.getRuntime().exec(cmd);
fileScanner = new Scanner(p.getInputStream());
while (fileScanner.hasNextLine()) {
fileWriter.println(fileScanner.nextLine());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
fileWriter.close();
fileScanner.close();
}
}