一、IO流类图结构
二、字节流
1、输入字节流 InputStream
OutputStream
是所有的输出字节流的父类,它是一个抽象类。ByteArrayInputStream
、StringBufferInputStream
、FileInputStream
是三种基本的介质流,它们分别从Byte 数组
、StringBuffer
、和本地文件
中读取数据。PipedInputStream
是从与其它线程共用的管道中读取数据ObjectInputStream
和所有FilterInputStream
的子类都是装饰流(装饰器模式的主角)
2、输出字节流 OutputStream
OutputStream
是所有的输出字节流的父类,它是一个抽象类。ByteArrayOutputStream
、FileOutputStream
是两种基本的介质流,它们分别向Byte 数组
、和本地文件
中写入数据。PipedOutputStream
是向与其它线程共用的管道中写入数据。ObjectOutputStream
和所有FilterOutputStream
的子类都是装饰流。
三、常用节点流
节点流:直接与数据源相连,读入或读出。
- 父 类 :
InputStream
、OutputStream
、Reader
、Writer
- 文 件 :
FileInputStream
、FileOutputStrean
、FileReader
、FileWriter
文件进行处理的节点流 - 数 组 :
ByteArrayInputStream
、ByteArrayOutputStream
、CharArrayReader
、CharArrayWriter
对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组) - 字符串 :
StringReader
、StringWriter
对字符串进行处理的节点流 - 管 道 :
PipedInputStream
、PipedOutputStream
、PipedReader
、PipedWriter
对管道进行处理的节点
四、常用的处理流
处理流:处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。如BufferedReader
.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
- 缓冲流:
BufferedInputStrean
、BufferedOutputStream
、BufferedReader
、BufferedWriter
增加缓冲功能,避免频繁读写硬盘。 - 转换流:
InputStreamReader
、OutputStreamReader
实现字节流和字符流之间的转换。 - 数据流:
DataInputStream
、DataOutputStream
等-提供将基础数据类型写入到文件中,或者读取出来。
五、字节流常用方法说明及举例
1、FileInputStream / FileOutputStream
(1)构造方法
FileInputStream public FileInputStream(File file) //通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 public FileInputStream(String name) //通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。FileOutputStream public FileOutputStream(File file) //通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 public FileOutputStream(String name) //通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
(2)常用方法
FileInputStream public abstract int read() throws IOException: //一次读取一个字节; 返回:下一个数据字节;如果已到达文件末尾,则返回 -1。 public int read(byte[] b) throws IOException: //一次读取一个字节数组 (读取实际的字节数) 指定字节数组的长度是:1024或者1024的倍数 ;返回:读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。 public void close() throws IOException //关闭此文件输入流并释放与此流有关的所有系统资源。FileInputStream public void write(int b) throws IOException: //一次写一个字节 b- 要写入的字节。 public int write(byte[] b) throws IOException: //一次写一个字节数组 public void close() throws IOException //关闭此文件输入流并释放与此流有关的所有系统资源。
(3) 举例
public class FileInputStreamDemo { public void demo() throws Exception{ FileInputStream fis = new FileInputStream("fis.txt") ; int by = 0 ; while((by=fis.read())!=-1) { System.out.print((char)by); } fis.close(); }}public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("fos.txt") ; //FileNotFoundException // 使用流对象给文件中写入数据 fos.write("hello".getBytes()); //关闭资源 /** * 1)将文件和流对象不建立关系了 (fos对象不指向fos.txt) * 2)及时释放掉流对象所占用的内存空间 */ fos.close(); /** * 如果关闭流对象了,那么就不能对流对象进行操作了 */ }}//使用FileInputStream和FileOutputStream实现文件的复制import java.io.FileInputStream; import java.io.FileOutputStream; /** * 使用文件输入流和文件输出流实现文件的复制 * @author Administrator * */ public class SummaryFISAndFOS { public static void main(String[] args){ /** * 1.先将文件中的内容读入到输入流中 * 2.将输入流中的数据通过输出流写入到目标文件中 * 3.关闭输入流和输出流 */ try { long begin=System.currentTimeMillis(); //从输入流中读取数据 FileInputStream fis=new FileInputStream("FOSDemo.txt"); //向输出流中写入数据 FileOutputStream fos=new FileOutputStream("FISAndFOSDest.txt"); //先定义一个字节缓冲区,减少I/O次数,提高读写效率 byte[] buffer=new byte[10240]; int size=0; while((size=fis.read(buffer))!=-1){ f os.write(buffer, 0, size); } fis.close(); fos.close(); long end=System.currentTimeMillis(); System.out.println("使用文件输入流和文件输出流实现文件的复制完毕!耗时:"+(end-begin)+"毫秒"); } catch (Exception e) { e.printStackTrace(); } //解决JNI问题(Java Native Interface) System.exit(0); } }
2、FilterInputStream/FilterOutputStream (装饰模式、过滤字节流) 装饰模式说明链接:
FilterInputStream 构造方法: protected FilterInputStream(InputStream in)
1)、 FilterInputStream <--------- BufferedInputStream 缓冲流
FilterOutputStream <--------- BufferedOutputStream
(1) 构造方法
BufferedInputStream public BufferedInputStream(InputStream in) public BufferedInputStream(InputStream in, int size) //指定大小缓冲流BufferedOutputStream public BufferedOutputStream(OutputStream out) public BufferedOutputStream(OutputStream out, int size)
(2)常用方法
BufferedInputStream public void close() throws IOException public synchronized int read(byte b[], int off, int len) throws IOException public synchronized int read() throws IOException public synchronized int available() throws IOException //判断是否可以读取下个字节BufferedOutputStream public synchronized void write(int b) throws IOException public synchronized void write(byte b[], int off, int len) throws IOException public synchronized void flush() throws IOException
(3)举例
/** * BufferedInputStream 测试程序 * * @author skywang */public class BufferedInputStreamTest { private static final int LEN = 5; public static void main(String[] args) { testBufferedInputStream() ; } /** * BufferedInputStream的API测试函数 */ private static void testBufferedInputStream() { // 创建BufferedInputStream字节流,内容是ArrayLetters数组 try { File file = new File("bufferedinputstream.txt"); InputStream in =new BufferedInputStream(new FileInputStream(file), 512); // 从字节流中读取5个字节。“abcde”,a对应0x61,b对应0x62,依次类推... for (int i=0; i= 0) { // 读取“字节流的下一个字节” int tmp = in.read(); System.out.printf("%d : 0x%s\n", i, Integer.toHexString(tmp)); } } // 若“该字节流”不支持标记功能,则直接退出 if (!in.markSupported()) { System.out.println("make not supported!"); return ; } // 标记“当前索引位置”,即标记第6个位置的元素--“f” // 1024对应marklimit in.mark(1024); // 跳过22个字节。 in.skip(22); // 读取5个字节 byte[] buf = new byte[LEN]; in.read(buf, 0, LEN); // 将buf转换为String字符串。 String str1 = new String(buf); System.out.printf("str1=%s\n", str1); // 重置“输入流的索引”为mark()所标记的位置,即重置到“f”处。 in.reset(); // 从“重置后的字节流”中读取5个字节到buf中。即读取“fghij” in.read(buf, 0, LEN); // 将buf转换为String字符串。 String str2 = new String(buf); System.out.printf("str2=%s\n", str2); in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}/** * BufferedOutputStream 测试程序 * * @author skywang */public class BufferedOutputStreamTest { private static final int LEN = 5; // 对应英文字母“abcddefghijklmnopqrsttuvwxyz” private static final byte[] ArrayLetters = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A }; public static void main(String[] args) { testBufferedOutputStream() ; } /** * BufferedOutputStream的API测试函数 */ private static void testBufferedOutputStream() { // 创建“文件输出流”对应的BufferedOutputStream // 它对应缓冲区的大小是16,即缓冲区的数据>=16时,会自动将缓冲区的内容写入到输出流。 try { File file = new File("out.txt"); OutputStream out =new BufferedOutputStream(new FileOutputStream(file), 16); // 将ArrayLetters数组的前10个字节写入到输出流中 out.write(ArrayLetters, 0, 10); // 将“换行符\n”写入到输出流中 out.write('\n'); // TODO! //out.flush(); readUserInput() ; out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 读取用户输入 */ private static void readUserInput() { System.out.println("please input a text:"); Scanner reader=new Scanner(System.in); // 等待一个输入 String str = reader.next(); System.out.printf("the input is : %s\n", str); }}
2)FilterInputStream <--------- PrintStream 输出打印流
1、构造方法
PrintStream(OutputStream out)PrintStream(OutputStream out, boolean autoFlush) //将“输出流out”作为PrintStream的输出流,自动flush,采用charsetName字符集。PrintStream(OutputStream out, boolean autoFlush, String charsetName) //创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用默认字符集。PrintStream(File file) //创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用charsetName字符集PrintStream(File file, String charsetName //创建fileName对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用默认字符集。PrintStream(String fileName) //创建fileName对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用charsetName字符集PrintStream(String fileName, String charsetName)
2、常用方法
public void println()PrintStream append(char c)// 将“字符序列从start(包括)到end(不包括)的全部字符”追加到“PrintStream输出流中”PrintStream append(CharSequence charSequence, int start, int end)// 将“字符序列的全部字符”追加到“PrintStream输出流中”PrintStream append(CharSequence charSequence)// flush“PrintStream输出流缓冲中的数据”,并检查错误boolean checkError()// 关闭“PrintStream输出流”synchronized void close()// flush“PrintStream输出流缓冲中的数据”。// 例如,PrintStream装饰的是FileOutputStream,则调用flush时会将数据写入到文件中synchronized void flush()// 根据“Locale值(区域属性)”来格式化数据PrintStream format(Locale l, String format, Object... args)// 根据“默认的Locale值(区域属性)”来格式化数据PrintStream format(String format, Object... args)
3、举例
/** * PrintStream 的示例程序 * * @author skywang */public class PrintStreamTest { public static void main(String[] args) { // 下面3个函数的作用都是一样:都是将字母“abcde”写入到文件“file.txt”中。 // 任选一个执行即可! testPrintStreamConstrutor1() ; //testPrintStreamConstrutor2() ; //testPrintStreamConstrutor3() ; // 测试write(), print(), println(), printf()等接口。 testPrintStreamAPIS() ; } /** * PrintStream(OutputStream out) 的测试函数 * * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中 */ private static void testPrintStreamConstrutor1() { // 0x61对应ASCII码的字母'a',0x62对应ASCII码的字母'b', ... final byte[] arr={0x61, 0x62, 0x63, 0x64, 0x65 }; // abced try { // 创建文件“file.txt”的File对象 File file = new File("file.txt"); // 创建文件对应FileOutputStream PrintStream out = new PrintStream( new FileOutputStream(file)); // 将“字节数组arr”全部写入到输出流中 out.write(arr); // 关闭输出流 out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * PrintStream(File file) 的测试函数 * * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中 */ private static void testPrintStreamConstrutor2() { final byte[] arr={0x61, 0x62, 0x63, 0x64, 0x65 }; try { File file = new File("file.txt"); PrintStream out = new PrintStream(file); out.write(arr); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * PrintStream(String fileName) 的测试函数 * * 函数的作用,就是将字母“abcde”写入到文件“file.txt”中 */ private static void testPrintStreamConstrutor3() { final byte[] arr={0x61, 0x62, 0x63, 0x64, 0x65 }; try { PrintStream out = new PrintStream("file.txt"); out.write(arr); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 测试write(), print(), println(), printf()等接口。 */ private static void testPrintStreamAPIS() { // 0x61对应ASCII码的字母'a',0x62对应ASCII码的字母'b', ... final byte[] arr={0x61, 0x62, 0x63, 0x64, 0x65 }; // abced try { // 创建文件对应FileOutputStream PrintStream out = new PrintStream("other.txt"); // 将字符串“hello PrintStream”+回车符,写入到输出流中 out.println("hello PrintStream"); // 将0x41写入到输出流中 // 0x41对应ASCII码的字母'A',也就是写入字符'A' out.write(0x41); // 将字符串"65"写入到输出流中。 // out.print(0x41); 等价于 out.write(String.valueOf(0x41)); out.print(0x41); // 将字符'B'追加到输出流中 out.append('B'); // 将"CDE is 5" + 回车 写入到输出流中 String str = "CDE"; int num = 5; out.printf("%s is %d\n", str, num); out.close(); } catch (IOException e) { e.printStackTrace(); } }}
3、ByteArrayInputStream / ByteArrayOutputStream (内存流)
1)构造方法
ByteArrayInputStream public ByteArrayInputStream(byte[] buf) public ByteArrayInputStream(byte[] buf, int offset, int length)ByteArrayOutputStream public ByteArrayOutputStream() public ByteArrayOutputStream(int size)
2)常用方法
ByteArrayInputStream public synchronized int read(byte b[], int off, int len) public synchronized int read() public void close() throws IOException ByteArrayOutputStream public synchronized void write(int b) public synchronized void write(byte b[], int off, int len) public synchronized byte toByteArray() public synchronized String toString() public void close() throws IOException
3)举例
/** 1*/public class Test { public static void readByteArray(String msg) { ByteArrayOutputStream baos = null; ByteArrayInputStream bais = null; try { baos = new ByteArrayOutputStream(); baos.write(msg.getBytes()); baos.flush(); bais = new ByteArrayInputStream(baos.toByteArray()); byte[] b = new byte[1024]; int len = bais.read(b); System.out.println("len:" + len); String str = new String(b, 0, len); System.out.println("str:" + str); } catch (IOException e) { e.printStackTrace(); } finally { try { if (baos != null) { baos.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { String msg = "hello world"; readByteArray(msg); }}/** 2*/ import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.Arrays;/** * 内存流: * ByteArrayInputStream * ByteArrayOutputSteam */public class Test { public static void main(String[] args) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { // 将内容写入到内存 baos.write("写个啥".getBytes()); baos.flush();// baos.toByteArray(); byte[] bs =new byte[20]; System.out.println(Arrays.toString(bs)); // 将内存中的数据读取出来 ByteArrayInputStream bais = new ByteArrayInputStream(bs);// byte必须传递 内存中的数据转成 byte数组的格式// 而不能直接传递一个空数组, 读取出来的数据也是空的 byte[] b = new byte[10]; int num = bais.read(b); System.err.println(Arrays.toString(b)); System.out.println(num); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
4、ObjectOutputStream/ObjectInputStream (序列化与反序列)
1)构造方法
ObjectOutputStream public ObjectOutputStream(OutputStream out)ObjectInputStream public ObjectInputStream(InputStream in)
2)举例
class User implements Serializable{ //必须实现Serializable接口 String uid; String pwd; public User(String _uid,String _pwd){ this.uid = _uid; this.pwd = _pwd; } @Override public String toString() { return "账号:"+this.uid+" 密码:"+this.pwd; }}public class Demo1 { public static void main(String[] args) throws IOException { //假设将对象信息写入到obj.txt文件中,事先已经在硬盘中建立了一个obj.txt文件 File f = new File("F:\\obj.txt"); writeObjec(f); System.out.println("OK"); } //定义方法把对象的信息写到硬盘上------>对象的序列化。 public static void writeObjec(File f) throws IOException{ FileOutputStream outputStream = new FileOutputStream(f);//创建文件字节输出流对象 ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(new User("酒香逢","123")); //最后记得关闭资源,objectOutputStream.close()内部已经将outputStream对象资源释放了,所以只需要关闭objectOutputStream即可 objectOutputStream.close(); }}public class Demo1 { public static void main(String[] args) throws IOException, ClassNotFoundException { //假设将对象信息写入到obj.txt文件中,事先已经在硬盘中建立了一个obj.txt文件 File f = new File("F:\\obj.txt"); //writeObjec(f); readObject(f); System.out.println("OK"); } //定义方法把对象的信息写到硬盘上------>对象的序列化。 public static void writeObjec(File f) throws IOException{ FileOutputStream outputStream = new FileOutputStream(f);//创建文件字节输出流对象 ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(new User("酒香逢","123")); //最后记得关闭资源,objectOutputStream.close()内部已经将outputStream对象资源释放了,所以只需要关闭objectOutputStream即可 objectOutputStream.close(); } //把文件中的对象信息读取出来-------->对象的反序列化 public static void readObject(File f) throws IOException, ClassNotFoundException{ FileInputStream inputStream = new FileInputStream(f);//创建文件字节输出流对象 ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); User user = (User)objectInputStream.readObject(); System.out.println(user); }}