终止Java进程时关闭BufferedReader和BufferedWriter

终止Java进程时关闭BufferedReader和BufferedWriter,java,Java,我有一个java程序,它在更新日志信息的同时读取日志信息,并将过滤后的数据写入一个新文件。当我作为一个jar执行这个程序时,它将一直运行,直到我终止这个进程 如何确保在终止此进程时关闭BufferedReader和BufferedWriter以防止内存泄漏 我曾尝试使用其他人建议的try…finally阻塞方法,但这会在程序仍在运行时关闭流。提前谢谢 FileWatcher.java import org.apache.commons.io.FileUtils; import org.apach

我有一个java程序,它在更新日志信息的同时读取日志信息,并将过滤后的数据写入一个新文件。当我作为一个jar执行这个程序时,它将一直运行,直到我终止这个进程

如何确保在终止此进程时关闭BufferedReader和BufferedWriter以防止内存泄漏

我曾尝试使用其他人建议的try…finally阻塞方法,但这会在程序仍在运行时关闭流。提前谢谢

FileWatcher.java

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*

public class FileWatcher implements Runnable
{
  boolean running = true;
  File file;
  BufferedReader reader;
  BufferedWriter writer;
  String pathToLog, pathToOutput;

  public FileWatcher(String pathToLog, String pathToOutput)
  {
    this.pathToLog = pathToLog;
    this.pathToOutput = pathToOutput;
  }

  public void run()
  {
    try
    {
      file = new File(pathToOutput);
      reader = new BufferedReader(new FileReader(pathToLog));
      writer = new BufferedWriter(new FileWriter(pathToOutput));

      if (!file.exists())
      {
        file.createNewFile();
      }
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }

    String line = null;

    System.out.println("Running...");
    while (running)
    {
      try
      {
        /* For each packet logged */
        for (int i = 0; i < 7; i++)
        {
          line = reader.readLine(); //Analyse text in line

          /* If no text then break */
          if (line == null)
          {
            break;
          }

          /* If the line begins with valid IP address then break to find Src and Dest IP */
          if (line.startsWith("192", 22))
          {
            break;
          }
        }

        /* If line is not null then filter out the Source IP and Destination IP */
        if (line != null)
        {
          int lastIndexOfSrcIP = StringUtils.ordinalIndexOf(line, ":", 3); // Position to stop reading Source IP
          int firstIndexOfDestIP = StringUtils.ordinalIndexOf(line, ">", 1) + 2; // Position to start reading Destination IP
          int lastIndexOfDestIP = StringUtils.ordinalIndexOf(line, ":", 4); // Position to stop reading Destination IP

          String sourceIP = line.substring(22, lastIndexOfSrcIP); // Source IP
          String destinationIP = line.substring(firstIndexOfDestIP, lastIndexOfDestIP); // Destination IP

          /* Check if Source IP is the IP address of the node  we are running Snort on
           * if so then don't append to malicious clients file */
          if (!(sourceIP.equals("192.168.7.5")))
          {
            //If Source IP is not in file then add it
            if (!(FileUtils.readFileToString(file).contains(sourceIP)))
            {
              writer.write(sourceIP + "\n");
              writer.flush();
            }

            System.out.println(sourceIP + "\t" + destinationIP);
          }
        }
        else
        {
          //Sleep whilst there are no new logging alert information
          try
          {
            Thread.sleep(1000);
          }
          catch (InterruptedException e)
          {
            running = false;
            writer.close();
            reader.close();
          }
        }
      }
      catch (IOException e)
      {
        e.printStackTrace();
      }
    }
  }
}

为了直接回答您的问题,我将在构造函数中创建文件,这允许您的代码快速失败,并让调用者知道这是行不通的

然后我会有一个try/finally块,它封装了所有的代码,比如

public void run() {
    try {
        run0();
    } catch(Throwable t) {
        System.err.println("Process dying");
        t.printStackTrace();
    } finally {
        // close all resources
    }
}

private void run0() throws Stuff... {
    // does the real work
}
如何确保在终止此进程时关闭BufferedReader和BufferedWriter以防止内存泄漏

当您杀死一个进程时,操作系统将回收所有进程资源,这样无论您如何编写它,都不会出现内存泄漏。唯一可以得到的资源泄漏是留下不需要的临时文件

顺便说一句

  • 当您调用FileWriter时,它将创建一个新文件或根据需要截断。没有必要检查文件是否仍然存在,因为即使它已被删除(这是极不可能的),您也不会使用刚刚创建的文件

  • 我不会在main的末尾创建一个新线程,因为这对您没有任何好处

  • 而且,如果线程是守护进程线程,我只会调用线程
    守护进程
    。给它起一个误导性的名字可能会让人困惑

如果您使用的是Java 7或更高版本,您可以使用来声明您的读卡器/写卡器,当您终止进程时,它们应该自动关闭

在您的示例中,它将如下所示:

try(reader = new BufferedReader(new FileReader(pathToLog));
    writer = new BufferedWriter(new FileWriter(pathToOutput));) {
        ...
}

使用Java 7的资源试用功能。
文件
不可关闭。感谢您的快速响应。你能解释一下不在main的末尾创建一个新线程是什么意思吗?我不太明白你的意思that@Balamory您正在用刚开始的线程替换主线程。您可以让主方法在FileWatcher中调用一个方法。
try(reader = new BufferedReader(new FileReader(pathToLog));
    writer = new BufferedWriter(new FileWriter(pathToOutput));) {
        ...
}