文章目录
字节流InputStreamFilterInputStreamByteArrayInputStream//todo FileInputStreamBufferInputStreamPipedInputStream//todo ObjectInputStream
OutputStream//todo FileOutputStreamBufferedOutputStreamPipedOutputStream//todo ObjectOutputStream
字符流Reader//todo FileReaderBufferedReader
Writer//todo FileWriter//todo BufferWriter
转换流//todo InputStreamReader//todo OutputStreamWriter
字节流
InputStream
public abstract class InputStream implements Closeable {
private static final int MAX_SKIP_BUFFER_SIZE
= 2048;
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
;
}
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
;
}
public int available() throws IOException
{
return 0;
}
public synchronized void mark(int readlimit
) {}
public synchronized void reset() throws IOException
{
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
FilterInputStream
public class FilterInputStream extends InputStream {
protected volatile InputStream in
;
protected FilterInputStream(InputStream in
) {
this.in
= in
;
}
public int read() throws IOException
{
return in
.read();
}
public int read(byte b
[]) throws IOException
{
return read(b
, 0, b
.length
);
}
public int read(byte b
[], int off
, int len
) throws IOException
{
return in
.read(b
, off
, len
);
}
public long skip(long n
) throws IOException
{
return in
.skip(n
);
}
public int available() throws IOException
{
return in
.available();
}
public void close() throws IOException
{
in
.close();
}
public synchronized void mark(int readlimit
) {
in
.mark(readlimit
);
}
public synchronized void reset() throws IOException
{
in
.reset();
}
public boolean markSupported() {
return in
.markSupported();
}
}
ByteArrayInputStream
将内存中的数组装饰成InputStrean
public
class ByteArrayInputStream extends InputStream {
protected byte buf
[];
protected int pos
;
protected int mark
= 0;
protected int count
;
public ByteArrayInputStream(byte buf
[]) {
this.buf
= buf
;
this.pos
= 0;
this.count
= buf
.length
;
}
public ByteArrayInputStream(byte buf
[], int offset
, int length
) {
this.buf
= buf
;
this.pos
= offset
;
this.count
= Math
.min(offset
+ length
, buf
.length
);
this.mark
= offset
;
}
public synchronized int read() {
return (pos
< count
) ? (buf
[pos
++] & 0xff) : -1;
}
public synchronized int read(byte b
[], int off
, int len
) {
if (b
== null
) {
throw new NullPointerException();
} else if (off
< 0 || len
< 0 || len
> b
.length
- off
) {
throw new IndexOutOfBoundsException();
}
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
);
pos
+= len
;
return len
;
}
public synchronized long skip(long n
) {
long k
= count
- pos
;
if (n
< k
) {
k
= n
< 0 ? 0 : n
;
}
pos
+= k
;
return k
;
}
public synchronized int available() {
return count
- pos
;
}
public boolean markSupported() {
return true;
}
public void mark(int readAheadLimit
) {
mark
= pos
;
}
public synchronized void reset() {
pos
= mark
;
}
public void close() throws IOException
{
}
}
//todo FileInputStream
BufferInputStream
public
class BufferedInputStream extends FilterInputStream {
private static int DEFAULT_BUFFER_SIZE
= 8192;
private static int MAX_BUFFER_SIZE
= Integer
.MAX_VALUE
- 8;
protected volatile byte buf
[];
private static final
AtomicReferenceFieldUpdater
<BufferedInputStream
, byte[]> bufUpdater
=
AtomicReferenceFieldUpdater
.newUpdater
(BufferedInputStream
.class, byte[].class, "buf");
protected int count
;
protected int pos
;
protected int markpos
= -1;
protected int marklimit
;
private InputStream
getInIfOpen() throws IOException
{
InputStream input
= in
;
if (input
== null
)
throw new IOException("Stream closed");
return input
;
}
private byte[] getBufIfOpen() throws IOException
{
byte[] buffer
= buf
;
if (buffer
== null
)
throw new IOException("Stream closed");
return buffer
;
}
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
];
}
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;
pos
= 0;
} 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
);
if (!bufUpdater
.compareAndSet(this, buffer
, nbuf
)) {
throw new IOException("Stream closed");
}
buffer
= nbuf
;
}
count
= pos
;
int n
= getInIfOpen().read(buffer
, pos
, buffer
.length
- pos
);
if (n
> 0)
count
= n
+ pos
;
}
public synchronized int read() throws IOException
{
if (pos
>= count
) {
fill();
if (pos
>= count
)
return -1;
}
return getBufIfOpen()[pos
++] & 0xff;
}
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
;
}
public synchronized int read(byte b
[], int off
, int len
)
throws IOException
{
getBufIfOpen();
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
;
InputStream input
= in
;
if (input
!= null
&& input
.available() <= 0)
return n
;
}
}
public synchronized long skip(long n
) throws IOException
{
getBufIfOpen();
if (n
<= 0) {
return 0;
}
long avail
= count
- pos
;
if (avail
<= 0) {
if (markpos
<0)
return getInIfOpen().skip(n
);
fill();
avail
= count
- pos
;
if (avail
<= 0)
return 0;
}
long skipped
= (avail
< n
) ? avail
: n
;
pos
+= skipped
;
return skipped
;
}
public synchronized int available() throws IOException
{
int n
= count
- pos
;
int avail
= getInIfOpen().available();
return n
> (Integer
.MAX_VALUE
- avail
)
? Integer
.MAX_VALUE
: n
+ avail
;
}
public synchronized void mark(int readlimit
) {
marklimit
= readlimit
;
markpos
= pos
;
}
public synchronized void reset() throws IOException
{
getBufIfOpen();
if (markpos
< 0)
throw new IOException("Resetting to invalid mark");
pos
= markpos
;
}
public boolean markSupported() {
return true;
}
public void close() throws IOException
{
byte[] buffer
;
while ( (buffer
= buf
) != null
) {
if (bufUpdater
.compareAndSet(this, buffer
, null
)) {
InputStream input
= in
;
in
= null
;
if (input
!= null
)
input
.close();
return;
}
}
}
}
PipedInputStream
public class PipedInputStream extends InputStream {
boolean closedByWriter
= false;
volatile boolean closedByReader
= false;
boolean connected
= false;
Thread readSide
;
Thread writeSide
;
private static final int DEFAULT_PIPE_SIZE
= 1024;
protected static final int PIPE_SIZE
= DEFAULT_PIPE_SIZE
;
protected byte buffer
[];
protected int in
= -1;
protected int out
= 0;
public PipedInputStream(PipedOutputStream src
) throws IOException
{
this(src
, DEFAULT_PIPE_SIZE
);
}
public PipedInputStream(PipedOutputStream src
, int pipeSize
)
throws IOException
{
initPipe(pipeSize
);
connect(src
);
}
public PipedInputStream() {
initPipe(DEFAULT_PIPE_SIZE
);
}
public PipedInputStream(int pipeSize
) {
initPipe(pipeSize
);
}
private void initPipe(int pipeSize
) {
if (pipeSize
<= 0) {
throw new IllegalArgumentException("Pipe Size <= 0");
}
buffer
= new byte[pipeSize
];
}
public void connect(PipedOutputStream src
) throws IOException
{
src
.connect(this);
}
protected synchronized void receive(int b
) throws IOException
{
checkStateForReceive();
writeSide
= Thread
.currentThread();
if (in
== out
)
awaitSpace();
if (in
< 0) {
in
= 0;
out
= 0;
}
buffer
[in
++] = (byte)(b
& 0xFF);
if (in
>= buffer
.length
) {
in
= 0;
}
}
synchronized void receive(byte b
[], int off
, int len
) throws IOException
{
checkStateForReceive();
writeSide
= Thread
.currentThread();
int bytesToTransfer
= len
;
while (bytesToTransfer
> 0) {
if (in
== out
)
awaitSpace();
int nextTransferAmount
= 0;
if (out
< in
) {
nextTransferAmount
= buffer
.length
- in
;
} else if (in
< out
) {
if (in
== -1) {
in
= out
= 0;
nextTransferAmount
= buffer
.length
- in
;
} else {
nextTransferAmount
= out
- in
;
}
}
if (nextTransferAmount
> bytesToTransfer
)
nextTransferAmount
= bytesToTransfer
;
assert(nextTransferAmount
> 0);
System
.arraycopy(b
, off
, buffer
, in
, nextTransferAmount
);
bytesToTransfer
-= nextTransferAmount
;
off
+= nextTransferAmount
;
in
+= nextTransferAmount
;
if (in
>= buffer
.length
) {
in
= 0;
}
}
}
private void checkStateForReceive() throws IOException
{
if (!connected
) {
throw new IOException("Pipe not connected");
} else if (closedByWriter
|| closedByReader
) {
throw new IOException("Pipe closed");
} else if (readSide
!= null
&& !readSide
.isAlive()) {
throw new IOException("Read end dead");
}
}
private void awaitSpace() throws IOException
{
while (in
== out
) {
checkStateForReceive();
notifyAll();
try {
wait(1000);
} catch (InterruptedException ex
) {
throw new java.io.InterruptedIOException();
}
}
}
synchronized void receivedLast() {
closedByWriter
= true;
notifyAll();
}
public synchronized int read() throws IOException
{
if (!connected
) {
throw new IOException("Pipe not connected");
} else if (closedByReader
) {
throw new IOException("Pipe closed");
} else if (writeSide
!= null
&& !writeSide
.isAlive()
&& !closedByWriter
&& (in
< 0)) {
throw new IOException("Write end dead");
}
readSide
= Thread
.currentThread();
int trials
= 2;
while (in
< 0) {
if (closedByWriter
) {
return -1;
}
if ((writeSide
!= null
) && (!writeSide
.isAlive()) && (--trials
< 0)) {
throw new IOException("Pipe broken");
}
notifyAll();
try {
wait(1000);
} catch (InterruptedException ex
) {
throw new java.io.InterruptedIOException();
}
}
int ret
= buffer
[out
++] & 0xFF;
if (out
>= buffer
.length
) {
out
= 0;
}
if (in
== out
) {
in
= -1;
}
return ret
;
}
public synchronized 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
< 0) {
return -1;
}
b
[off
] = (byte) c
;
int rlen
= 1;
while ((in
>= 0) && (len
> 1)) {
int available
;
if (in
> out
) {
available
= Math
.min((buffer
.length
- out
), (in
- out
));
} else {
available
= buffer
.length
- out
;
}
if (available
> (len
- 1)) {
available
= len
- 1;
}
System
.arraycopy(buffer
, out
, b
, off
+ rlen
, available
);
out
+= available
;
rlen
+= available
;
len
-= available
;
if (out
>= buffer
.length
) {
out
= 0;
}
if (in
== out
) {
in
= -1;
}
}
return rlen
;
}
public synchronized int available() throws IOException
{
if(in
< 0)
return 0;
else if(in
== out
)
return buffer
.length
;
else if (in
> out
)
return in
- out
;
else
return in
+ buffer
.length
- out
;
}
public void close() throws IOException
{
closedByReader
= true;
synchronized (this) {
in
= -1;
}
}
}
//todo ObjectInputStream
OutputStream
public abstract class OutputStream implements Closeable, Flushable
{
public abstract void write(int b
) throws IOException
;
public void write(byte b
[]) throws IOException
{
write(b
, 0, b
.length
);
}
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
]);
}
}
public void flush() throws IOException
{
}
public void close() throws IOException
{
}
}
//todo FileOutputStream
BufferedOutputStream
Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力。所以管道也可以作为数据源以及目标媒介
public
class BufferedOutputStream extends FilterOutputStream {
protected byte buf
[];
protected int count
;
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
];
}
private void flushBuffer() throws IOException
{
if (count
> 0) {
out
.write(buf
, 0, count
);
count
= 0;
}
}
public synchronized void write(int b
) throws IOException
{
if (count
>= buf
.length
) {
flushBuffer();
}
buf
[count
++] = (byte)b
;
}
public synchronized void write(byte b
[], int off
, int len
) throws IOException
{
if (len
>= buf
.length
) {
flushBuffer();
out
.write(b
, off
, len
);
return;
}
if (len
> buf
.length
- count
) {
flushBuffer();
}
System
.arraycopy(b
, off
, buf
, count
, len
);
count
+= len
;
}
public synchronized void flush() throws IOException
{
flushBuffer();
out
.flush();
}
}
PipedOutputStream
public
class PipedOutputStream extends OutputStream {
private PipedInputStream sink
;
public PipedOutputStream(PipedInputStream snk
) throws IOException
{
connect(snk
);
}
public PipedOutputStream() {
}
public synchronized void connect(PipedInputStream snk
) throws IOException
{
if (snk
== null
) {
throw new NullPointerException();
} else if (sink
!= null
|| snk
.connected
) {
throw new IOException("Already connected");
}
sink
= snk
;
snk
.in
= -1;
snk
.out
= 0;
snk
.connected
= true;
}
public void write(int b
) throws IOException
{
if (sink
== null
) {
throw new IOException("Pipe not connected");
}
sink
.receive(b
);
}
public void write(byte b
[], int off
, int len
) throws IOException
{
if (sink
== null
) {
throw new IOException("Pipe not connected");
} else 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;
}
sink
.receive(b
, off
, len
);
}
public synchronized void flush() throws IOException
{
if (sink
!= null
) {
synchronized (sink
) {
sink
.notifyAll();
}
}
}
public void close() throws IOException
{
if (sink
!= null
) {
sink
.receivedLast();
}
}
}
//todo ObjectOutputStream
字符流
Reader
public abstract class Reader implements Readable, Closeable
{
protected Object lock
;
protected Reader() {
this.lock
= this;
}
protected Reader(Object lock
) {
if (lock
== null
) {
throw new NullPointerException();
}
this.lock
= lock
;
}
public int read(java
.nio
.CharBuffer target
) throws IOException
{
int len
= target
.remaining();
char[] cbuf
= new char[len
];
int n
= read(cbuf
, 0, len
);
if (n
> 0)
target
.put(cbuf
, 0, n
);
return n
;
}
public int read() throws IOException
{
char cb
[] = new char[1];
if (read(cb
, 0, 1) == -1)
return -1;
else
return cb
[0];
}
public int read(char cbuf
[]) throws IOException
{
return read(cbuf
, 0, cbuf
.length
);
}
abstract public int read(char cbuf
[], int off
, int len
) throws IOException
;
private static final int maxSkipBufferSize
= 8192;
private char skipBuffer
[] = null
;
public long skip(long n
) throws IOException
{
if (n
< 0L
)
throw new IllegalArgumentException("skip value is negative");
int nn
= (int) Math
.min(n
, maxSkipBufferSize
);
synchronized (lock
) {
if ((skipBuffer
== null
) || (skipBuffer
.length
< nn
))
skipBuffer
= new char[nn
];
long r
= n
;
while (r
> 0) {
int nc
= read(skipBuffer
, 0, (int)Math
.min(r
, nn
));
if (nc
== -1)
break;
r
-= nc
;
}
return n
- r
;
}
}
public boolean ready() throws IOException
{
return false;
}
public boolean markSupported() {
return false;
}
public void mark(int readAheadLimit
) throws IOException
{
throw new IOException("mark() not supported");
}
public void reset() throws IOException
{
throw new IOException("reset() not supported");
}
abstract public void close() throws IOException
;
}
//todo FileReader
BufferedReader
public class BufferedReader extends Reader {
private Reader in
;
private char cb
[];
private int nChars
,
nextChar
;
private static final int INVALIDATED
= -2;
private static final int UNMARKED
= -1;
private int markedChar
= UNMARKED
;
private int readAheadLimit
= 0;
private boolean skipLF
= false;
private boolean markedSkipLF
= false;
private static int defaultCharBufferSize
= 8192;
private static int defaultExpectedLineLength
= 80;
public BufferedReader(Reader in
, int sz
) {
super(in
);
if (sz
<= 0)
throw new IllegalArgumentException("Buffer size <= 0");
this.in
= in
;
cb
= new char[sz
];
nextChar
= nChars
= 0;
}
public BufferedReader(Reader in
) {
this(in
, defaultCharBufferSize
);
}
private void ensureOpen() throws IOException
{
if (in
== null
)
throw new IOException("Stream closed");
}
private void fill() throws IOException
{
int dst
;
if (markedChar
<= UNMARKED
) {
dst
= 0;
} else {
int delta
= nextChar
- markedChar
;
if (delta
>= readAheadLimit
) {
markedChar
= INVALIDATED
;
readAheadLimit
= 0;
dst
= 0;
} else {
if (readAheadLimit
<= cb
.length
) {
System
.arraycopy(cb
, markedChar
, cb
, 0, delta
);
markedChar
= 0;
dst
= delta
;
} else {
char ncb
[] = new char[readAheadLimit
];
System
.arraycopy(cb
, markedChar
, ncb
, 0, delta
);
cb
= ncb
;
markedChar
= 0;
dst
= delta
;
}
nextChar
= nChars
= delta
;
}
}
int n
;
do {
n
= in
.read(cb
, dst
, cb
.length
- dst
);
} while (n
== 0);
if (n
> 0) {
nChars
= dst
+ n
;
nextChar
= dst
;
}
}
public int read() throws IOException
{
synchronized (lock
) {
ensureOpen();
for (;;) {
if (nextChar
>= nChars
) {
fill();
if (nextChar
>= nChars
)
return -1;
}
if (skipLF
) {
skipLF
= false;
if (cb
[nextChar
] == '\n') {
nextChar
++;
continue;
}
}
return cb
[nextChar
++];
}
}
}
private int read1(char[] cbuf
, int off
, int len
) throws IOException
{
if (nextChar
>= nChars
) {
if (len
>= cb
.length
&& markedChar
<= UNMARKED
&& !skipLF
) {
return in
.read(cbuf
, off
, len
);
}
fill();
}
if (nextChar
>= nChars
) return -1;
if (skipLF
) {
skipLF
= false;
if (cb
[nextChar
] == '\n') {
nextChar
++;
if (nextChar
>= nChars
)
fill();
if (nextChar
>= nChars
)
return -1;
}
}
int n
= Math
.min(len
, nChars
- nextChar
);
System
.arraycopy(cb
, nextChar
, cbuf
, off
, n
);
nextChar
+= n
;
return n
;
}
public int read(char cbuf
[], int off
, int len
) throws IOException
{
synchronized (lock
) {
ensureOpen();
if ((off
< 0) || (off
> cbuf
.length
) || (len
< 0) ||
((off
+ len
) > cbuf
.length
) || ((off
+ len
) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len
== 0) {
return 0;
}
int n
= read1(cbuf
, off
, len
);
if (n
<= 0) return n
;
while ((n
< len
) && in
.ready()) {
int n1
= read1(cbuf
, off
+ n
, len
- n
);
if (n1
<= 0) break;
n
+= n1
;
}
return n
;
}
}
String
readLine(boolean ignoreLF
) throws IOException
{
StringBuffer s
= null
;
int startChar
;
synchronized (lock
) {
ensureOpen();
boolean omitLF
= ignoreLF
|| skipLF
;
bufferLoop
:
for (;;) {
if (nextChar
>= nChars
)
fill();
if (nextChar
>= nChars
) {
if (s
!= null
&& s
.length() > 0)
return s
.toString();
else
return null
;
}
boolean eol
= false;
char c
= 0;
int i
;
if (omitLF
&& (cb
[nextChar
] == '\n'))
nextChar
++;
skipLF
= false;
omitLF
= false;
charLoop
:
for (i
= nextChar
; i
< nChars
; i
++) {
c
= cb
[i
];
if ((c
== '\n') || (c
== '\r')) {
eol
= true;
break charLoop
;
}
}
startChar
= nextChar
;
nextChar
= i
;
if (eol
) {
String str
;
if (s
== null
) {
str
= new String(cb
, startChar
, i
- startChar
);
} else {
s
.append(cb
, startChar
, i
- startChar
);
str
= s
.toString();
}
nextChar
++;
if (c
== '\r') {
skipLF
= true;
}
return str
;
}
if (s
== null
)
s
= new StringBuffer(defaultExpectedLineLength
);
s
.append(cb
, startChar
, i
- startChar
);
}
}
}
public String
readLine() throws IOException
{
return readLine(false);
}
public long skip(long n
) throws IOException
{
if (n
< 0L
) {
throw new IllegalArgumentException("skip value is negative");
}
synchronized (lock
) {
ensureOpen();
long r
= n
;
while (r
> 0) {
if (nextChar
>= nChars
)
fill();
if (nextChar
>= nChars
)
break;
if (skipLF
) {
skipLF
= false;
if (cb
[nextChar
] == '\n') {
nextChar
++;
}
}
long d
= nChars
- nextChar
;
if (r
<= d
) {
nextChar
+= r
;
r
= 0;
break;
}
else {
r
-= d
;
nextChar
= nChars
;
}
}
return n
- r
;
}
}
public boolean ready() throws IOException
{
synchronized (lock
) {
ensureOpen();
if (skipLF
) {
if (nextChar
>= nChars
&& in
.ready()) {
fill();
}
if (nextChar
< nChars
) {
if (cb
[nextChar
] == '\n')
nextChar
++;
skipLF
= false;
}
}
return (nextChar
< nChars
) || in
.ready();
}
}
public boolean markSupported() {
return true;
}
public void mark(int readAheadLimit
) throws IOException
{
if (readAheadLimit
< 0) {
throw new IllegalArgumentException("Read-ahead limit < 0");
}
synchronized (lock
) {
ensureOpen();
this.readAheadLimit
= readAheadLimit
;
markedChar
= nextChar
;
markedSkipLF
= skipLF
;
}
}
public void reset() throws IOException
{
synchronized (lock
) {
ensureOpen();
if (markedChar
< 0)
throw new IOException((markedChar
== INVALIDATED
)
? "Mark invalid"
: "Stream not marked");
nextChar
= markedChar
;
skipLF
= markedSkipLF
;
}
}
public void close() throws IOException
{
synchronized (lock
) {
if (in
== null
)
return;
try {
in
.close();
} finally {
in
= null
;
cb
= null
;
}
}
}
public Stream
<String> lines() {
Iterator
<String> iter
= new Iterator<String>() {
String nextLine
= null
;
@Override
public boolean hasNext() {
if (nextLine
!= null
) {
return true;
} else {
try {
nextLine
= readLine();
return (nextLine
!= null
);
} catch (IOException e
) {
throw new UncheckedIOException(e
);
}
}
}
@Override
public String
next() {
if (nextLine
!= null
|| hasNext()) {
String line
= nextLine
;
nextLine
= null
;
return line
;
} else {
throw new NoSuchElementException();
}
}
};
return StreamSupport
.stream(Spliterators
.spliteratorUnknownSize(
iter
, Spliterator
.ORDERED
| Spliterator
.NONNULL
), false);
}
}
Writer
//todo FileWriter
//todo BufferWriter
转换流
//todo InputStreamReader
//todo OutputStreamWriter