【问题标题】:Why cant a RandomAccessFile be casted to Inputstream?为什么不能将 RandomAccessFile 强制转换为 Inputstream?
【发布时间】:2012-03-06 10:58:14
【问题描述】:

执行此转换时出现编译错误:

RandomAccessFile raf = new RandomAccessFile(...)
InputStream is = (InputStream)raf;

RandomAccessFile 应该是InputStream 的子类,尽管不是直接的。

来自文档:

RandomAccessFile 实现了DataInput,而DataInputstream & InputStream

为什么无效?

还感谢您对将RandomAccessFile 用作InputStream 的正确方法的意见?

我正在考虑包装方法。

【问题讨论】:

  • RandomAccessFile 的要点在于它不是流(不是顺序的)。你为什么要改变它?只需创建一个FileInputStream
  • 您的“文件缓存不受 RAF 干扰......”是什么意思?这段代码的最终目标是什么?如果您需要帮助解决问题,您需要告知详细信息。考虑查看此链接How To s The Smart Way,其中包含有关如何更轻松地回答论坛问题的重要提示。
  • @Jeffrey 好吧,那是无知的......有很多案例。例如,如果您使用来自使用InputStream 的apache commons 中的IOUtils.copyLarge,那么您将寻找您的RandomAccessFile,然后创建包装器InputStream,但同样没有理由不能RandomAccessFile 扩展InputStream ...

标签: java java-io


【解决方案1】:

RandomAccessFile 扩展 Object扩展 InputStream

如果您想从RandomAccessFile 中获得InputStream,我认为实现包装类是您最简单的选择。幸运的是InputStream 的唯一抽象方法是read()

RandomAccessFile 实现了 DataInput 从而产生 DataInputstream 和 InputStream

DataInputStreamInputStream 的子类,它也恰好实现了DataInput。继承和接口实现树如下所示:

           InputStream      DataInput
               \              /   \
                \            /     \
                 \          /       \
                DataInputStream   RandomAccessFile

您可以在任何可以使用InputStreamDataInput 的地方使用DataInputStream。您可以在任何可以使用DataInput 的地方使用RandomAccessFile

但是你不能像这样使用强制转换在继承层次结构中上下移动。特别是,将类转换为子类(或将接口转换为实现)将引发ClassCastException,除非该对象恰好是子类的实例。

尽管两个类碰巧扩展了Object,但这并不意味着它们可以互换。

【讨论】:

  • sverre,感谢您回答我的愚蠢问题。我没有正确阅读层次结构。
  • 这很容易使用 Channels 实用程序类实现... // 第 1 步:创建只读随机访问文件 RandomAccessFile raf = new RandomAccessFile("/text.txt", "r"); // STEP 2: 使用Channels转换为InputStream InputStream is = Channels.newInputStream(raf.getChannel()); (单独回答)
【解决方案2】:

RandomAccessFile 应该扩展 InputStream 虽然不是 直接。

不,不是。请参阅 Javadoc。

来自文档:

RandomAccessFile 实现 DataInput 进而实现 DataInputstream & InputStream.

这根本不是“来自文档”。你编的。你写的甚至没有意义。 DataInput 是一个接口。 DataInputStreamInputStream 是类。接口不实现或扩展类。

Javadoc 实际上说的是RandomAccessFile 扩展了java.lang.Object 并实现了Closeable, DataInput, DataOutput

【讨论】:

    【解决方案3】:

    使用 Channels 实用程序类很容易实现这一点...

    // STEP 1:  Create random access file read-only
    RandomAccessFile raf = new RandomAccessFile("/text.txt", "r");
    
    // STEP 2:  Use Channels to convert to InputStream
    InputStream is = Channels.newInputStream(raf.getChannel());
    

    【讨论】:

    • @dpg 我感觉它会在读取完成后关闭流,如果你从文件DataInput接口读取就不会这样。
    • InputStream 是否有任何类型的缓冲,如果有,该缓冲区是否在RandomAccessFile 中的位置更改后失效/刷新?
    【解决方案4】:

    以@robert-christian 的回答为基础,使用RandomAccessFile 开头的主要原因是seek 到某个位置,而不是skipping 来自FileInputStream 的字节。但是,为什么还要为 NIO 之前的 API 烦恼呢?

    try (FileChannel ch = FileChannel.open(Paths.get(…), StandardOpenOption.READ)) {
        InputStream is = Channels.newInputStream(ch.position(…));
        // …
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 2015-05-24
      • 2017-02-19
      • 2014-01-02
      • 2010-12-11
      • 2017-11-26
      • 1970-01-01
      相关资源
      最近更新 更多