IO分为磁盘IO和网络IO
IO
java.io.*包中主要包含三部分:
- 流时部分
- 非流式部分,主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类
- 其他-文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类
File&RandomAccessFile
File是对文件的抽象,提供了获取文件属性,创建、删除文件等操作,目录也是文件。
//构造File对象
public File(String pathname);
public File(File parent, String child);
public File(String parent, String child);
public File(URI uri);
//获取文件属性
public String getName();
public long length();
public boolean canExecute();
public int hashCode();
public boolean isDirectory();
public boolean exists();
.......
//文件操作
public boolean createNewFile() throws IOException;
public boolean mkdir();
public boolean delete();
public void deleteOnExit();
public boolean renameTo(File dest);
RandomAccessFile提供了随机读写文件的接口,即可用定位文件位置,然后进行读取或写入数据。
public class RandomAccessFile implements DataOutput, DataInput, Closeable {
public RandomAccessFile(String name, String mode);
public native void seek(long pos) throws IOException;
public int read() throws IOException;
public void write(byte b[]) throws IOException;
}
流
流是对数据源和数据目的地的抽象,提供数据传输操作的接口。
数据源:
- 键盘
- 内存
- 文件
- 网络
- 管道
数据目的地:
- 显示器
- 内存
- 文件
- 网络
- 管道
Java中将输入数据源抽象为输入流,输出数据目的地抽象为输出流,数据源/目的地直接作为流对象构造函数参数传入。
输入流
根据流里数据类型分为字符流和字节流,Java中字符是Unicode字符,且是UTF-16编码,字符内部也是字节,字符流一次读取多个字节然后根据Unicode码表映射成字符,因此,处理文本数据时使用字符流,其他数据则用字节流。
字节输入流InputStream
public abstract class InputStream implements Closeable {
// MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
// use when skipping.
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
// 返回读入的字节,范围0-255,无数据返回-1
public abstract int read() throws IOException;
//返回读入的字节个数,无数据返回-1代表流结束
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
//读取数据倒缓冲区
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 void close() throws IOException {}
public synchronized void mark(int readlimit) {}
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
}
InputStream主要提供read()方法一次读取一个字节,以及read(byte buf[])读取多个字符到缓冲区,此外还提供了skip/mark/reset接口进行标记重复读取数据。
字符输入流Reader
public abstract class Reader implements Readable, Closeable {
public int read() throws IOException;
public int read(char cbuf[]);
abstract public int read(char cbuf[], int off, int len) throws IOException;
public long skip(long n);
public boolean markSupported();
public void reset() throws IOException;
........
}
与InputStream提供的接口类似,只是read方法读取的是字符。
键盘
键盘抽象为字节流InputStream, java.lang.System.in常量抽象为标准输入,一般对应键盘
内存
字节输入流
字节输入流ByteArrayInputStream,继承InputStream,读取byte[]类型数据,支持skip/mark/reset操作:
public ByteArrayInputStream(byte buf[]);
public ByteArrayInputStream(byte buf[], int offset, int length);
此外Object本身也是由一连串byte组成,其成员是基本类型或Object, 因此抽象出可以从字节流中反序列化对象的ObjectInputStream,一般输入源是序列化对象时使用字节输出流ObjectOutputStream输出的数据,反序列化时再形成输入字节流作为ObjectInputStream的数据源。
public class ObjectInputStream
extends InputStream implements ObjectInput, ObjectStreamConstants {
public ObjectInputStream(InputStream in) throws IOException;
public Object readObject() throws ClassNotFoundException, IOException;
........
}
ObjectInputStream继承自ObjectInput,除了提供readObject方法外,还实现了读取Primitive类型的DataInput接口
public interface ObjectInput extends DataInput, AutoCloseable {
public Object readObject() throws ClassNotFoundException, IOException;
public int read() throws IOException;
public int read(byte b[]) throws IOException;
public int read(byte b[], int off, int len) throws IOException;
public long skip(long n) throws IOException;
public int available() throws IOException;
public void close() throws IOException;
}
public interface DataInput {
void readFully(byte b[]) throws IOException;
void readFully(byte b[], int off, int len) throws IOException;
int skipBytes(int n) throws IOException;
boolean readBoolean() throws IOException;
byte readByte() throws IOException;
int readUnsignedByte() throws IOException;
short readShort() throws IOException;
int readUnsignedShort() throws IOException;
char readChar() throws IOException;
int readInt() throws IOException;
long readLong() throws IOException;
float readFloat() throws IOException;
double readDouble() throws IOException;
String readLine() throws IOException;
String readUTF() throws IOException;
}
DataInput抽象了基本数据类型的读取
字符输入流
字符输入流CharArrayReader,继承Reader,读取char[]数据,支持skip/mark/reset:
CharArrayReader(char[] buf);
public CharArrayReader(char buf[], int offset, int length);
又有String本质也是CharArray, 为方便将String转换为流提供了StringReader:
public StringReader(String s);
文件
文件抽象为File对象,FileInputStream则是把File作为数据源的字节输入流的抽象,FileReader则是字符输入流。
FileInputStream
FileInputStream(File file);
FileInputStream(FileDescriptor fdObj);
public FileInputStream(String name) throws FileNotFoundException;
public FileChannel getChannel();
FileReader
一般读取文本文件使用FileReader,FileReader直接借助FileInputStream实现,将读取的字节流通过码表转换为字符流,InputStreamReader实现了字节到字符的转换。
public class FileReader extends InputStreamReader {
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
public FileReader(File file) throws FileNotFoundException {
super(new FileInputStream(file));
}
public FileReader(FileDescriptor fd) {
super(new FileInputStream(fd));
}
}
网络
网络传输的是字节数据,没有直接提供抽象网络流的类,而是绑定到某个Socket,通过网络套接字java.net.Socket直接获取输入/输出字节流。
class public Socket implements java.io.Closeable {
public InputStream getInputStream() throws IOException;
public OutputStream getOutputStream() throws IOException
}
管道
PipedInputStream一般连接一个PipeOutputStream, 一个线程通过PipedInputStream从PipedInputStream读取数据,另外一个线程通过PipeOutputStream写数据
public PipedInputStream(PipedOutputStream src);
public PipedInputStream(PipedOutputStream src, int pipeSize);
同样,PipedReader是基于管道的字符输入流
过滤输入流
Java中通过装饰模式为流提供了更丰富的功能,FilterInputStream是一种装饰后的InputStream,因此构造函数中需传入一个InputStream对象,并将此对象保存成成员对象,底层数据传输都是通过此对象完成。
BufferedInputStream & BufferedReader
BufferedInputStream在InputStream基础上增加了缓冲区,读取数据更加高效,默认缓冲大小为8192,因此使用InputStream读取数据时一般包装成BufferedInputStream
同理BufferedReader为Reader增加缓冲区,此外还增加了readLine()方法按行读取文本数据。
public BufferedReader(Reader in);
//读取一行,返回null时代表流结束
String readLine();
DataInputStream
DataInputStream在InputStream基础上实现DataInput接口,提供了从InputStream读取Java Primitive类型数据
输出流
与输入流相反,InputStream对应成OutputStream, Reader对应成Writer
字节输出流OutputStream
OutputStream提供了write(int b)写一个字节或write(byte b[])写多个字节
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 {
}
}
字符输出流Writer
Writer则提供了输出一个字符、字符数组和字符串的方法
public abstract class Writer implements Appendable, Closeable, Flushable {
public void write(int c) throws IOException;
public void write(char cbuf[]) throws IOException;
public void write(String str) throws IOException;
.....
}
显示器
显示器抽象为字节输出流PrintStream, java.lang.System.out/err是标准输出/错误输出对象,对应显示器。
PrintStream在OutputStream基础上增加了print/println/printf方法:
public void print(boolean b);
public void println(float x)
public PrintStream printf(String format, Object ... args);
内存
字节输出流
ByteArrayOutputStream将数据存储到byte[],因此内部维持一个byte[]缓冲区,写入数据时按翻倍的速率动态调整大小,默认大小为32.
//默认大小32
public ByteArrayOutputStream();
//指定大小
public ByteArrayOutputStream(int size);
//获取缓冲器数据
public synchronized byte[] toByteArray();
ObjectOutputStream用于将对象输出到OutputStream, 实现了ObjectOutput和DataOutput接口, 输出Object以及Primitive类型数据。
public class ObjectOutputStream
extends OutputStream implements ObjectOutput, ObjectStreamConstants {
public ObjectOutputStream(OutputStream out) throws IOException;
public final void writeObject(Object obj) throws IOException;
}
public interface ObjectOutput extends DataOutput, AutoCloseable {
public void writeObject(Object obj) throws IOException;
public void write(int b) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
public void flush() throws IOException;
public void close() throws IOException;
}
public interface DataOutput {
void write(int b) throws IOException;
void write(byte b[]) throws IOException;
void write(byte b[], int off, int len) throws IOException;
void writeBoolean(boolean v) throws IOException;
void writeByte(int v) throws IOException;
void writeShort(int v) throws IOException;
void writeChar(int v) throws IOException;
void writeInt(int v) throws IOException;
void writeLong(long v) throws IOException;
void writeFloat(float v) throws IOException;
void writeDouble(double v) throws IOException;
void writeBytes(String s) throws IOException;
void writeChars(String s) throws IOException;
void writeUTF(String s) throws IOException;
}
字符输出流
CharArrayWriter将字符流输出到char[]缓冲中,char[]也会动态扩容
public CharArrayWriter();
public CharArrayWriter(int initialSize);
public char[] toCharArray();
StringWriter内部使用StringBuffer保存流输出数据
public StringWriter();
public StringWriter(int initialSize);
public StringBuffer getBuffer();
文件
FileOutputStream
FileOutputStream输出字节数据到File
public FileOutputStream(File file) throws FileNotFoundException;
public FileOutputStream(File file, boolean append);
public FileOutputStream(String name) throws FileNotFoundException;
public FileOutputStream(String name, boolean append);
FileWriter
FileWriter借助FileOutputStream实现,继承自OutputStreamWriter,OutputStreamWriter实现了将字符流转换为字节流,然后输出的功能.
public class FileWriter extends OutputStreamWriter {
public FileWriter(String fileName) throws IOException {
super(new FileOutputStream(fileName));
}
public FileWriter(String fileName, boolean append) throws IOException {
super(new FileOutputStream(fileName, append));
}
public FileWriter(File file) throws IOException {
super(new FileOutputStream(file));
}
public FileWriter(File file, boolean append) throws IOException {
super(new FileOutputStream(file, append));
}
public FileWriter(FileDescriptor fd) {
super(new FileOutputStream(fd));
}
}
网络
数据输出到网络,直接通过java.net.Socket.getOutputStream()获取字节流数据数据倒Socket.
管道
PipeOutputStream一般连接一个PipeInputStream, PipeReader连接一个PipeWriter.
过滤输出流
FilterOutputStream用例装饰OutputStream,构造函数中需传入一个OutputStream对象,并将此对象保存成成员对象。
BufferedOutputStream & BufferedWriter
BufferedOutputStreamm在Outputstream基础上增加了缓冲区,使用Outputstream输出数据时一般包装成BufferedOutputStream
BufferedWriter为Writer增加缓冲区,此外增加了newLine()方法输出换行符。
public BufferedWriter(Writer out);
public void newLine() throws IOException;
DataOutputStream
DataOutputStream实现了DataOutput,在底层OutputStream基础上增加了输出输出原生类型的方法。