BufferedInputStream标记/重置无效标记

时间:2014-09-04 15:14:06

标签: java bufferedinputstream

我有2个BufferedInputStreams,它们都包含一个xml字符串:一个小字符串,一个非常大。

以下是每个xml字符串的开头如何:

<RootElement success="true">

我创建了一个方法:

  1. 在输入流的开头设置标记
  2. 读取xml的前几个字节以检查根元素是否具有特定的属性。
  3. 将输入流重置为标记位置,因此另一种方法可以享受完整的完整流。
  4. 我的印象是,缓冲输入流的缓冲区(默认为8012bytes)和标记readlimit的大小实际上都很重要,因为我只是在重置之前读取前50个字节而不管如何我的输入流很大。

    不幸的是,我得到了一个&#34; IOException: resseting to invalid mark&#34;例外。这是相关代码:

    private boolean checkXMLForSuccess(BufferedInputStream responseStream) throws XMLStreamException, FactoryConfigurationError
    {
        //Normally, this should be set to the amount of bytes that can be read before invalidating.
        //the mark. Because we use a default buffer size (1024 or 2048 bytes) that is much greater
        //than the amount of bytes we will read here (less than 100 bytes) this is not a concern.
        responseStream.mark(100);
    
        XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(responseStream);
        xmlReader.next(); //Go to the root element
    
        //This is for loop, but the root element can only have 1 attribute.
        for (int i=0; i < xmlReader.getAttributeCount(); i++)
        {
            if(xmlReader.getAttributeLocalName(i).equals(SUCCES_ATTRIBUTE))
            {
                Boolean isSuccess = Boolean.parseBoolean(xmlReader.getAttributeValue(i));
    
                if (isSuccess)
                {
                    try
                    {
                        responseStream.reset();
                    }
                    catch (IOException e)
                    {
                        //Oh oh... reset mark problem??
                    }
    
                    return true; 
                }
            }
        }
    
        return false;
    }
    

    现在,我当然尝试将标记读取限制设置为更高的数字。在最终工作之前,我必须将其设置为10000。我无法想象下面的代码需要读取10000个字节!还有哪些因素可能导致这种行为?

2 个答案:

答案 0 :(得分:1)

根据InputStream类的文档 - reset()方法:

  

public void reset()              抛出IOException

     

重置的一般合同是:   如果方法markSupported返回true,则:   如果自标记以来从流中读取的字节数   最后一次调用大于最后一次调用时标记的参数,   然后可能抛出IOException。

在您的代码中,

您已将100作为字节读取限制。

responseStream.mark(100);

并且代码部分的可能性非常高:

xmlReader.next();

读取超过100个字节,标记失效并调用reset()方法抛出IOException。

  

XMLStreamReader.next():

     

获取下一个解析事件 - 处理器可以返回所有连续的   单个块中的字符数据,或者可以将其拆分为多个   块

因此,读者可以保持读取超过读取限制字节的数量,从而导致标记无效。 (无论文件大小如何,以及连续字符是否很大,都会发生这种情况。)

第二个例子,

  

如果方法markSupported返回false,则:   对reset的调用可能会抛出IOException

但BufferedInputStream支持标记

  

public boolean markSupported()

     

测试此输入流是否支持mark和reset方法。该   bufferedInputStream的markSupported方法返回true。

所以第二种情况可以减少。

答案 1 :(得分:0)

这是一个猜测,但XMLStreamReader可能会在InputStreamgetAttributeCount方法中读取getAttributeLocalName的很大一部分,尽管它可能正在完成当创建XMLStreamReader时......

我没有通过OpenJDK代码来确认这一点。