摘要:重要方法一个一个字节读取,放到数组中重要方法读取一个字节调用方法读取的内容调用方法声明继承自构造方法从中读取一个字节归根究底,目的是将数据放入中缓存,下次读取可以直接获取重要方法调用模板方法,由子类实现写一
1. InputStream
重要方法:
</>复制代码
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
一个一个字节读取,放到byte数组中
1.1 FileInputStream重要方法:
</>复制代码
// 读取一个字节
public int read() throws IOException {
return read0();
}
// 调用 native 方法
private native int read0() throws IOException;
</>复制代码
// 读取b.length的内容
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
// 调用 native 方法
private native int readBytes(byte b[], int off, int len) throws IOException;
1.2 BufferedInputStream
1.2.1 声明
</>复制代码
// 继承自 FilterInputStream
public class BufferedInputStream extends FilterInputStream
1.2.2 构造方法
</>复制代码
private static int DEFAULT_BUFFER_SIZE = 8192;
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
// super(in);
protected FilterInputStream(InputStream in) {
this.in = in;
}
1.2.3 read
</>复制代码
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
// 从buf中读取一个字节
return getBufIfOpen()[pos++] & 0xff;
}
private byte[] getBufIfOpen() throws IOException {
byte[] buffer = buf;
if (buffer == null)
throw new IOException("Stream closed");
return buffer;
}
</>复制代码
public synchronized int read(byte b[], int off, int len) throws IOException{
getBufIfOpen(); // Check for closed stream
if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
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;
// if not closed but no bytes available, return
InputStream input = in;
if (input != null && input.available() <= 0)
return n;
}
}
private int read1(byte[] b, int off, int len) throws IOException {
int avail = count - pos;
if (avail <= 0) {
/* If the requested length is at least as large as the buffer, and
if there is no mark/reset activity, do not bother to copy the
bytes into the local buffer. In this way buffered streams will
cascade harmlessly. */
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;
}
// 归根究底,目的是将数据放入buffer中缓存,下次读取可以直接获取
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */
else if (pos >= buffer.length) /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
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 { /* grow buffer */
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);
if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
// Can"t replace buf if there was an async close.
// Note: This would need to be changed if fill()
// is ever made accessible to multiple threads.
// But for now, the only way CAS can fail is via close.
// assert buf == null;
throw new IOException("Stream closed");
}
buffer = nbuf;
}
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
}
</>复制代码
private int read1(byte[] b, int off, int len) throws IOException {
int avail = count - pos;
if (avail <= 0) {
/* If the requested length is at least as large as the buffer, and
if there is no mark/reset activity, do not bother to copy the
bytes into the local buffer. In this way buffered streams will
cascade harmlessly. */
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;
}
2. OutputStream
重要方法:
</>复制代码
public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
for (int i = 0 ; i < len ; i++) {
// 调用模板方法,由子类实现
write(b[off + i]);
}
}
2.1 FileOutputStream
2.1.1 write
</>复制代码
// 写一个字节
public void write(int b) throws IOException {
write(b, append);
}
private native void write(int b, boolean append) throws IOException;
</>复制代码
public void write(byte b[]) throws IOException {
writeBytes(b, 0, b.length, append);
}
private native void writeBytes(byte b[], int off, int len, boolean append)
throws IOException;
</>复制代码
public void write(byte b[], int off, int len) throws IOException {
writeBytes(b, off, len, append);
}
2.2 BuffedOutputStream
2.2.1 声明
</>复制代码
public class BufferedOutputStream extends FilterOutputStream
2.2.2 constructor
</>复制代码
// 在内存中申请一个 byte[]
public BufferedOutputStream(OutputStream out) {
this(out, 8192);
}
public BufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
2.2.3 write
</>复制代码
// 写一个字节
public synchronized void write(int b) throws IOException {
if (count >= buf.length) {
flushBuffer();
}
buf[count++] = (byte)b;
}
// 调用 outputstream 的 write方法
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
count = 0;
}
}
</>复制代码
public synchronized void write(byte b[], int off, int len) throws IOException {
if (len >= buf.length) {
/* If the request length exceeds the size of the output buffer,
flush the output buffer and then write the data directly.
In this way buffered streams will cascade harmlessly. */
flushBuffer();
out.write(b, off, len);
return;
}
if (len > buf.length - count) {
flushBuffer();
}
// 首先存放到buffer内存中
System.arraycopy(b, off, buf, count, len);
count += len;
}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72254.html
任何程序都需要加载到内存才能与CPU进行交流 同理, 字节码.class文件同样需要加载到内存中,才可以实例化类 ClassLoader的使命就是提前加载.class 类文件到内存中 在加载类时,使用的是Parents Delegation Model(溯源委派加载模型) Java的类加载器是一个运行时核心基础设施模块,主要是在启动之初进行类的加载、链接、初始化 showImg(https://s...
摘要:封装了和,并且有多个优点提供超时机制不需要人工区分字节流与字符流,易于使用易于测试本文先介绍的基本用法,然后分析源码中数据读取的流程。和分别用于提供字节流和接收字节流,对应于和。和则是保存了相应的缓存数据用于高效读写。 简介 Okio 是 square 开发的一个 Java I/O 库,并且也是 OkHttp 内部使用的一个组件。Okio 封装了 java.io 和 java.nio,...
阅读 3813·2021-11-23 09:51
阅读 1486·2021-11-10 14:35
阅读 4088·2021-09-22 15:01
阅读 1390·2021-08-19 11:12
阅读 472·2019-08-30 15:53
阅读 1767·2019-08-29 13:04
阅读 3519·2019-08-29 12:52
阅读 3165·2019-08-23 16:14