Java关闭钩子并写入Excel工作表

时间:2014-06-12 14:38:59

标签: java excel apache-poi shutdown-hook

如此高级别我有一个从Excel SpreadSheet读取数据的程序将其存储在哈希映射列表中,执行圆顶操作,获取状态,然后将信息写回Excel SpreadSheet。截至目前,如果某种异常导致程序崩溃或程序正常完成,一切都很好。

现在我正在尝试处理如果用户通过按Ctrl + C终止运行的内容。我认为执行此操作的最佳方法是实现我自己的关闭挂钩。

private static class TerminationThread extends Thread
{       
    public void run() {
            for(UserCredential user : creds)
        {
            Accel.setRow(user.getMap(), user.getRowIndex());
        }

        try {
            Accel.writeToFile();
        } catch (IOException e)  {
            e.printStackTrace();
        }
    }
}

在我的Main()中,我将其注册为关闭钩子

TerminationThread sH = new TerminationThread();
Runtime.getRuntime().addShutdownHook(sH);

当程序进入关闭钩子时,一切正常,直到它到达写入文件的部分,然后它开始抛出一堆异常,最后我得到一个损坏的电子表格。

这是我的写代码:

public void writeToFile() throws IOException
{
    try 
    {
        fileOut = new FileOutputStream(theFile);
        theWorkbook.write(fileOut);
    } 
    catch (IOException e) 
    {
        throw new IOException("Exception in writeToFile(). " + e);
    }
    finally
    {
        try
        {
            fileOut.flush();
            fileOut.close();
        }
        catch(IOException e)
        {
            throw new IOException("Exception closing FileOutputStream. " + e);
        }
    }
}

我假设正在发生的事情是,处理我的Excel电子表格的对象在写入完成之前就会被删除,或者在写入数据之前存储数据的哈希映射列表将被清除。

我已经将Thread Joins视为我问题的可能解决方案,但在查看它们时,我认为它们不是我问题的解决方案。

所以我想我的问题是如何让我按照我希望的方式工作

干杯, 迈内特

编辑:这是例外

Exception in thread "Thread-4" org.apache.xmlbeans.impl.values.XmlValueDisconnectedException
    at org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1213)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.newCursor(XmlObjectBase.java:243)
    at org.apache.xmlbeans.impl.values.XmlComplexContentImpl.arraySetterHelper(XmlComplexContentImpl.java:1073)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTDefinedNamesImpl.setDefinedNameArray(Unknown Source)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.saveNamedRanges(XSSFWorkbook.java:1270)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.commit(XSSFWorkbook.java:1291)
    at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:313)
    at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:173)
    at com.cba.statuschecker.ExcelManager.writeToFile(ExcelManager.java:179)
    at com.cba.statuschecker.Main$TerminationThread.run(Main.java:495)

编辑2 :我发现了自己的问题。我正以错误的方式接近这一点。我的代码是正确的唯一问题是在我的finally块中我也有一个文件写入。因此,当我的程序在没有中断的情况下一直执行时,它将执行两次写入,这是异常的原因。我通过检查是否执行了finally块以及是否跳过了挂钩中的写入来修复此问题。

最后:

finally 
{           
    // Print out statuses
    printStatus();

    for(UserCredential user : creds)
    {
        Accel.setRow(user.getMap(), user.getRowIndex());
    }

    try {
        Accel.writeToFile();
    } catch (IOException e)  {
        e.printStackTrace();
    }

    didFinally = true;

    LOGGER.info(Log("Fin."));
    System.exit(0);
}

关机挂钩

private static class TerminationThread extends Thread
{           
    public void run() {
        System.out.println("Shutdown Initiated...");
        if(!didFinally){
            for(UserCredential user : creds)
            {
                Accel.setRow(user.getMap(), user.getRowIndex());
            }

            System.out.println("Writing to file...");
            try {
                Accel.writeToFile();
            } catch (IOException e)  {
                e.printStackTrace();
            }
        }

        System.out.println("Terminated!");
    }
}

1 个答案:

答案 0 :(得分:1)

我发现了自己的问题。我正以错误的方式接近这一点。我的代码是正确的唯一问题是在我的finally块中我也有一个文件写入。因此,当我的程序在没有中断的情况下一直执行时,它将执行两次写入,这是异常的原因。我通过检查是否执行了finally块以及是否跳过了挂钩中的写入来修复此问题。

最后:

finally 
{           
    // Print out statuses
    printStatus();

    for(UserCredential user : creds)
    {
        Accel.setRow(user.getMap(), user.getRowIndex());
    }

    try {
        Accel.writeToFile();
    } catch (IOException e)  {
        e.printStackTrace();
    }

    didFinally = true;

    LOGGER.info(Log("Fin."));
    System.exit(0);
}

关机挂钩

private static class TerminationThread extends Thread
{           
    public void run() {
        System.out.println("Shutdown Initiated...");
        if(!didFinally){
            for(UserCredential user : creds)
            {
                Accel.setRow(user.getMap(), user.getRowIndex());
            }

            System.out.println("Writing to file...");
            try {
                Accel.writeToFile();
            } catch (IOException e)  {
                e.printStackTrace();
            }
        }

        System.out.println("Terminated!");
    }
}