java.io.FileNotFoundException:/ tmp /(打开的文件太多)

时间:2015-04-21 09:39:38

标签: java rest jax-ws jersey-2.0

我在Java EE中有一个休息服务,出于一些奇怪的向后兼容性原因,我必须在其中添加一些行后从URL请求返回.mdb文件。

首先,我只是打开一个mdb文件,清除其中的所有行,写入我的行并将其返回给调用者,但是我意识到.mdb保持这种方式增长,因为Access在删除时不会清除行但只是擦除它和我正在使用的库(Jackcess)不支持完全清除行。

所以我切换到使用java.io.File.createTempFile()创建一个空的.mdb文件的副本并返回它但是留下了一个指向/ tmp /文件夹中文件的悬空指针,几天之后我得到了一个

java.io.FileNotFoundException: /tmp/tmpdb.mdb04949499 (Too many open files)

到目前为止我找到的唯一解决方案是:

  1. 将MAX_FILE_HANDLES_FOR_READ_ENDS_MAP设置为一个非常高的数字(只会推迟问题)
  2. 删除临时文件,然而这是不可行的,因为我从函数返回它,一旦返回我失去了对指针的控制。
  3. 低于我目前的水平:

    GET
    @Path("/get/database/{filename}")
    @Produces("application/jet")
    public StreamingOutput getDatabase(@PathParam("filename") String fileName)
    {
       //access files increase indefinitely in size because deleted rows are simply marked "deleted" and not removed
       //so we create a temporary file equal to the template .mdb file and use it instead
       java.io.File myDBFile = null;
        try
        {
            java.io.File templateDBFile = new java.io.File(url + "resources/clean_tmpdb.mdb");
            myDBFile = java.io.File.createTempFile("tmpdb", ".mdb");
            myDBFile.deleteOnExit(); //useless hint
            FileChannel src = new FileInputStream(templateDBFile).getChannel();
            FileChannel dest = new FileOutputStream(myDBFile).getChannel();
            dest.transferFrom(src, 0, src.size());
        }
        catch (IOException ex)
        {
            Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
        }
    finally
        {
            if (src != null)
            {
                try
                {
                    src.close();
                }
                catch (IOException ex)
                {
                    Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            if (dest != null)
            {
                try
                {
                    dest.close();
                }
                catch (IOException ex)
                {
                    Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
    
    /* work on the file inserting rows */
    
    return new FileStreamingOutput(myDBFile);
    }
    

    编辑:发现了一个类似的问题,接受了一个模糊的答案:How to delete file after REST response,接受的答案是“直接写入Response中包含的输出流。”

1 个答案:

答案 0 :(得分:1)

您不能关闭srcdest。为确保它们已关闭,请在finally块中关闭它们,或使用try-with-resources语法。

return new FileStreamingOutput(myDBFile);
/* here I should call myDBFile.close(); and myDBFile.delete(); */

这里你无法调用myDBFile.close(),因为没有这样的方法。您也无法拨打myDBFile.delete(),否则来电者将收到不存在的File。如果需要删除File,则调用者必须执行此操作。你声明的要求没有意义。