ColdFusion 11 未关闭 java.io.FileInputStream

ColdFusion 11 not closing java.io.FileInputStream

我在 ColdFusion 中有一个脚本,它正在从本地 SMTP 服务器读取一些文件 .EML 并从文件中提取一些数据。

我一切正常,但有时文件会被锁定,我无法删除文件,并且在 ColdFusion 中出现以下错误。

ColdFusion could not delete the file C:/inetpub/mailroot/Queue/NTFS_AAAAAAAAAAAAAAAAAA.EML for an unknown reason.

这是我使用的代码

<cfscript>
props = createObject("java", "java.lang.System").getProperties();

props.put( javacast("string", "mail.host"), javacast("string", "localhost"));
props.put( javacast("string", "mail.transport.protocol"),  javacast("string", "smtp"));

mailSession = createObject("java", "javax.mail.Session").getDefaultInstance(props, javacast("null", ""));

fileList = directoryList('C:\inetpub\mailroot\Queue\');

for (x=1; x LTE ArrayLen(fileList); x=x+1) {
    pathToEmailFile = fileList[x];

    this.fileSource = createObject("java", "java.io.FileInputStream").init(pathToEmailFile);

    try {
        message = createObject("java", "javax.mail.internet.MimeMessage").init(mailSession, this.fileSource);

        bodyData = message.getContent();
        bodyPart = bodyData.getBodyPart(javacast("int", 0)).getContent();
        from = reMatchNoCase('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}', message.getFrom()[1].toString())[1];
        subject = message.getSubject();

        // CALL FUNCTION TO PROCESS DATA HERE
    } catch (any e) {
        // CLOSE THE FILE IF THERE IS ANY ERROR
        this.fileSource.close();
        writeDump(e);
    }
    this.fileSource.close();
    fileDelete(pathToEmailFile);
}
</cfscript>

我是不是忘了关闭其他任何东西,这就是导致文件被锁定的原因?

FileInputStream 的构造函数试图打开文件流,因此它应该是您的 try 块的一部分。提醒:如果操作的结果不在您的手中(例如文件系统、数据库和网络),请始终为失败做好准备。您还需要确保尽可能关闭文件流,无论打开后发生什么情况,以确保释放文件句柄。

这就是 finally 块的用途。无论 trycatch 块中发生什么,都会执行此块。

  • 没有异常发生? finally最后执行。
  • 出现异常,catch被执行? finally最后执行。
  • 出现异常,catch不覆盖异常? finally最后执行。
  • 出现异常,catch执行了,又抛出异常? finally最后执行。

但是,当执行 finally 时,您可能不知道关于文件流的确切情况(例如,文件流一开始就无法打开,所以您不会也可以关闭它)。因此,您仍然应该 try 关闭流。

for (x=1; x LTE ArrayLen(fileList); x=x+1) {
    pathToEmailFile = fileList[x];

    deleteFile = false;

    try {
        this.fileSource = createObject("java", "java.io.FileInputStream").init(pathToEmailFile);
        // your extraction code...
        deleteFile = true; // extraction succeeded, delete file after releasing it
    } catch (any e) {
        // log the exception
    } finally {
        // try to close the file stream
        try {
            this.fileSource.close();
        } catch (any e) {
            // file stream was probably not even opened
        }
    }

    if (deleteFile) {
        try {
            fileDelete(pathToEmailFile);
        } catch (any e) {
            // file could not be deleted, probably for the same reasons it failed previously
        }
    }
}

我不确定你是否真的打算不管提取结果如何删除文件,所以我为此添加了逻辑,你自己决定。

此外,Ageax 正确观察到:

I noticed the code uses this. scope, which might create a problem if the container is a cfc stored in a shared scope i.e. race conditions.

this 范围内有 fileSource 的原因吗?您不应该使用 public 字段(this 可以从组件外部访问)作为临时变量。