Java 关闭已在if语句中初始化的PrintWriter对象
这可能是一个非常基本的问题,但我正在尝试创建一个Java方法,该方法执行一个进程,读取从该进程创建的inputstream并写入一个新文件。我使用的是Runtime.getRuntime().exec(cmd[]),我想对特定索引使用不同的参数,例如cmd[3]=“something”或cmd[3]=“something other”。我使用for循环来实现这一点,但是对于cmd[3]的参数数组中的第一个索引,我希望它使用PrintWriter打印到一个新文件,因此在for循环顶部初始化它之后,我在if语句中初始化了它。如果我只显示代码,可能会更容易,因此您可以:Java 关闭已在if语句中初始化的PrintWriter对象,java,Java,这可能是一个非常基本的问题,但我正在尝试创建一个Java方法,该方法执行一个进程,读取从该进程创建的inputstream并写入一个新文件。我使用的是Runtime.getRuntime().exec(cmd[]),我想对特定索引使用不同的参数,例如cmd[3]=“something”或cmd[3]=“something other”。我使用for循环来实现这一点,但是对于cmd[3]的参数数组中的第一个索引,我希望它使用PrintWriter打印到一个新文件,因此在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();
}
}
public static synchronized void myMethod(字符串[]argument3,文件文件)引发IOException{
字符串[]cmd={“命令”、“参数1”、“参数2”};
PrintWriter fileWriter=null;
Scanner fileScanner=null;
int i;
对于(i=0;i<3.length;i++){
fileWriter=newprintwriter(newoutputstreamwriter(newfileoutputstream(file,true));;
cmd[3]=argument3[i];
如果(i==0){
fileWriter=新的PrintWriter(新的OutputStreamWriter(新的FileOutputStream(文件,false));
}
进程p=Runtime.getRuntime().exec(cmd);
fileScanner=newscanner(p.getInputStream());
while(fileScanner.hasNextLine()){
fileWriter.println(fileScanner.nextLine());
}
fileWriter.close();
fileScanner.close();
}
}
所有这些都很好,但在eclipse中,我收到一条警告,说我在if语句中初始化PrintWriter时发生了资源泄漏,所以我有点好奇为什么会这样,因为我在for循环的底部关闭了它们?我知道它没有太大的区别,因为它无论如何都能工作。我只是想尝试正确地清理我的代码。
提前感谢需要注意的重要事项是
throws IOException
这可以抛出,如果抛出,您的资源将不会关闭。您应该确保您的资源在任何情况下都会关闭,即使抛出异常也是如此。使用
try { ... } finally { ... close here... }
…为了这个。想象一下,当您的文件被读取时,发生了一些不好的事情。IOException被抛出,而您的close()
语句从未被调用,这将是eclipse提到的可怕的资源泄漏
我收到一条警告,说我在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();
第一次通过循环时,当该条件成立时,您将创建两个
打印作者,其中只有第二个关闭。你只是在抛弃第一个。相反,您可以这样初始化它:
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file, i != 0)));
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();
}
但这就提出了一个问题,为什么每次通过循环都要重新创建PrintWriter
?只需在循环之外创建一次
另一个问题是,如果抛出异常,则实际上不会执行任何清理代码。您需要的是一个try-catch-finally块,在这里您可以保证您的清理代码被执行。如果您至少使用Java 7,则可以使用,它将自动为您完成所有清理工作:
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());
}
}
}
}
}
void myMethod(字符串[]argument3,文件文件)引发IOException{
字符串[]cmd={“命令”、“参数1”、“参数2”};
try(PrintWriter fileWriter=新的PrintWriter(文件)){
for(int i=0;i
基本上,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
您基本上应该像这样分离元素定义:
fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file, i != 0)));
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();
}
for(i=0;i
这将删除警告
注意:如前一个答案所示,将方法移动到finally
块将被认为是最好的。使用try-catch-finally块,并在finally块中关闭扫描仪
和PrintWriter
,因为finally始终执行:
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();
}
}
公共静态同步void myMethod(字符串[]argument3,文件){
字符串[]cmd={“命令”、“参数1”、“参数2”};
PrintWriter fileWriter=null;
Scanner fileScanner=null;
试一试{
for(int i=0;i