【问题标题】:Java Validator locks file on failure - what am I doing wrong?Java Validator 在失败时锁定文件 - 我做错了什么?
【发布时间】:2011-11-17 16:02:22
【问题描述】:

我正在尝试根据 Java 中的模式验证 XML 文件,问题是如果文件验证失败,则文件将被锁定,直到应用程序终止。如果输入文件有效,则文件不会被锁定,一切都很好。

我正在使用javax.xml.validation.Validatorvalidate() 方法。这看起来很简单,并且在验证通过时很好。我只能假设我在错误处理中遗漏了一些东西,但 Validator 的 API 似乎没有提供任何有用的东西。谁能解释我在这里做错了什么?

我已将所有这些简化为下面的一个独立类。如果您在扫描程序启动时运行此程序,请检查输入文件,您可以看到它现在已被锁定。如果您需要,我可以提供输入和结构文件。

谢谢,

菲尔

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.net.URI; import java.util.Scanner; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; public class ValidationTest { public static void validate(URI xmlLocation, URI schemaLocation) throws Exception { SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" ); Source schemaSource = new StreamSource(schemaLocation.toString()); Schema schema = schemaFactory.newSchema(schemaSource); Validator schemaValidator = schema.newValidator(); StreamSource source = new StreamSource(xmlLocation.getPath()); schemaValidator.validate( source ); } public static void main(String[] args) throws Exception { File srcFile = new File("c:/aaa/MySrc-Broken.xml"); File schema = new File("c:/aaa/MyStructureDefinition.xsd"); try { ValidationTest.validate(srcFile.toURI(), schema.toURI()); } catch(Exception e) { System.err.println(e); } // Use a Scanner to pause the thread, so that I can // go and check the file's permissions. Scanner scan = new Scanner(System.in); scan.nextLine(); } }

更新:

我有一点技巧,它提供了一个(坏的)解决方案。我将自定义 errorHandler 添加到 schemaValidator。此 errorHandler 仅将任何错误存储在成员变量中。这意味着验证器将始终成功,从而释放输入文件上的所有锁。但是,我必须检查错误处理程序以查看是否有任何错误,如果有则抛出错误。这不是很好,但确实让我解决了这个问题。

【问题讨论】:

  • 我也遇到过这个问题(主要是在 Windows LOL 上),我认为这是一个 JDK 错误...

标签: java xml validation


【解决方案1】:

请注意,不允许使用 StreamSource 实例。 (http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/validation/Validator.html)

URL xmlFileURL = xmlFileToCheck.toURI().toURL();
InputStream inputStream = xmlFileURL.openStream();
InputSource is = new InputSource(inputStream);
SAXSource saxSource = new SAXSource(is);

xmlValidator.validate(saxSource);

inputStream.close(); // this is probably important...

【讨论】:

  • 最新的JDK没有这个限制,但是这个bug还是存在的。您必须实例化 FileInputStream 并在异常处理程序中关闭它。 :(
【解决方案2】:

捕获您的 validate() 调用中引发的异常,关闭链接到您的文件的 StreamSource 对象以释放文件资源,然后将异常抛出给您的调用方法。

编辑:您可能需要显式检索 InputStream 以关闭底层文件句柄 - 似乎 StreamSource 没有定义关闭底层流的显式方法。检查您是否获得了 source.getInputStream() 返回的 InputStream 对象 - 如果是,关闭它应该释放文件的所有底层句柄。

【讨论】:

  • 要么是这样,要么是由 OP 错误地使用类引起的。我个人没有使用过 StreamSources,因此没有进一步的建议可提供 - 但锁定的文件等同于未发布的文件句柄,我在上面看到的唯一候选对象是 StreamSource 对象。
  • 这似乎是一个错误..."如果文件验证失败,则文件将被锁定,直到应用程序终止。如果输入文件有效,则文件不会被锁定并且一切没事。”恕我直言,文件应始终独立于结果被锁定或释放。如果我错了,请纠正我的想法
  • StreamSource 的 inputStream 为空。是的,StreamSource 没有有用的“关闭”方法。
  • @Pitelk 我完全同意!我很惊讶这种行为是这样的。顺便说一句,我在 JDK 1.6 和 1.7 上试过这个。我更愿意相信这是我糟糕的编码而不是错误。
  • 好吧,验证会根据接口抛出 IO 或 SAX 异常,这两者都没有在进行验证的方法中处理 - 所以我认为这很可能与不清理在方法。编辑:@Phil - 好的,奇怪。尝试 getReader() 看看它是否返回任何东西?您使用的是什么 XML API 提供程序?
【解决方案3】:

验证器无法关闭Source。这可能you are not supposed to use a StreamSource with the validate() method. 的唯一原因(但可能还有其他原因,因此您可能需要重新考虑您的方法。)

应用程序需要负责关闭流。为确保发生这种情况,您可以使用 finally 块。

public static void validate(URI xmlLocation, URI schemaLocation) 
  throws Exception 
{
  SchemaFactory schemaFactory = 
    SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
  InputStream sIn = schemaLocation.toURL().openStream();
  try {
    Source schemaSource = new StreamSource(sIn, schemaLocation.toString());
    Schema schema = schemaFactory.newSchema(schemaSource);
    Validator schemaValidator = schema.newValidator();
    InputStream xIn = xmlLocation.toURL().openStream();
    try {
      StreamSource source = new StreamSource(xIn, xmlLocation.toString());
      schemaValidator.validate( source );
    } finally {
      xIn.close();
    }
  } finally {
    sIn.close();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    相关资源
    最近更新 更多