I/O流概述
I/O(Input/Output)流,即输人输出流,是Java中实现输人输出的基础,它可以方便地实现数据的输人输出操作。
I/O流有很多种,按照不同的分类方式,可以分为以下3类:
1.字节流和字符流
根据流操作的数据单位的不同,可以分为字节流和字符流。字节流以字节为单位进行数据的读写,每次读写一一个或多个字节数据;字符流以字符为单位进行数据的读写,每次读写一个或者多个字符数据。
2.输入流和输出流
根据流传输方向的不同,又可分为输人流和输出流。其中输人流只能从流中读取数据,而不能向其写人数据;输出流只能向流中写人数据,而不能从中读取数据。
3.节点流和处理流
根据流的功能不同,可以分为节点流和处理流。其中节点流也被称为低级资,是指可以从一个特定的I/0设备(如磁盘)读写数据的流,它只能直接连接数据源,进行数据的读写操作;处理流也被称为高级流,它用于对于一个已存在的节点流进行连接和封装,通过封装后的流来实现流的读写能力。当使用处理流时,程序不会直接连接到实际的数据源,而是连接在已存在的流之上
文件流
package day07;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* 流
* 流根据方向不同分为输入流与输出流,参照点为
* 当前程序
* 输入流用来读取数据,输出流用来写出数据
* java.io.InputStream
* 抽象类,定义了输入流的读取字节方法,所有的字节
* 输入流都继承自它
*
* java.io.OutputStream 则是所有字节输出流的父类
* @author
*
*
*流分类节点流与处理流
*节点流,也叫低级流,是负责读写数据的流
*读写操作中必须要有低级流。数据源明确
*
*处理流,也叫高级流,读写可以没有高级流,
*高级流也不能独立存在,必须用于处理其他流,
*处理其他流的目的是简化读写数据中的操作
*
* java.io.FileOutputStream
* 文件输出流,是一个低级流,作用是向文件中
* 写出字节
*/
public class FOSDemo {
public static void main(String[] args) throws IOException {
/**
* 默认创建的FOS是覆盖写操作
* FOS会将文件数据(所有数据)全部
* 删除,然后在开始写
*/
FileOutputStream fos = new FileOutputStream("fos.txt");
String str = "我爱北京天安门";
/**
* String->byte[]
*
* byte getBytes()
* 将当前字符串按照系统默认字符集转换为一组字节
*
* byte getBytes(String csn)
* 按照给定的字符集将当前字符串转换为一组字节
*/
byte[] data = str.getBytes("UTF-8");
fos.write(data);
System.out.println("写出完毕");
fos.close();
}
}
package day07;
/**
* 文件输出流
* 追加写操作
*/
import java.io.FileOutputStream;
import java.io.IOException;
public class FosDemo2 {
public static void main(String[] args) throws IOException{
/**
* 在创建FOS时,若指定第二个参数,
* 并且该值为true时,则是追加
* 写操作,那么本次通过FOS写出
* 的内容会被追加到该文件末尾
*/
FileOutputStream fos= new FileOutputStream("fos.txt",true);
fos.write("哦".getBytes("UTF-8"));
System.out.println("写出完毕");
fos.close();
}
}
package day07;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Java.io.FileInputStream
* 文件输入流,是一个低级流,用于
* 从文件中读取字节
* @author
*
*/
public class FosDemo3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] data = new byte[100];
int len = fis.read(data);
String str = new String(data,0,len,"UTF-8");
System.out.println(str);
fis.close();
}
}
package day07;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 使用文件流复制文件
* @author
*
*/
public class CopyDemo {
public static void main(String[] args) throws IOException {
/**
* 使用文件输入流读取文件,再使用
* 文件输出流向目标文件中写
* 顺序从原文件中读取每个字节并写入到
* 目标文件即可完成复制
*/
FileInputStream src = new FileInputStream("课后答案.txt");
FileOutputStream desc = new FileOutputStream("课后答案44.txt");
byte[] buf = new byte[1024*10];
int len = 10;
while ((len = src.read(buf))!=-1) {
desc.write(buf,0,len);
}
System.out.println("复制完毕");
src.close();
desc.close();
}
}
缓冲流
package day07;
/**
* 缓冲流
* java.io.BufferedInputStream
* java.io.BufferedOutputStream
* 缓冲字节输入输出流是一对高级流,使用他们
* 可以加快读写效率
*
* 高级流可以处理其他流,但是无论添加了多少高级流
* 最底下都要有低级流,因为低级流是真实
* 读写数据的流,高级流都是处理数据的
* 高级流处理其他流形成了流的链接,并且有效的
* 组合不同的高级流可以得到叠加的效果
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 使用缓冲流加快读写效率
*
* @author Administrator
*/
public class CopyDemo2 {
public static void main(String[] args)throws IOException {
FileInputStream fis = new FileInputStream("课后答案.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("7777.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int d = -1;
/**
* 缓冲流内部有一个缓冲区
* 当bis.read方法读取第一个字节时
* 实际上BIS会一次性读取一组字节并存入内部
* 的字节数组中,然后将第一个字节返回,
* 当再次调用read方法时,BIS直接从字节数组中
* 将第二个字节返回,直到字节数组中所有字节全部返回后
* 才会再次读取一组字节
* 所以缓冲流也是依靠提高一次读写的数据量减少读写
* 次数来达到提高读写的效率的
*/
while ((d = bis.read()) != -1) {
bos.write(d);
}
System.out.println("复制完毕");
/*
* 关闭流时,只关闭最外层的高级流即可
*/
bis.close();
bos.close();
}
}
package day07;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 缓冲输出流写出数据的注意事项
* @author Administrator
*
*/
public class BosDemo {
public static void main(String[] args) throws IOException{
FileOutputStream fos
= new FileOutputStream("bos.txt");
BufferedOutputStream bos
= new BufferedOutputStream(fos);
String str = "就是因为这句话审核不通过";
byte[] buf = str.getBytes("UTF-8");
bos.write(buf);
/*
* 强制将当前缓冲流中的缓冲区中的数据
* 全部写出,无论缓冲区是否被装满
*/
bos.flush();
System.out.println("写出完毕");
//close时,也会自动调用一次flush
bos.close();
}
}
对象流
package day07;
/**
* 该类用于测试作为对象流读写对象使用
*/
import java.io.Serializable;
import java.util.List;
/**
* 一个对象若想通过ObjectOutputStream
* 进行序列化(被对象流读写),那么该对象所属的类必须实现
* Serializable接口
* 该接口没有定义任何抽象方法,实现该接口
* 仅仅用于标识当前类的实例可以被序列化
* @author Administrator
*
*/
public class Person implements Serializable{
/**
* 当一个类实现了Serializable接口后
* 应当添加一个常量:serialVersionUID
* 该常量为当前类的序列化版本号,若不定义
* 系统会根据当前类的结构生成,但是只要类的
* 结构发生改变,版本号也会发生改变
*
* 版本号影响着反序列化的结果。即:
* 当OIS对一个对象进行反序列化时,会检查
* 该对象与类的版本是否一致:
* 若一致:反序列化成功,但是若该对象与类
* 的结构不一致时 ,则采用兼容模式,能还原的属性
* 都还原
* 若不一致:反序列化直接抛出版本不一致异常
*/
private static final long serialVersionUID = 1L;
/*
* 当类的属性增加或修改了,若版本号不变
* 那么反序列化时会尽可能兼容现有版本
* 若版本号发生了改变,那么反序列化时会
* 抛出异常。
*/
private String name;
private int age;
private String gender;
/**
* transient关键字用来修饰属性
* 当被修饰后,该类实例在使用OOS进行对象
* 序列化时,该属性值被忽略,从而达到对象“瘦身”
* 的目的
*/
private transient List<String> otherInfo;
public Person() {
}
public Person(String name, int age, String gender, List<String> otherInfo) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.otherInfo = otherInfo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public List<String> getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(List<String> otherInfo) {
this.otherInfo = otherInfo;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + ", otherInfo=" + otherInfo + "]";
}
}
package day07;
/**
* 对象流
* 对象流是一对高级流,作用是方便读写Java中的对象
* java.io.ObjectOutputStream
* 对象输出流,可以将给定的对象转换为一组字节
* 后写出
*/
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class OOSDemo {
public static void main(String[] args) throws IOException{
Person p = new Person();
p.setName("张三");
p.setAge(15);
p.setGender("男");
List<String> otherInfo = new ArrayList<String>();
otherInfo.add("是一个学生");
otherInfo.add("喜欢打游戏");
p.setOtherInfo(otherInfo);
FileOutputStream fos = new FileOutputStream("person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
/**
* ObjectOutputStream的writeObject
* 方法可以将给定对象转换为一组字节后写出。这些
* 字节比该对象实际内容要大,因为除了数据外还有结构等描述信息
*
* 下面的代码实际上经历了两个操作:
* 1:oos将Person对象转换为一组字节
* 将一个对象转换为一组字节的过程
* 称为:对象序列化
*
* 2:再通过fos将这组字节写入到硬盘
* 将该对象转换的字节写入到硬盘
* 做长久保存的过程称为:对象持久化
*/
oos.writeObject(p);
System.out.println("写出对象完毕");
oos.close();
}
}
package day07;
/**
* java.io.ObjectInputStream
* 对象输入流,作用是
* 读取一组字节并还原为对象
* OIS读取的字节必须是有OOS将对象序列化
* 得到的字节,否则会抛出异常
*/
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class OISDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException{
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
//对象反序列化
Person p = (Person)ois.readObject();
System.out.println(p);
ois.close();
}
}