【问题标题】:Proper Way to exit JAVA application after flie write文件写入后退出JAVA应用程序的正确方法
【发布时间】:2016-06-05 21:16:53
【问题描述】:

**UPDATE---问题不是文件编写器没有关闭而是Java应用程序的错误终止。我已经更新了问题。

我有以下类启动 JAVAFX Web 视图并将一些 java 对象暴露给 Web 视图的 html。

public class FileSystemBridge {

private void writeToFile(String[] fileContents){

        if (content!=null){

            String fileName ="pathToFile";
            BufferedWriter fileWriter;
                for (int i =0; i<fileContents.length(); i++ ){
                    String fileContent fileContents[i]);
                    try {
                        fileName = fileName+Integer.toString(i)+".txt";
                        fileName = fileName.replaceAll("\\s","");
                        System.out.println(fileName);
                        File f= new File(filesDir+"/"+fileName);
                        f.createNewFile();
                        fileWriter = new BufferedWriter(new FileWriter(f));
                        fileWriter.write("");
                        fileWriter.write(fileContent);

                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e) {
                        System.out.println("in the exception!");
                        e.printStackTrace();
                    }
                }

        }
        else {
            System.out.println("no content");
        }
        System.out.println("done writing, exit app now");

    }

public void exit(){
    System.out.println("EXITING!");
    Platform.exit();
    System.exit(0);
}
}

上面的类还有额外的成员类,它们作为 POJOS 来暴露被读/写到“前端”html 的文件结构。

我通过覆盖默认的 Browser 类构造函数并添加以下代码,将 FileSystemBridge 的实例传递给 Web 视图。

webEngine.getLoadWorker().stateProperty().addListener(
                (ObservableValue<? extends State> ov, State oldState, 
                    State newState) -> {

                        if (newState == State.SUCCEEDED) {
                            JSObject context= (JSObject) webEngine.executeScript("window");
                            context.setMember("fsBridge", new FileSystemBridge());
                            webEngine.executeScript("init('desktop')");//the hook into our app essentially

                        }
            });

webEngine.executeScrit("init) 本质上是在我们的前端执行一些初始化。然后在用户交互的 webview 上执行的 javascript 上,我们调用 FileSystemBridge 的 write 方法和回调来调用 FileSystemBridge 的退出方法,这本质上是调用 Platform.exit()。

用户点击

App.handleWrite(contentToBeWritten, function(success){
                        if (success){
                            console.log("inside success!");
                            App.handleExit();
                        }
                    });

然后是我们的handleWrite javascript函数

handleWrite: function(content, callback){
    fsBridge.callWrite(content);
    retVal = true;//more logic to this but simplified for demo
    callBack(retVal);
}

现在在 FileSystemBridge.exit() 方法中,我添加了 System.exit(0),它成功终止了我的 java 实例,这是原来的问题。但是我想知道这是否是处理退出的正确方法使用 JAVAFX webview 的 java 应用程序。以这种方式使用 System.exit(0) 是否有不可预见的后果?

【问题讨论】:

  • 应用程序的这一部分是否带有 UI?
  • 您的程序是否打印“完成写入”行(以及之前的所有预期文件名)?你说'在命令行中它仍在等待输入' - 这让我怀疑问题不在于文件写入。
  • 这可以编译吗?例如,当 i==2 时,filename 会得到什么?主线长什么样?
  • 这是在 javaFX Web 视图中执行的,并且正在从 Web 视图 javascript 调用 write 方法。但是我已经通过 System.out.prints 验证了函数返回,程序执行终止。无论出于何种原因,尽管 java 实例没有终止
  • 您不应该在 WebView 的回调中写入文件。相反,您应该在单独的线程上启动异步Task 以执行写入操作(并确保在应用程序的stop 方法中正常关闭异步线程)。您不妨提供一个mcve,您的问题可能在别处。

标签: java io filewriter


【解决方案1】:

在满足特定条件之前,创建 UI 的 Java 应用程序不会终止。对于 JavaFX 应用程序,make sure you are closing all Stage instances.

【讨论】:

  • 这实际上可能是问题的根源,我需要进一步调查。我正在调用 Platform.exit() 但在阅读文档后,似乎如果在另一个线程正在执行时调用此方法,它可能实际上不会执行。
【解决方案2】:

我确实看到了一些陷阱,但没有真正的问题,尤其是当您处理异常时。 length() 表示您在此处简化了代码。

在新样式的路径/文件中尝试它,因为它更“原子” - 更简单。

    String fileName ="pathToFile";
    fileName = fileName.replaceAll("[\\s/\\\\]", "");
    for (int i = 0; i < fileContents.length; i++) {
        Path path = Paths.get(fileName + i + ".txt";
        byte[] bytes = ("\ufeff" + fileContents).getBytes("UTF-8");
        //Or: byte[] bytes = fileContents.getBytes();
        try {
            Files.write(path, bytes);
        } catch (IOException e) {
            System.out.println("Could not write " + path.getFileName());
        }
    }

此版本以 UTF-8 写入,并带有一个起始 BOM 字符。 BOM 很丑,但允许 Windows 识别 UTF-8。这允许特殊字符。

Files.write 可以有额外的参数列表 StandardOpenOptions.REPLACE_EXISTING。

【讨论】:

    【解决方案3】:

    如果您不能按照上一个答案将其处理成 finally 块,那么使用资源尝试如何?像这样(你需要删除之前的 fileWriter 声明):

    '

    for (int i =0; i<fileContents.length(); i++ ){
                    String fileContent fileContents[i]);
                    try {
                        fileName = fileName+Integer.toString(i)+".txt";
                        fileName = fileName.replaceAll("\\s","");
                        System.out.println(fileName);
                        File f= new File(filesDir+"/"+fileName);
                        f.createNewFile();
                        try(BufferedWriter fileWriter = new BufferedWriter(new FileWriter(f));)
                        {
    
                            fileWriter.write("");
                            fileWriter.write(fileContent);
                        }
                    } catch (IOException e) {
                        System.out.println("in the exception!");
                        e.printStackTrace();
                    }
                }
    

    '

    【讨论】:

      【解决方案4】:

      尝试将 close 放在下面的 finally 块中,看看是否有任何不同。

      try {
      } catch (Exception e) {
      } finally {
       fileWriter.close();
      }
      

      【讨论】:

      • 我无法访问 finally 子句中的引用,因为缓冲的读取器直到 for 循环内部才被初始化。
      • 根据您的代码,我认为如果有异常以及您如何打开文件写入器,它不会被关闭,因为您在 catch 块中没有 filewrite.close。此外,您应该有权访问文件编写器,因为您已在 for 循环之外声明它。
      猜你喜欢
      • 2010-09-26
      • 2016-11-12
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      • 2016-11-23
      • 1970-01-01
      • 2012-01-03
      相关资源
      最近更新 更多