代码之家  ›  专栏  ›  技术社区  ›  ha9u63a7

使用ByteArrayInputStream进行“正确”标记/重置行为的危险/保证

  •  1
  • ha9u63a7  · 技术社区  · 7 年前

    这个问题可能是泛泛的,但我试图理解这里的主要含义。

    我正在尝试使用BCEL库进行一些字节码工程,部分工作流程要求我多次读取同一字节码文件(从一开始)。流程如下

    // 1. Get Input Stream
    
    // 2. Do some work
    
    // 3. Finish
    
    // 4. Do some other work.
    

    在第4步中,我需要重置标记或获取流,就像它是从一开始的一样。我知道以下选择。

    1) 使用包装流 BufferedInputStream -获得“重置为无效标记”IOException的机会

    2) 使用ByteArrayInputStream包装它——即使一些在线研究表明它是错误的,但它总是有效的?

    3) 只需呼叫 getInputStream() 如果我需要再次阅读流。

    我正在努力了解哪种选择对我来说更好。我不想使用BufferedInputStream,因为我不知道最后一个 mark 被召唤,所以召唤 reset 对于较高的标记位置,将导致IOException。我更喜欢使用ByteArrayInputStream,因为它对我来说需要最少的代码更改,但是有人能建议选项2还是选项3更好吗?

    我知道mark()和reset()的实现对于 ByteArrayInputStream 缓冲输入流 在JDK中。

    当做

    1 回复  |  直到 7 年前
        1
  •  3
  •   Holger    7 年前

    的问题 mark / reset 您不仅必须提前知道在这些调用之间读取的最大数据量,还必须知道您授权的代码是否会在内部使用该功能,从而使您的标记过时。代码不可能使用 做记号 / 重置 记住并恢复调用方以前的标记。

    因此,虽然可以通过将总文件大小指定为最大值来解决最大值问题 readlimit ,在通过考试时,你永远不能依靠工作分数 InputStream 对于不显式记录的任意库函数,请不要使用 做记号 / 重置 内部功能。

    此外,a BufferedInputStream 获得 读取限制 匹配总文件大小不会比 ByteArrayInputStream 包装包含整个文件的数组,因为两者最终都会保持相同大小的缓冲区。


    最好的解决方案是将整个类文件读入数组一次,然后直接使用该数组,例如,对于您控制下的代码,或者当您可以选择库(ASMs)时 ClassReader 支持使用字节数组而不是 输入流 ,例如)。

    如果你必须给一个 输入流 然后将字节数组包装到 字节数组输入流 需要时,但是 创建新的 字节数组输入流 每次都必须重新解析类文件。构建新的 字节数组输入流 成本不高,因为它是一个轻量级包装器,并且是可靠的,因为它不以任何方式依赖于旧输入流的状态。你甚至可以有多个 字节数组输入流 实例同时读取同一数组。

    使命感 getInputStream() 如果您必须处理非常大的文件,而缓冲整个内容不是一个选项,那么这也是一个选项,然而,类文件不是这样。