1.流
* 流根据方向不同分为输入流和输出流,参照点为当前程序。
* 输入流用来读取数据,输出流用来写出数据
* java.io.InputStream
* 抽象类,定义了输入流的
* 读取字节方法,所有的字节流输入流都要继承自它。
*
* java.io.OutputStream
* 抽象类,定义了输出流的输出字节方法,所有的字节流输出流都要继承自它。
*
* 流分类节点流与处理流
* 节点流,也叫低级流,是真实负责读写数据的流
* 读写操作中必须要有低级流,数据源明确。
*
* 处理流,也叫高级流,读写可以没有高级流,高级流也不能独立存在,必须用于处理其他流。
* 其他流的目的是简化读写数据中的操作。
*
* java.io.FileOutputStream
* 文件输出流,是一个低级流,作用是向文件中写出字节。
2.输入流往文件写数据
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 )
* 将当前字符串按照csn字符集转换为一组字节
*/
byte[] data=str.getBytes("UTF-8");
fos.write(data);
System.out.println("写入成功!");
fos.close();
}
}
3.通过输入流往文件追加写操作
public class FOSDemo2 {
public static void main(String[] args) throws IOException {
/*
* 在创建FOS时,若指定第二个参数,并且该值为true时,则是追加写操作,
* 那么本次通过FOS写出的内容会被追加到该文件末尾。
*/
FileOutputStream fos=new FileOutputStream("fos.txt",true);
String str="天安门红旗升起";
byte[] data=str.getBytes("UTF-8");
fos.write(data);
fos.close();
}
}
4.通过输入流从文件中读出数据
public class FISDemo {
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);
}
}
5.使用文件流复制文件
public class CopyDemo1 {
public static void main(String[] args) throws IOException {
FileInputStream src=new FileInputStream("fos.txt");//读文件
FileOutputStream dsc=new FileOutputStream("fos1.txt");//写文件
byte[] data=new byte[1024*10];
int len=-1;
while((len=src.read(data))!=-1) {
dsc.write(data,0,len);
}
src.close();
dsc.close();
System.out.println("复制完毕!");
}
}
6.缓冲流
* java.io.BufferedInputStream
* java.io.BufferedOutputStream
* 缓冲字节输入输出流是一对高级流,使用它们可以加快读写效率
*
* 高级流可以处理其他流,但是无论添加了多少高级流,最底下都要有低级流。
* 因为低级流是真是读写数据的流,高级流都是处理数据的。
* 高级流处理其他流就形成了新的链接。并且有效的组合不同的高级流可以得到叠加的效果。
在这里我重写文件复制例子:
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("fos.txt");//源文件
BufferedInputStream bis=new BufferedInputStream(fis);//缓冲流
FileOutputStream fos=new FileOutputStream("fos2.txt");//将源文件的内容复制到目标文件中
BufferedOutputStream bos=new BufferedOutputStream(fos);//缓冲流
long start=System.currentTimeMillis();
int len=-1;
/*
* 缓冲流内部有一个缓冲区
* 当bis.read方法读取第一个字节时,实际上BIS回一次性读取一组字节并存入内部的字节数组中,
* 然后将第一个字节返回,当再次调用read方法时,BIS直接从字节数组中将第二个字节返回,直到字节数组中所有
* 字节全部返回时,才会再次读取一组字节,所以缓冲流也是依靠提高一次读写数据量减少读写次数来达到提高读写效率的。
*/
while((len=bis.read())!=-1) {//一次读取一个字节
bos.write(len);
}
bos.close();
long end=System.currentTimeMillis();
System.out.println("写入完毕,共耗时"+(end-start)+"毫秒");
}
}
7.对象流
对象流是一对高级流,作用是为了方便读写java中的对象。
(1)先建立一个Person类
package day07;
/**
* 当一个类需要被对象流读写,那么该类必须实现java.io.Serializable接口
*/
import java.io.Serializable;
import java.util.List;
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;
}
public String toString() {
return name+","+age+","+gender+","+otherInfo;
}
}
(2)对象输出流
java.io.ObjectOutputStream,对象输出流,可以将给定的对象转换为一组字节后写出。
public class OOSDemo {
public static void main(String[] args) throws IOException {
Person p=new Person();
p.setName("吕老师");
p.setAge(22);
p.setGender("男");
List<String> otherInfo=new ArrayList<String>();
otherInfo.add("他是一名很好的老师");
otherInfo.add("深受学生的喜爱");
otherInfo.add("往往跟同学们打成一片");
p.setOtherInfo(otherInfo);
FileOutputStream fos=new FileOutputStream("person.obj");
ObjectOutputStream oos=new ObjectOutputStream(fos);
/*
* 下面的代码实际上经历了两个操作:
* 1.oos将Person对象转换为一组字节
* 讲一个对象转换一组字节的过程称为对象序列化
* 2.再通过fos将这组字节写入到硬盘
* 将该对象转换的字节写入到硬盘,做长久保存的过程称为对象持久化。
*/
oos.writeObject(p);
oos.close();
System.out.println("写入完毕!");
}
}
(3)对象输入流
public class OISDemo {
public static void main(String[] args) throws IOException{
FileInputStream fis=new FileInputStream("person.obj");
ObjectInputStream ois=new ObjectInputStream(fis);
Person p = null;
try {
p = (Person)ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p);
ois.close();
}
}
8.字符流
* 字符流的读写单位为字符
* 字符流都是高级流,虽然以字符为单位读写数据,但实际底层还是读写字节,从字节与字符的转换工作交给了字符流来完成
* java.io.Reader:字符输入流的顶级父类
* java.io.Writer:字符输出流的顶级父类
转换流:之所以称OutputStreamWriter与InputStreamWriter为转换流,是因为大多数的字符流都只处理其他字符流,而低级流又是字节流,这就导致字符流不能处理字节流的问题,转换流就相当于一个转换器的作用,他们可以将字节流先转变为字符流,这样其他的字符流就能处理了。
(1)转换流-->字符输出流
public class OSWDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos=new FileOutputStream("osw.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos, "UTF-8");
osw.write("我爱你");
osw.write("爱的很深沉");
System.out.println("写出完毕!");
osw.close();
}
}
(2)转换流-->字符输入流
/**
* java.io.InputStreamReader
* 字符输入流,可以按照给定的字符集读取字符
* @author LvChaoZhang
*
*/
public class ISRDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("osw.txt");
InputStreamReader isr=new InputStreamReader(fis,"UTF-8");
int len=-1;
while((len=isr.read())!=-1) {
System.out.print((char)len);
}
isr.close();
}
}
9.缓冲字符流
(1)
* BufferedWriter BufferedReader
* 特点是可以按行读写字符串*
* java.io.PrintWriter
* 具有自动行刷新的缓冲字符输出流
* 创建PW时,它一定会在内部创建BufferedWriter作为缓冲功能的叠加
public class PWDemo1 {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
/*
* 提供了多种构造方法
* 其中有两个可以直接对文件进行写出操作的构造方法
* PrintWriter(File file)
* PrintWriter(String path)
*/
PrintWriter pw=new PrintWriter("pw.txt","UTF-8");
pw.println("锄禾日当午");
pw.println("汗滴禾下土");
System.out.println("写入完毕");
pw.close();
}
}
(2)
/**
* PrintWriter也提供了可以处理其他流的构造方法* 提供的方法可以传入字节流,也可以处理字符流。
* 并且,当使用这类构造方法时,可以再传入第二个参数,该参数为boolean值,该值为true时,则具有自动行刷新功能
* @author LvChaoZhang
*
*/
public class PWDemo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos=new FileOutputStream("pw1.txt");
PrintWriter pw=new PrintWriter(fos);
pw.println("你好");
pw.println("我很好");
System.out.println("写出完毕");
pw.close();
}
}
10.记事本的例子
package day07;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;
/**
* 完成记事本功能
* 要求:
* 程序启动后,要求用户输入一个文件名,然后创建该文件,之后提示用户开始输入内容
* 并将用户输入的每一行内容都写入到该文件,当用户输入“exit”时,退出程序
* @author LvChaoZhang
*
*/
public class Note {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
Scanner sc=new Scanner(System.in);
System.out.println("请输入文件名:");
String fileName=sc.nextLine();
FileOutputStream fos=new FileOutputStream(fileName);
OutputStreamWriter osw=new OutputStreamWriter(fos, "UTF-8");
PrintWriter pw=new PrintWriter(osw);
System.out.println("请你开始输入内容");
String line=null;
while(true) {
line=sc.nextLine();
if("exit".equals(line)) {
System.out.println("再见");
break;
}else {
pw.println(line);
pw.flush();
}
}
pw.close();
}
}
11.缓冲字符输入流
package day07;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* java.io.BufferedReader
* 缓冲字符输入流 特点:按行读取字符串
* @author LvChaoZhang
*
*/
public class BRDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("src/day07/BRDemo.java");
InputStreamReader isr=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);
/*
* BufferedReader提供了按行读取方法:
* String readLine()
* 连续读取若干个字符,直到读取到换行符为止,并将换行符之间读取的字符以一个字符串返回,若返回值为NULL
* 则表示读取到末尾
*
*/
String line=null;
while((line=br.readLine())!=null) {
System.out.println(line);
}
br.close();
}
}