缓冲流(高效率的流)
BufferedOutputStream 缓冲输出字节流
构造方法:
BufferedOutputStream(OutputStream out)
参数:字节输出流的父类 FileOutputStream
使传进来的流更高效
BufferedInputStream 缓冲输入字节流
当程序发出指令去读取一个文件时,对比使用字节流和缓冲流的区别:
字节流:程序——JVM——磁盘文件——JVM——程序,同理写入到其他文件中去(但每次只读一个字节)
缓冲流:与字节流不同的是JVM会开辟一个缓冲区,将每次读取的字节先存到缓冲区中,
当缓冲区存满时再将缓冲区中的内容写入到其他文件中,当缓冲区没有存满时,不会写入。
假设一个文件有1024个字节,缓冲区大小为100个字节,那么要读取11次,最后一次只有24个字节,
但此时缓冲区并没有存满,不能将存储的内容从缓冲区中取出。
这时我们可以调用缓冲流自带的一个方法flush(强制写入)将最后一次读取的内容强制写入到文件中去。
字节流与字符流的效率对比
当读取一个较小的文件时,字节流与缓冲流效率差别不大
但当我们读取一个较大的文件时,通过实际测试对比发现缓冲流明显比字节流快得多。
BufferedInputStream比FileInputStream多了一个缓冲区,执行read时先从缓冲区读取,
当缓冲区数据读完时再把缓冲区填满。
因此,当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,
而BufferedInputStream大部分是从缓冲区读入。读取内存速度比读取硬盘速度快得多,
因此BufferedInputStream效率高。
BufferedOutputStream和FileOutputStream同理,差异更明显一些。
使用缓冲流 BufferedOutputStream 写入文件
FileOutputStream fos = new FileOutputStream("/Users/Desktop/Test/Test.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("HelloWorld".getBytes());
bos.close();
使用缓冲流 BufferedIntputStream 读取文件
FileInputStream fis = new FileInputStream("/Users/Desktop/Test/Test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] b = new byte[1024];
int len = 0;
while((len = bis.read(b)) != -1){
System.out.println(new String(b, 0, len));
}
bis.close();
测试,比较使用缓冲流复制文件和不使用缓冲流复制文件所用时间差距
public class Test{
public static void main(String[] args) throws IOException {
// 测试
new fun1.printTime();
new fun2.printTime();
new fun3.printTime();
new fun4.printTime();
}
}
// 程序的开始部分和结尾部分均相同,创建抽象类
abstract class TestTime {
// 源文件路径
public String src = "/Users/DeskTop/Test/Test.png";
// 目的文件路径
public String dest = "/Users/DeskTop/Test/Tests.png";
// 统计花费时间方法
public void printTime() throws IOException {
// 获取程序开始时间
long start = System.currentTimeMillis();
// 调用抽象方法复制文件
copyFile();
// 获取程序结束时间
long end = System.currentTimeMillis();
}
// 抽象方法,字符流/缓冲流复制文件
public abstract void copyFile() throws IOException;
// 抽象方法,打印两种方法所用时间
public abstract void printSpeedTimes(long start, long end);
}
// 字符流复制文件
abstract class Mycopy1 extends TestTime {
public void copyFile() throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest);
int len = 0;
// 调用内部实现的抽象方法
run1(len, fis, fos);
fis.close();
fos.close();
}
// 内部实现的抽象方法
public abstract void run1(int len, FileInputStream fis, FileOutputStream fos) throws IOException);
public abstract void printSpeedTimes(long start, long end);
}
// 字节流单字节内部实现
class fun1 extends Mycopy1 {
public void run1(int len, FileInputStream fis, FileOutputStream fos) throws IOException {
while((len = fis.read()) != -1){
fos.write((char)len);
}
}
// 花费时间
public void printSpeedTimes(long statr, long end){
System.out.println("字节流单字节复制耗费时间:" + (end - start));
}
}
// 字节流数组
class fun2 extends Mycopy1 {
public void run1(int len, FileInputStream fis, FileOutputStream fos) throws IOException {
byte[] b = new byte[1024];
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
}
public void printSpeedTimes(long start, long end) {
System.out.println("字节流数组复制耗费时间:" + (end - start));
}
}
// 使用缓冲流单字节复制文件
abstract class Mycopy2 extends TestTime {
public void copyFile() throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int len = 0;
run2(bis, bos, len);
bis.close();
bos.close();
}
public abstract void printSpeedTimes(long start, long end) ;
public abstract void run2(BufferedInputStream bis, BufferedOutputStream bos, int len) throws IOException;
}
class fun3 extends Mycopy2 {
public void run2(BufferedInputStream bis, BufferedOutputStream bos, int len) throws IOException {
while ((len = bis.read()) != -1) {
bos.write(len);
}
}
public void printSpeedTimes(long start, long end) {
System.out.println("缓冲流字节复制耗费时间:" + (end - start));
}
}
class fun4 extends Mycopy2{
@Override
public void printSpeedTimes(long start, long end) {
System.out.println("缓冲流数组复制耗费时间:" + (end - start));
}
public void run2(BufferedInputStream bis, BufferedOutputStream bos, int len) throws IOException {
byte[] b = new byte[1024];
while ((len = bis.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
}
}
缓冲字符流
BufferedWriter
构造方法:
参数: Writer(父类)
可传 FileWriter OutputStreamWriter
特有方法
newLine() 此方法无关平台性
mac 为 \n
Windows 为 /r/n
BUfferedReader
使用 BufferedWriter 写入文件
FileWriter fw = new FileWriter("/Users/Desktop/Test/Test.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("雪中智代雨中杏,");
bw.newLine();
bw.flush();
bw.write("樱下小渚花田汐。");
bw.newLine();
bw.flush();
bw.write("香醇宫泽黑琴美,");
bw.newLine();
bw.flush();
bw.write("天际芽衣黄昏椋。");
bw.newLine();
bw.flush();
bw.close();
使用 BufferedReader 读取文件
FileReader fr = new FileReader("/Users/Desktop/Test/Test.txt");
BufferedReader br = new BufferedReader(fr);
// 按行来读
// 在读取时,BufferedReader 不能把换行也一起读出来
// 所以,在读取时,要与原文本一样,就需要加上换行符来打印
String string = "";
while((string = br.readLine()) != null) {
System.out.println(string);
}
br.close();
使用缓冲流进行文件复制
// 读
FileReader fr = new FileReader("/Users/Desktop/Test/Test.txt");
BufferedReader bf = new BufferedReader(fr);
// 写
FileWriter fw = new FileWriter("/Users/Desktop/Test/Tests.txt");
BufferedWriter bw = new BufferedWriter(fw);
// 边读边写
String string = "";
while((string = bf.readLine()) != null){
bw.write(string);
bw.newLine();
bw.flush();
}
bf.close();
bw.close();
1.明确要做的操作
读取数据源
InputStream
Reader
写到数据目的地
OutputStream
Writer
2.明确要操作的是什么内容
文本、音频、图片、视频---使用字节流(全能流)
文本(按编码格式读写) ---使用字符流
3.明确流要在什么设备上使用
文本
网络通过流进行数据交互---字节流
4.是否需要提高效率
Buffered 缓冲流
应用场景:迅雷加速器会员非会员
Properties 集合(双列集合)父类 Hashtable
作用:Properties 是集合中唯一一个能和 IO 流配合的集合类
读取和写入是参数
可以是字符流
也可以是字节流(必须要使用转换流)
// 写入
Properties properties = new Properties();
properties.put("name", 1);
// 注意:该集合最好使用的是 key 和 value 都是字符串
// 最好都使用该集合
properties.setProperty("gender", "女");
System.out.println(properties);
// 遍历集合
// 取出所有 key 的集合
Set set = properties.stringPropertyNames();
for(String key : set) {
// 获取 value
String value = properties.getProperty(key);
System.out.println(key + ":" + value);
}
// 读取
Properties properties = new Properties();
FileReader fr = new FileReader("/Users/Desktop/Test/Test.txt");
properties.load(fr);
System.out.println(properties);
fr.close();
Properties properties = new Properties();
properties.setProperty("a","啊");
properties.setProperty("b", "吧");
properties.setProperty("c", "从");
// 后缀名是什么,都不会产生影响
// 一般写法,使用. properties 当做文件后缀名,来标识该文件可以使用 properties 类读取
FileWriter fw = new FileWriter("/Users/Desktop/Test/Test.properties");
// 利用 properties 类中的方法写入
// 参数二:相当于写入文件的注释,一般什么都不写
// 在 properties 文件中,可以使用#号来写注释
properties.store(fw, "");
fw.close();
序列化:把对象写进文件中
反序列化:从文件中把对象读出来
对象流
ObjectInputStream
ObjectOutputStream
注意:静态成员变量是不能进行序列化的
序列化:序列是对象,静态成员变量是属于类的
序列化相当于是把对象进行持久化文件
// 读取序列化文件(反序列化)
// 在进行反序列化(读取)的时候,需要依赖你的编译文件. class 文件来进行读取
FIleInputStream fis = new FIleInputStream("/Users/Desktop/Test/Test.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// 读文件
Object object = ois.readObject();
System.out.println(object);
ois.close();
// 注意:如果要对对象进行实例化
// 必须要实现 Serializable (序列化接口)
// Serializable 该接口是标记型接口
// 写对象都使用字节流去操作
FIleOutputStream fos = new FIleOutputStream("/Users/Desktop/Test/Test.txt");
// 对象输出流(序列化流)
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 使用写对象的方法
oos.writerObject(new Person("dp",15));
ooc.close();
public class Person implements Serializable{
/**
* 序列化使用序列号
* 只要写了这个号,在编译时,系统就不会重新计算序列号了
*/
private static final long serialVersionUID = 1L;
// 不想写成静态,也不想序列化,怎么办?
// 使用 transient 关键字 瞬态关键字
// 作用:可以组织成员变量序列化
private transient String name;
private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "[姓名:" + name + "]\n[年龄:" + age + "]";
}
}
/*
* 学生类
* 姓名 性别 年龄 空参有参构造 set和get方法 toString方法
* 键盘录入6个学员信息(格式为 张三,男,25),要求有两个相同的信息,将6个学员信息存入到ArrayList集合中
* 将存有6个学员信息的ArrayList集合对象写入到文件中
* 读取文件中的ArrayList对象
* 对集合中的6个学生对象进行去重并按照年龄从小到大的顺序排序
* 再将排序完成的集合写进重新写进文件中
* 再重新读取,查看排序结果
*
* 注意:一般序列化的对象,只存一个容器
*/
public class Student implements Serializable ,Comparable{
private static final long serialVersionUID = 1L;
private String name;
private String gender;
private int age;
public Student() {
super();
}
public Student(String name, String gender, int age) {
super();
this.name = name;
this.gender = gender;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "[姓名:" + name + ", 性别:" + gender + ", 年龄:" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((gender == null) ? 0 : gender.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (gender == null) {
if (other.gender != null)
return false;
} else if (!gender.equals(other.gender))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int compareTo(Student o) {
int num = this.age - o.getAge();
return num;
}
}
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ArrayList studentList = getStudentList();
writerList(studentList);
ArrayList readList = readList();
for (Student student : readList) {
System.out.println(student);
}
TreeSet set = new TreeSet<>();
// 添加到 set 中去重排序
// 注意:必须要实现 comparable 接口,或者传入比较器
set.addAll(readList);
// 重新放入到 list 中
// 重新写入
readList.clear();
readList.addAll(set);
writerList(readList);
ArrayList readList2 = readList();
for (Student student : readList2) {
System.out.println(student);
}
}
// 键盘输入学生,并且返回装好学生的数组
public static ArrayList getStudentList(){
ArrayList list = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
while (list.size() < 6) {
System.out.println("请按格式(姓名,性别,年龄)输入学生:");
String string = scanner.nextLine();
try {
// 切割
String[] split = string.split(",");
String name = split[0];
String gender = split[1];
int age = Integer.parseInt(split[2]);
// 创建学生对象
Student student = new Student(name, gender, age);
// 装进数组
list.add(student);
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界,请重写!");
} catch (Exception e) {
System.out.println("格式有误,请重新输入!");
}
}
scanner.close();
return list;
}
// 把集合直接写入到文件中(序列化)
private static void writerList(ArrayList student) throws IOException {
FileOutputStream fos = new FileOutputStream("/Users/Desktop/Test/student.txt");
// 对象输出流(序列化流)
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 使用写对象的方法
oos.writeObject(student);
oos.close();
}
@SuppressWarnings("unchecked")
private static ArrayList readList() throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("/Users/Desktop/Test/student.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// 读文件
Object object = ois.readObject();
ArrayList list = (ArrayList)object;
ois.close();
return list;
}
}
http://blog.csdn.net/huzongnan/article/list