InputStream
public abstract class InputStream implements Closeable
字节输入流的所有超类
abstract int read() 从输入流读取数据的下一个字节。 int read(byte[] b) 从输入流读取一些字节数,并将它们存储到缓冲区 b 。 int read(byte[] b, int off, int len) 从输入流读取最多 len字节的数据到一个字节数组。void close() 关闭此输入流并释放与流相关联的任何系统资源。 available() 返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 void mark(int readlimit) 标记此输入流中的当前位置。 boolean markSupported() 测试这个输入流是否支持 mark和 reset方法。 void reset() 将此流重新定位到上次在此输入流上调用 mark方法时的位置。 long skip(long n) 跳过并丢弃来自此输入流的 n字节数据。
int read(byte b[], int off, int len) off 从byte[]的off位置开始储存 len 存储多少个字节
public int read(byte b[], int off, int len) throws IOException {
int c = read(); //读取一个字节(字节)
if (c == -1) { // 没有数据 返回-1
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) { // 一个一个读取 放入byte[]中
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i; // 返回读取了多少个字节
}
long skip(long n) 跳过并丢弃来自此输入流的 n字节数据 返回 实际跳过的字节数
public long skip(long n) throws IOException {
long remaining = n; //
int nr;
if (n <= 0) { //
return 0;
}
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0) { //读取字节数
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining; //实际跳过的字节数
}
FileInputStream
class FileInputStream extends InputStream
文件输入流
构造函数
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager(); //返回null
if (security != null) {
security.checkRead(name);
}
if (file.isInvalid()) { // 地址是否无效
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor(); // 文件描述类
isFdOwner = true;
this.path = name;
BlockGuard.getThreadPolicy().onReadFromDisk();
open(name);
guard.open("close");
}
int read() b[0] & 0xff 原理 转化字节码
public int read() throws IOException {
byte[] b = new byte[1];
return (read(b, 0, 1) != -1) ? b[0] & 0xff : -1;
}
int read(byte b[], int off, int len)
public int read(byte b[], int off, int len) throws IOException {
if (closed && len > 0) {
throw new IOException("Stream Closed");
}
tracker.trackIo(len);
return IoBridge.read(fd, b, off, len); // 看不懂 获取一个一个字节
}
扩充 硬盘的读写原理
盘片表面凹凸不平,凸起的地方被磁化,凹的地方是没有被磁化;凸起的地方代表数字1(磁化为1),凹的地方代表数字0。因此硬盘可以以二进制来存储表示文字、图片等信息。
硬盘的组成
硬盘都是由盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、接口、缓存等几个部份组成
读取规则 从上到下,然后从外到内。数据的读/写按柱面进行,而不按盘面进行。
FilterInputStream
class FilterInputStream extends InputStream
包含一些其他输可入流,它用作其基本的数据源,能会沿途转换数据或提供附加功能 (装饰者模式 中装饰的基类)
InputStream in 采用装饰着模式 该类方法默认调用in 中的对应方法
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in; //
}
BufferedInputStream
public class BufferedInputStream extends FilterInputStream
BufferedInputStream为另一个输入流添加了功能,即缓冲输入和支持mark和reset方法的功能
protected byte[] buf 存储数据的内部缓冲区数组。 protected int count 索引一大于缓冲区中最后一个有效字节的索引。 protected int marklimit mark方法调用后,最大超前允许,后续调用 reset方法失败。 protected int markpos pos字段在最后一个 mark方法被调用时的值。 protected int pos 缓冲区中的当前位置。
protected volatile byte buf[]; // 字节缓存数组
protected int count; //字节的数量
protected int pos; // 下一字节读取的下标
protected int markpos = -1; //标记位置下标
protected int marklimit; //标记上限
synchronized int read()
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
fill()
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0) // 没有标记
pos = 0;
else if (pos >= buffer.length)
if (markpos > 0) { // 有标记
int sz = pos - markpos; // 从
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
} else if (buffer.length >= MAX_BUFFER_SIZE) {
throw new OutOfMemoryError("Required array size too large");
} else { //
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
pos * 2 : MAX_BUFFER_SIZE;
if (nsz > marklimit)
nsz = marklimit;
byte nbuf[] = new byte[nsz];
System.arraycopy(buffer, 0, nbuf, 0, pos);
buffer = nbuf;
}
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
}
synchronized int read(byte b[], int off, int len)
public synchronized int read(byte b[], int off, int len)
throws IOException
{
... 检测数据
int n = 0;
for (;;) {
int nread = read1(b, off + n, len - n);
if (nread <= 0)
return (n == 0) ? nread : n;
n += nread;
if (n >= len)
return n;
InputStream input = in;
if (input != null && input.available() <= 0)
return n;
}
}
int read1(byte[] b, int off, int len) 如果缓冲区有数据就从缓冲区读取 如果没有就调用fill 从流中读取
private int read1(byte[] b, int off, int len) throws IOException {
int avail = count - pos;
if (avail <= 0) {
if (len >= getBufIfOpen().length && markpos < 0) {
return getInIfOpen().read(b, off, len);
}
fill();
avail = count - pos;
if (avail <= 0) return -1;
}
int cnt = (avail < len) ? avail : len;
System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
pos += cnt;
return cnt;
}
ByteArrayInputStream
class ByteArrayInputStream extends InputStream
ByteArrayInputStream包含一个内部缓冲区,其中包含可以从流中读取的字节
protected byte[] buf 由数据流的创建者提供的字节数组。 protected int count 索引一大于输入流缓冲区中的最后一个有效字符。 protected int mark 流中当前标记的位置。 protected int pos 从输入流缓冲区读取的下一个字符的索引。
public synchronized int read()
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
synchronized int read(byte b[], int off, int len)
public synchronized int read(byte b[], int off, int len) {
if (pos >= count) {
return -1;
}
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) { return 0; }
System.arraycopy(buf, pos, b, off, len); //从本身buf里面的数据拷贝到读取的字节数组中
pos += len;
return len;
}
DataInputStream
class DataInputStream extends FilterInputStream implements DataInput
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型 ()
int read(byte[] b) 从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b 。 int read(byte[] b, int off, int len) 从包含的输入流读取最多 len个字节的数据为字节数组。 boolean readBoolean() 见的总承包 readBoolean的方法 DataInput 。 byte readByte() 见的总承包 readByte的方法 DataInput 。 char readChar() 见 readChar方法的总合同 DataInput 。 double readDouble() 见 readDouble方法 DataInput的总体合同。 float readFloat() 见 readFloat法 DataInput的一般合同。 void readFully(byte[] b) 见的总承包 readFully的方法 DataInput 。 void readFully(byte[] b, int off, int len) 见的总承包 readFully的方法 DataInput 。 int readInt() 见 readInt方法 DataInput的一般合同。 long readLong() 见的总承包 readLong的方法 DataInput 。 short readShort() 见 readShort方法 DataInput的一般合同。 int readUnsignedByte() 见的总承包 readUnsignedByte的方法 DataInput 。 int readUnsignedShort() 见 readUnsignedShort法 DataInput的一般合同。 String readUTF() 见 readUTF法 DataInput的一般合同。 static String readUTF(DataInput in) 从流in读取以modified UTF-8格式编码的Unicode字符串的表示; 这个字符串然后作为String返回。 int skipBytes(int n) 见 skipBytes法 DataInput的一般合同。
final int read(byte b[])
public final int read(byte b[]) throws IOException {
return in.read(b, 0, b.length);
}
final int read(byte b[], int off, int len)
public final int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
final int readInt()
public final int readInt() throws IOException {
// b/30268192
// Android-changed: Use read(byte[], int, int) instead of read().
readFully(readBuffer, 0, 4);
return Memory.peekInt(readBuffer, 0, ByteOrder.BIG_ENDIAN);
}
final void readFully(byte b[], int off, int len)
public final void readFully(byte b[], int off, int len) throws IOException {
if (len < 0)
throw new IndexOutOfBoundsException();
int n = 0;
while (n < len) {
int count = in.read(b, off + n, len - n);
if (count < 0)
throw new EOFException();
n += count;
}
}
final boolean readBoolean()
public final boolean readBoolean() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (ch != 0);
}
final byte readByte()
public final byte readByte() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
}