首页 > 解决方案 > 包装 byte[] 的 ImageInputStreamImpl 实现

问题描述

我正在尝试创建一个简单地包装一个字节 [] 的 ImageInputStream 实现。

这是我的实现,但对于某些图像 ImageIO 返回有关损坏数据的错误。

我找不到任何有用的替代方案,与 JDK 捆绑的 ImageInputStreamImpl 的每个子类都执行缓存并浪费内存。

public static class MyMemoryCacheImageInputStream extends ImageInputStreamImpl {

        private SimpleByteArrayInputStream stream;

        public MyMemoryCacheImageInputStream(SimpleByteArrayInputStream stream) {
            if (stream == null) {
                throw new IllegalArgumentException("stream == null!");
            }
            this.stream = stream;
        }

        @Override
        public int read() throws IOException {
            bitOffset = 0;
            return stream.read();
        }

        @Override
        public void seek(long pos) throws IOException {
            super.seek(pos);
            stream.seek(pos);
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException("b == null!");
            }
            if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
                throw new IndexOutOfBoundsException("off < 0 || len < 0 || off+len > b.length || off+len < 0!");
            }

            bitOffset = 0;

            if (len == 0) {
                return 0;
            }

            return stream.read(b, off, len);
        }

        @Override
        public boolean isCached() {
            return false;
        }

        @Override
        public boolean isCachedFile() {
            return false;
        }

        @Override
        public boolean isCachedMemory() {
            return false;
        }

        @Override
        public void close() throws IOException {
            super.close();
            stream = null;
        }
    }

请注意,SimpleByteArrayInputStream 本质上是一个带有“seek”方法的 ByteArrayInputStream 来修改内部流位置。

标签: javajavax.imageio

解决方案


我也面临过类似的挑战,并创建了一个在 BSD 许可下在 GitHub 上可用的实现。它不是包装 aByteArrayInputStream它直接与byte数组一起使用。

streamPos我没有测试你的实现,但我认为它的主要问题是它在阅读时没有正确更新。当您调用super.seek(pos). 以下应该可以解决问题:

@Override
public int read() throws IOException {
    bitOffset = 0;

    int val = stream.read();

    if (val != -1) {
        streamPos++;
    }

    return val;
}

@Override
public int read(byte[] b, int off, int len) throws IOException {
    if (b == null) {
        throw new NullPointerException("b == null!");
    }
    if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
        throw new IndexOutOfBoundsException("off < 0 || len < 0 || off+len > b.length || off+len < 0!");
    }

    bitOffset = 0;

    if (len == 0) {
        return 0;
    }

    int read = stream.read(b, off, len);

    if (read > 0) {
        streamPos += read;
    }

    return read;
}

我也相信,如果它确实由数组支持,那么严格isCached()来说isCachedMemory应该返回你的实现。但我认为这并不重要(即,我从未见过实际使用这些方法来优化任何东西的代码)。truebyte


推荐阅读