
1. 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理
2. 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理
读取:
- File file=new File("hello.txt");
- FileReader fr=new FileReader(file);
-
- //1.空参构造器
- int data = fr.read();//返回读入的一个字符,到末尾返回-1
- while (data!=-1){
- System.out.print((char)data);
- data= fr.read();
- }
-
- //2.char[]参数
- char[] cbuffer=new char[5];
- int len;//记录字符个数
- while ((len= fr.read(cbuffer))!=-1){
- for(int i=0;i<len;i++) System.out.print(cbuffer[i];
- }
-
- fr.close();
复制:
- //复制文件
- File file=new File("hello.txt");
- FileReader fr=new FileReader(file);
-
- //若文件不存在,则创建新文件;文件存在的话可以设置 append参数 选择覆盖还是追加
- File file1=new File("hello1.txt");
- FileWriter fw=new FileWriter(file1,false);
-
- char[] cbuffer=new char[5];
- int len;//记录字符个数
- while ((len= fr.read(cbuffer))!=-1){
- fw.write(cbuffer,0,len);
- }
-
- fr.close();
- fw.close();
注:FileWriter的第二个参数可设置是覆盖还是追加。
实现对图片的复制操作:
-
- @Test
- public void testFileInputOutputStream() {
- FileInputStream fis = null;
- FileOutputStream fos = null;
- File srcFile = new File("test.jpg");
- File destFile = new File("test1.jpg");
-
- fis = new FileInputStream(srcFile);
- fos = new FileOutputStream(destFile);
-
- //复制的过程
- byte[] buffer = new byte[5];
- int len;
- while((len = fis.read(buffer)) != -1){
- fos.write(buffer,0,len);
- }
-
- fos.close();
- fis.close();
- }
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类 时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
-BufferedInputStream
-BufferedOutputStream
-BufferedReader
-BufferedWriter
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
当使用BufferedInputStream读取字节文件时,会一次性从文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法 flush()可以强制将缓冲区的内容全部写入输出流
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
- /*
- 实现非文本文件的复制
- */
- @Test
- public void BufferedStreamTest(){
- BufferedInputStream bis = null;
- BufferedOutputStream bos = null;
-
- //1.造文件
- File srcFile = new File("爱情与友情.jpg");
- File destFile = new File("爱情与友情3.jpg");
- //2.造流
- //2.1 造节点流
- FileInputStream fis = new FileInputStream((srcFile));
- FileOutputStream fos = new FileOutputStream(destFile);
- //2.2 造缓冲流
- bis = new BufferedInputStream(fis);
- bos = new BufferedOutputStream(fos);
-
- //3.复制的细节:读取、写入
- byte[] buffer = new byte[10];
- int len;
- while((len = bis.read(buffer)) != -1){
- bos.write(buffer,0,len);
- //4.资源关闭
- //要求:先关闭外层的流,再关闭内层的流
- bos.close();
- bis.close();
- //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
- }
-
- /*
- 使用BufferedReader和BufferedWriter实现文本文件的复制
- */
- @Test
- public void testBufferedReaderBufferedWriter(){
- BufferedReader br = null;
- BufferedWriter bw = null;
- //创建文件和相应的流
- br = new BufferedReader(new FileReader(new File("dbcp.txt")));
- bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));
-
- //读写操作
- //方式一:使用char[]数组
- char[] cbuf = new char[1024];
- int len;
- while((len = br.read(cbuf)) != -1){
- bw.write(cbuf,0,len);
- bw.flush();
- }
- //方式二:使用String,每次读一行数据
- String data;
- while((data = br.readLine()) != null){
- //方法一:
- bw.write(data + "\n");//data中不包含换行符
- //方法二:
- bw.write(data);//data中不包含换行符
- bw.newLine();//提供换行的操作
- }
- //关闭资源
- if(bw != null){
- bw.close();
- br.close();
- }
注:BufferedReader有一个额外的方法 readLine(),可以读一行的字符。
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
ObjectOutputStream和 ObjectInputStream不能序列化static和transient修饰的成员变量
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从 而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现Serializable接口
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
private static final long serialVersionUID;
serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。
如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议, 显式声明。
若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
1.创建一个 ObjectOutputStream
2.调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
3.注意写出一次,操作flush()一次
反序列化
1.创建一个 ObjectInputStream
2.调用 readObject() 方法读取流中的对象
强调:如果某个类的属性不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化 。
- /**
- * 对象流的使用
- */
- public class ObjectInputOutputStreamTest {
-
- /*
- 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
- 使用ObjectOutputStream实现
- */
- @Test
- public void testObjectOutputStream(){
- //1.
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
- //2.
- oos.writeObject(new String("我爱北京天安门"));
- oos.flush();//刷新操作
-
- oos.writeObject(new Person("王铭",23));
- oos.flush();
-
- oos.writeObject(new Person("张学良",23,1001,new Account(5000)));
- oos.flush();
-
-
- //3.
- oos.close();
- }
-
- /*
- 反序列化:将磁盘文件中的对象还原为内存中的一个java对象
- 使用ObjectInputStream来实现
- */
- @Test
- public void testObjectInputStream(){
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"));
-
- Object obj = ois.readObject();
- String str = (String) obj;
-
- Person p = (Person) ois.readObject();
- Person p1 = (Person) ois.readObject();
-
- System.out.println(str);
- System.out.println(p);
- System.out.println(p1);
-
- ois.close();
-
- }
-
-
- import java.io.Serializable;
-
- /**
- * Person需要满足如下的要求,方可序列化
- * 1.需要实现接口:Serializable
- * 2.当前类提供一个全局常量:serialVersionUID
- * 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
- * 也必须是可序列化的。(默认情况下,基本数据类型可序列化)
- *
- * 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
- */
- public class Person implements Serializable{
-
- public static final long serialVersionUID = 475463534532L;
-
- private String name;
- private int age;
- private int id;
- private Account acct;
-
- public Person(String name, int age, int id) {
- this.name = name;
- this.age = age;
- this.id = id;
- }
-
- public Person(String name, int age, int id, Account acct) {
- this.name = name;
- this.age = age;
- this.id = id;
- this.acct = acct;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", id=" + id +
- ", acct=" + acct +
- '}';
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- 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 Person(String name, int age) {
-
- this.name = name;
- this.age = age;
- }
-
- public Person() {
-
- }
- }
-
- class Account implements Serializable{
- public static final long serialVersionUID = 4754534532L;
- private double balance;
-
- @Override
- public String toString() {
- return "Account{" +
- "balance=" + balance +
- '}';
- }
-
- public double getBalance() {
- return balance;
- }
-
- public void setBalance(double balance) {
- this.balance = balance;
- }
-
- public Account(double balance) {
-
- this.balance = balance;
- }
- }
转换流提供了在字节流和字符流之间的转换,很多时候我们使用转换流来处理文件乱码问题,实现编码和解码的功能。
InputStreamReader
实现将字节的输入流按指定字符集转换为字符的输入流。
需要和InputStream“套接”。
public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)
OutputStreamWriter
实现将字符的输出流按指定字符集转换为字节的输出流。
需要和OutputStream“套接”。
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
- //解码:字节、字节数组 --->字符数组、字符串
- //编码:字符数组、字符串 ---> 字节、字节数组
-
- /*
- InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
- */
- @Test
- public void test1() {
-
- FileInputStream fis = new FileInputStream("dbcp.txt");
- //参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
- InputStreamReader isr = new InputStreamReader(fis,"UTF-8");//使用系统默认的字符集
-
- char[] cbuf = new char[20];
- int len;
- while((len = isr.read(cbuf)) != -1){
- String str = new String(cbuf,0,len);
- System.out.print(str);
- }
-
- isr.close();
-
- }
-
- /*
- 综合使用InputStreamReader和OutputStreamWriter
- */
- @Test
- public void test2() {
- //1.造文件、造流
- File file1 = new File("dbcp.txt");
- File file2 = new File("dbcp_gbk.txt");
-
- FileInputStream fis = new FileInputStream(file1);
- FileOutputStream fos = new FileOutputStream(file2);
-
- InputStreamReader isr = new InputStreamReader(fis,"utf-8");
- OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
-
- //2.读写过程
- char[] cbuf = new char[20];
- int len;
- while((len = isr.read(cbuf)) != -1){
- osw.write(cbuf,0,len);
- }
-
- //3.关闭资源
- isr.close();
- osw.close();
- }
-