本文目录导读:

我将为你详细解析 ImageInputStreamImpl 的基础实现,这是 Java Image I/O API 中用于读取图像数据的关键抽象类。
核心类结构
public abstract class ImageInputStreamImpl implements ImageInputStream {
// 关键成员变量
protected ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; // 默认大端序
protected long streamPosition = 0L; // 当前流位置
protected long flushedPosition = 0L; // 已刷新位置
protected int bitOffset = 0; // 位偏移量(用于位级操作)
// 关闭状态
private boolean closed = false;
// 流长度(可选)
protected long length = -1L;
}
基础实现方法
位置管理
public class ImageInputStreamImpl {
// 获取当前位置
@Override
public long getStreamPosition() {
checkClosed();
return streamPosition;
}
// 设置位置(前向seek)
@Override
public void seek(long pos) throws IOException {
checkClosed();
// 验证位置有效性
if (pos < flushedPosition) {
throw new IndexOutOfBoundsException(
"pos < flushedPosition!");
}
// 更新位置
streamPosition = pos;
bitOffset = 0; // 重置位偏移
}
// 跳过字节
@Override
public long skipBytes(long n) throws IOException {
checkClosed();
if (n < 0) {
return 0; // 不支持向后跳转
}
long newPos = streamPosition + n;
long oldPos = streamPosition;
// 如果超过文件末尾,修正位置
if (length != -1L && newPos > length) {
newPos = length;
}
streamPosition = newPos;
return streamPosition - oldPos;
}
}
字节读取方法
public class ImageInputStreamImpl {
// 读取单字节
@Override
public int read() throws IOException {
checkClosed();
bitOffset = 0;
byte[] b = new byte[1];
int result = read(b, 0, 1);
return result == -1 ? -1 : b[0] & 0xFF;
}
// 读取字节数组
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkClosed();
if (b == null) {
throw new NullPointerException("b == null!");
}
if (off < 0 || len < 0 || off + len > b.length) {
throw new IndexOutOfBoundsException();
}
if (len == 0) {
return 0;
}
bitOffset = 0;
// 需要子类实现具体的读取逻辑
return 0; // 抽象方法
}
// 读取所有剩余字节
@Override
public int readBytes(byte[] b, int off, int len) throws IOException {
int total = 0;
while (total < len) {
int count = read(b, off + total, len - total);
if (count == -1) {
break;
}
total += count;
}
return total;
}
}
位级操作
public class ImageInputStreamImpl {
// 读取指定位数
@Override
public int readBits(int numBits) throws IOException {
checkClosed();
if (numBits < 0 || numBits > 64) {
throw new IllegalArgumentException();
}
if (numBits == 0) {
return 0;
}
// 累积位缓存
long bits = 0;
int remaining = numBits;
while (remaining > 0) {
// 如果当前字节已读完,读取下一个字节
if (bitOffset == 0) {
int b = read();
if (b == -1) {
throw new EOFException();
}
savedBitCache = b;
}
// 计算可用的位数
int available = 8 - bitOffset;
int toRead = Math.min(remaining, available);
// 提取位数
int shift = available - toRead;
long value = (savedBitCache >> shift) &
((1L << toRead) - 1);
// 更新缓存
bits = (bits << toRead) | value;
bitOffset += toRead;
if (bitOffset == 8) {
bitOffset = 0;
}
remaining -= toRead;
}
return (int) bits;
}
// 设置位偏移
@Override
public void setBitOffset(int bitOffset) {
checkClosed();
if (bitOffset < 0 || bitOffset > 7) {
throw new IllegalArgumentException();
}
this.bitOffset = bitOffset;
}
}
字节顺序处理
public class ImageInputStreamImpl {
// 设置字节顺序
@Override
public void setByteOrder(ByteOrder byteOrder) {
checkClosed();
this.byteOrder = byteOrder;
}
// 获取字节顺序
@Override
public ByteOrder getByteOrder() {
checkClosed();
return byteOrder;
}
// 按当前字节顺序读取短整数
@Override
public short readShort() throws IOException {
checkClosed();
bitOffset = 0;
int b1 = read();
int b2 = read();
if (b1 == -1 || b2 == -1) {
throw new EOFException();
}
if (byteOrder == ByteOrder.BIG_ENDIAN) {
return (short) ((b1 << 8) | b2);
} else {
return (short) ((b2 << 8) | b1);
}
}
// 按当前字节顺序读取整数
@Override
public int readInt() throws IOException {
checkClosed();
bitOffset = 0;
int b1 = read();
int b2 = read();
int b3 = read();
int b4 = read();
if (b1 == -1 || b2 == -1 || b3 == -1 || b4 == -1) {
throw new EOFException();
}
if (byteOrder == ByteOrder.BIG_ENDIAN) {
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
} else {
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
}
}
流管理
public class ImageInputStreamImpl {
// 刷新(丢弃已读数据)
@Override
public void flushBefore(long pos) throws IOException {
checkClosed();
if (pos < flushedPosition) {
throw new IndexOutOfBoundsException();
}
flushedPosition = pos;
}
// 获取已刷新位置
@Override
public long getFlushedPosition() {
checkClosed();
return flushedPosition;
}
// 标记当前位置(用于reset)
@Override
public void mark() {
checkClosed();
markPosition = streamPosition;
}
// 重置到标记位置
@Override
public void reset() throws IOException {
checkClosed();
if (markPosition != -1) {
seek(markPosition);
markPosition = -1;
}
}
// 关闭流
@Override
public void close() throws IOException {
checkClosed();
closed = true;
}
// 检查是否关闭
@Override
public boolean isClosed() {
return closed;
}
// 检查流状态
private void checkClosed() {
if (closed) {
throw new IllegalStateException("Stream is closed!");
}
}
}
实用性方法
public class ImageInputStreamImpl {
// 读取无符号字节
@Override
public int readUnsignedByte() throws IOException {
return read() & 0xFF;
}
// 读取无符号短整数
@Override
public int readUnsignedShort() throws IOException {
return readShort() & 0xFFFF;
}
// 读取长整数
@Override
public long readLong() throws IOException {
int hi = readInt();
int lo = readInt();
return ((long) hi << 32) | (lo & 0xFFFFFFFFL);
}
// 读取浮点数
@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
// 读取双精度浮点数
@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
}
自定义实现示例
public class ByteArrayImageInputStream extends ImageInputStreamImpl {
private byte[] data;
private int length;
public ByteArrayImageInputStream(byte[] data) {
this.data = data;
this.length = data.length;
this.streamPosition = 0;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
checkClosed();
// 检查边界条件
if (streamPosition >= length) {
return -1; // EOF
}
// 计算实际可读字节数
int available = (int) (length - streamPosition);
int bytesToRead = Math.min(len, available);
// 复制数据
System.arraycopy(data, (int) streamPosition,
b, off, bytesToRead);
// 更新位置
streamPosition += bytesToRead;
return bytesToRead;
}
@Override
public long length() {
return length;
}
}
使用示例
public class ImageIOExample {
public static void main(String[] args) throws IOException {
// 创建自定义实现
byte[] imageData = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
ByteArrayImageInputStream input =
new ByteArrayImageInputStream(imageData);
try {
// 读取数据
input.setByteOrder(ByteOrder.BIG_ENDIAN);
// 读取一个整数值
int value = input.readInt();
System.out.println("Read value: " + value);
// 使用位操作
input.seek(0); // 回到开头
int bits = input.readBits(12);
} finally {
input.close();
}
}
}
这个基础实现提供了处理图像I/O的所有必要功能,子类只需要实现核心的 read() 方法即可,这种设计使得扩展不同的数据源变得非常简单。