节点流与处理流
根据封装类型不同流又分为:1.节点流 2.处理流 节点流:如果流封装的是某种特定的数据源,如文件、字符串、字符串数组等,则称为节点流。 处理流:如果流封装的是其它流对象,称为处理流。 处理流提供了缓冲功能,提高读写效率,同时增加了一些新的方法 节点流中常用类: 字节输入流 FileInputStream 字节输出流 FileOutputStream 字符输入流 FileReader 字符输出流 FileWriter 处理流中常用类: 缓冲字节输出流 BufferedOutputStream 缓冲字节输入流 BufferedInputStream 缓冲字符输入流 BufferedReader 缓冲字符输出流 BufferedWrite
public static void main(String[] args) throws IOException { /* 节点流: 流对象是直接对数据操作 构造方法(文件) 处理流/包装流: 流对象中包含的是另一个流,提供一些额外的数据处理 BufferedInputStream 带缓冲区 BufferedOutputStream ObjectOutputStream ObjectInputStream */ FileInputStream in = new FileInputStream("E:/feige.exe"); FileOutputStream out = new FileOutputStream("E:/fg.exe"); BufferedInputStream bin = new BufferedInputStream(in);//DEFAULT_BUFFER_SIZE = 8192; BufferedOutputStream bout = new BufferedOutputStream(out); //BufferedOutputStream bout = new BufferedOutputStream(out,2048); /*int size = 0; byte[] b = new byte[3000];//自带缓存区 while((size=bin.read(b))!=-1){//read时,自定义的数组不大于底层数组时会把读到的数据缓冲到底层数组中去 bout.write(b); }*/ int b = 0; while((b=bin.read())!=-1){//read时,会把读到的数据缓冲到底层数组中去 bout.write(b); //write时并不是每write一次就向磁盘去写数据,等待内部的缓存数组写满时,再向磁盘输出 } bout.flush();//关闭之前,刷新缓冲区 bin.close(); bout.close(); }}
输入输出字符流
Reader 的基本方法 读取一个字符并以整数的形式返回, 如果返回-1已到输入流的末尾。 int read() throws IOException 读取一系列字符并存储到一个数组buffer, 返回实际读取的字符数,如果读取前已到输入流的末尾返回-1 int read( char[] cbuf) throws IOException 关闭void close() throws IOException Writer 的基本方法 向输出流中写入一个字符数据,该字节数据为参数b的16位 void write(int c) throws IOException 一个字符类型的数组中的数据写入输出流 void write( char[] cbuf) throws IOException 将一个字符类型的数组中的从指定位置(off set)开始的 length个字符写入到输出流 void write( char[] cbuf, int off set, int length) throws IOException 关闭void close() throws IOException
public static void main(String[] args) throws IOException { /* 一个汉字在utf-8编码中需要3个字节,底层存储单位是字节,字符流如何做到一次直接读到一个汉字字符 Reader 字符输入流的基类 FileReader extends InputStreamReader(转换流,将读到的字节,按照指定charset转换为字符) Writer 字符输出流的基类 FileWriter extends OutputStreamWriter 转换流,将字符转为字节写出 字符流只能读取纯文本文件 */ FileReader reader = new FileReader("E:/demo1.txt"); FileWriter writer = new FileWriter("E:/demo2.txt"); char [] chars = new char[5]; int size = 0; while ((size=reader.read(chars))!=-1){ writer.write(chars,0,size);//20013 } /* int c = 0; while ((c=reader.read())!=-1){ writer.write(c); }*/ reader.close(); writer.close(); /*System.out.println((char)reader.read()); System.out.println((char)reader.read()); System.out.println(reader.read()); System.out.println(reader.read());*/ FileReader reader = new FileReader("E:/demo1.txt"); FileWriter writer = new FileWriter("E:/demo2.txt",true);//写入数据时,保留之前的,向后面追加内容 BufferedReader bufferedReader = new BufferedReader(reader); BufferedWriter bufferedWriter = new BufferedWriter(writer); String line = null; while((line=bufferedReader.readLine())!=null){//readLine() 一次读取一行数据 System.out.println(line); bufferedWriter.write(line); bufferedWriter.newLine();//插入换行符 } bufferedWriter.flush(); bufferedReader.close(); bufferedWriter.close(); }}
Print流
Print 打印流:只做输出没有输入 ,打印流分为字节打印流和字符打印流 PrintWriter:字符打印流 print方法可以打印各种类型数据,在javaweb项目中,服务器端向客户端响应数据以打印流的方式响应.
public static void main(String[] args) throws FileNotFoundException { /* 打印流: 单向的从程序中向目标输出数据 PrintWriter 打印字符流 */ PrintWriter out = new PrintWriter("E:/demo.html"); out.print("<h1>你好客户端</h1>"); out.print("<h1>你好客户端</h1>"); out.print("<h1>你好客户端</h1>"); out.print("<h1>你好客户端</h1>"); out.close(); }}
对象输入输出流
对象的寿命通常随着生成该对象的程序的终止而终止。 有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。 对象的输入输出流 :主要的作用是用于写入对象信息与读取对象信息。 对象信息 一旦写到文件上那么对象的信息就可以做到持久化了. 对象的输出流:ObjectOutputStream对象的输入流:ObjectInputStream 在ObjectInputStream 中用readObject()方法可以直接读取一个对象,ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中. 对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程. 对象的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。 对象的输出流将对象写入到文件中称之为对象的序列化,所以被序列化对象的类必须要实现 Serializable接口。 Serializable接口中没有任何方法。当一个类声明实现Serializable接口后, 表明该类可被序列化。 在类中可以生成一个编号 private static final long serialVersionUID = -5974713180104013488L; 随机生成 唯一的 serialVersionUID 用来表明实现序列化类的不同版本间的兼容性。某个类在与之对应的对象已经序列化出去后做了修改,该对象依然可以被正确反序列化. 如果不显示生成序列号,那么将会隐式生产,但是隐式生成后,类一旦发生 改变,序列号也会随之改变.
transient关键字
默认情况下当执行了对象序列化的时候会将类中的全部属性的内容进行全部的序列化操作,但是很多情况下有一些属性可能并不需要序列化的处理,这个时候就可以在属性的定义上使用transient关键字来完成了。private transient String name
/* 对象存储在内存中,程序终止运行,内存数据清空, 有时需要保存对象中的数据,需要用流对象,将对象数据输出到文件中,做到对象数据的持久化(长久保存) ObjectInputStream ObjectOutputStream 都属于处理流 此过程也称为对象的序列化和反序列化,其中反序列也是一种创建对象的方法 */ public static void main(String[] args) throws IOException, ClassNotFoundException { /* FileOutputStream fout= new FileOutputStream("E:/obj.txt"); ObjectOutputStream out = new ObjectOutputStream(fout); Date date = new Date(); String s = "abc"; out.writeObject(date); out.writeObject(s); out.flush(); out.close();*/ //反序列化 会新创建对象 FileInputStream in = new FileInputStream("E:/obj.txt"); ObjectInputStream oin = new ObjectInputStream(in); Date date = (Date)oin.readObject(); String s = (String)oin.readObject(); System.out.println(date); System.out.println(s); }} /*Serializable 序列化接口 如果需要将某个类的对象进行序列化,那么此类必须实现Serializable接口 会为类生成一个版本号,如果不显得定义版本号,会自定默认生成,会有一个问题,每次当类改变了,版本号会重新生成*/ public class Car implements Serializable { //序列化版本号 显示的定义之后,类信息发生改变不会重新生成 private static final long serialVersionUID = -1981902868337741342L; //transient修饰的属性在序列式,不会保存到文件中 private transient int no; private String name; public Car(int no, String name) { this.no = no; this.name = name; } @Override public String toString() { return "Car{" + "no=" + no + ", name='" + name + '\'' + '}'; } } public static void main(String[] args) throws IOException, ClassNotFoundException { /*FileOutputStream fout= new FileOutputStream("E:/obj.txt"); ObjectOutputStream out = new ObjectOutputStream(fout); Car car = new Car(100, "宝马"); out.writeObject(car); out.flush(); out.close(); */ //反序列化 会新创建对象 FileInputStream in = new FileInputStream("E:/obj.txt"); ObjectInputStream oin = new ObjectInputStream(in); Car car= (Car)oin.readObject(); System.out.println(car); }}//0(int新对象是0),宝马