第12章_IO流

第12章_IO流

File类

引入

对文件操作

package com.ymj.test11IO;

import
java.io.File;
import
java.io.IOException;

public class
Test01 {
   
public static void main(String[] args) throws IOException {

        File f =
new File("d:\\test.txt");
       
File f1 = new File("d:/test.txt");
       
//File.separator 属性可以帮助获取当前操作系统的路径拼接符号
       
File f2 = new File("d:" + File.separator + "test.txt");
       
//常用方法
       
if (f.exists()){
            f.delete()
;
       
}else{
            f.createNewFile()
;
       
}
        System.
out.println(f == f1);//比较地址
       
System.out.println(f.equals(f1));//比较路径
       
//路径:绝对路径:f.getAbsolutePath(),相对路径:f.getPath()f.toString (相对路径)
   
}
}

对目录操作

包含文件的方法

跟目录相关的方法

package com.ymj.test11IO;

import
java.io.File;
import
java.io.IOException;

public class
Test01 {
   
public static void main(String[] args) throws IOException {

        File f =
new File("d:\\test.txt");
       
File f1 = new File("d:/test.txt");
       
//File.separator 属性可以帮助获取当前操作系统的路径拼接符号
       
File f2 = new File("d:" + File.separator + "test.txt");
       
//常用方法
       
if (f.exists()) {
            f.delete()
;
       
} else {
            f.createNewFile()
;
       
}
        System.
out.println(f == f1);//比较地址
       
System.out.println(f.equals(f1));//比较路径
        
//路径:绝对路径:f.getAbsolutePath(),相对路径:f.getPath()f.toString (相对路径)

       
File file = new File("D:\\a\\b\\c");
//        创建目录
       
file.mkdir();
       
file.mkdirs();

       
//删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除
       
file.delete();
       
//查看
       
String[] list = file.list();
        for
(String s : list) {
            System.
out.println(s);
       
}
        System.
out.println("===============");
       
File[] files = file.listFiles();//作用更加广泛
       
for (File fi :
                files) {
            System.
out.println(fi.getName() + "," + fi.getAbsolutePath());
       
}

    }
}

IO流

引入

  1. File类:封装文件/目录的各种信息,对目录/文件进行操作,但不可以获取到文件/目录中的内容。
  2. 引入:IO流

I/O :Input/Output的缩写,用于处理设备之间的数据传输

  1. 形象理解

  1. IO流的体系结构

读取文件内容FileReader

一个字符一个字符的将文件中的内容读取到程序中了

package com.ymj.test11IO;

import
java.io.File;
import
java.io.FileNotFoundException;
import
java.io.FileReader;
import
java.io.IOException;

public class
Test02 {
   
public static void main(String[] args) throws IOException {
       
//文件 -> 程序
       
//1.有一个文件: -> 创建一个File类的对象
       
File f = new File("d:\\Test.txt");
       
//2.利用FileReader这个流,接入源文件上 -> 创建一个FileReader流对象
       
FileReader fr = new FileReader(f);
//        3.进行读取动作
       
//到了文件结尾,读取的地址为-1
       
int n = fr.read();
        while
(n != -1) {
            System.
out.println(n);
           
n = fr.read();
       
}

       
int n1;
        while
((n1 = fr.read()) != -1) {
            System.
out.println(n1);
       
}
       
//4.关闭流
       
//流,数据库,网络资源,靠jvm本身无法关闭,必须手动关闭;
       
fr.close();
   
}
}

一次性读取五个字符

利用缓冲数组

package com.ymj.test11IO;

import
java.io.File;
import
java.io.FileReader;
import
java.io.IOException;

public class
Test03 {
   
public static void main(String[] args) throws IOException {
       
//文件 -> 程序
       
//1.有一个文件: -> 创建一个File类的对象
       
File f = new File("d:\\Test.txt");
       
//2.利用FileReader这个流,接入源文件上 -> 创建一个FileReader流对象
       
FileReader fr = new FileReader(f);
//        3.进行读取动作
       
//到了文件结尾,读取的地址为-1
      
char[] ch = new char[5];
       int
len = fr.read(ch);//一次性读取五个,返回该数组的有效长度
       
while(len!=-1){
           
for (int i = 0; i < len; i++) {
                System.
out.println(ch[i]);
           
}
//            方式2
           
String str = new String(ch,0,len);
           
System.out.println(str);
           
len = fr.read(ch);
       
}
       
//4.关闭流
       
//流,数据库,网络资源,靠jvm本身无法关闭,必须手动关闭;
       
fr.close();
   
}
}

FileWriter

      

 File f1 = new File("d:\\Demo.txt");
       
FileWriter fw = new FileWriter(f1, false);//默认false,覆盖原内容,true为追加内容
       
String str = "Hello Java !@";
        for
(int i = 0; i < str.length(); i++)
            fw.write(str.charAt(i))
;
//        fw.write(str);
       
fw.close();

利用FileReader、FileWriter文件复制

package com.ymj.test11IO;

import
java.io.File;
import
java.io.FileReader;
import
java.io.FileWriter;
import
java.io.IOException;

public class
Test04 {
   
public static void main(String[] args) throws IOException {
       
//源文件
       
File f1 = new File("d:\\Test.txt");
       
//目标文件
       
File f2 = new File("d:\\Test02.txt");
       
//Input
       
FileReader fr = new FileReader(f1);
       
//Out
       
FileWriter fw = new FileWriter(f2);
       
//复制
       
//[1] 一个一个字符复制
       
int n = fr.read();//n为读取的ASC
        while (n != -1) { //文件末尾ASC=-1
            fw.write(n);
           
n = fr.read();
       
}
       
//[2] 利用缓冲字符数组
       
char[] ch = new char[5];
        int
len = fr.read(ch);//返回值是ch的有效长度
        while(len!=-1){//读取到最后,文件末尾len = -1
            fw.write(ch,0,len);
           
len = fr.read(ch);
       
}
       
//[3] 利用缓冲字符数组,转为字符串
       
char[] ch1 = new char[5];
        int
len1 = fr.read(ch);
        while
(len1!=-1){
            String s =
new String(ch1,0,len1);
           
fw.write(s);
           
len1 = fr.read(ch1);
       
}
       
//6.关闭流,倒着关闭
       
fw.close();
       
fr.close();
   
}
}

利用try-catch-final解决异常

package com.ymj.test11IO;

import
java.io.*;

public class
Test05 {
   
public static void main(String[] args) {
       
//源文件
       
File f1 = new File("d:\\Test.txt");
       
//目标文件
       
File f2 = new File("d:\\Test02.txt");
       
//Input
       
FileReader fr = null;
       
FileWriter fw = null;
        try
{
            fr =
new FileReader(f1);
           
//Out
           
fw = new FileWriter(f2);
           
//复制
           
//[1] 一个一个字符复制
           
//n为读取的ASC
           
int n = fr.read();
            while
(n != -1) {
                fw.write(n)
;
               
n = fr.read();
           
}
           
//[2] 利用缓冲字符数组
           
char[] ch = new char[5];
            int
len = fr.read(ch);
            while
(len != -1) {
                fw.write(ch
, 0, len);
               
len = fr.read(ch);
           
}
           
//[3] 利用缓冲字符数组,转为字符串
           
char[] ch1 = new char[5];
            int
len1 = fr.read(ch1);
            while
(len1 != -1) {
                String s =
new String(ch1, 0, len1);
               
fw.write(s);
                
len1 = fr.read(ch1);

           
}
        }
catch (FileNotFoundException e) {
            e.printStackTrace()
;
       
} catch (IOException e) {
            e.printStackTrace()
;
       
} finally {
           
//6.关闭流,倒着关闭
           
try {
               
if (fw != null)
                    fw.close()
;
           
} catch (IOException e) {
                e.printStackTrace()
;
           
}
           
try {
               
if (fr != null)
                    fr.close()
;
            
} catch (IOException e) {
                e.printStackTrace()
;
           
}

        }
    }
}

FileStreamReader读取文件

注意:

  1. 文件是UTF-8存储的,英文字符占1个字节,中文字符占3个字节;如果用字节流读取的话,1个中文字符会读取出三个ASC码;
  2. 文件是文本文件,那么就不要使用字节流读取了,建议使用字符流
  3. read()读取一个字节,但返回值是int类型,而不是byte类型
    1. read()方法底层做了处理,让返回的数据都是“正数”
    2. 就是为了避免如果字节返回的是-1的话,无法判断是读入的字节还是文件结尾。

利用字节流读取非文本文件

缓冲字节流(处理流)BufferedInputStream

  1. 利用缓冲区

想要完成上面的效果,单纯的靠FileInputStream,FileOutputStream是不可以完成的,这个时候就需要功能的加强,需要引入新的流(在FileInputStream,FileOutputStream外面再套一层流):BufferedInputStream,BufferedOutputStream -> 处理流

package com.ymj.test11IO;

import
java.io.*;

public class
Test06 {
   
public static void main(String[] args) throws IOException {
        File f1 =
new File("d:\\lol.png");
       
File f2 = new File("d:\\lol2.png");
//        FileInputStream fi = new FileInputStream(f1);
//        FileOutputStream fo = new FileOutputStream(f2);
       
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f1));
       
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f2));
        byte
[] bt = new byte[1024 * 6];
        int
len = bis.read(bt);
        while
(len != -1) {
            bos.write(bt
,0,len);
//            bos.flush(); //底层 调用fushBuffer()方法 自动刷新缓冲区
           
len = bis.read(bt);
       
}
       
//关闭流时,高级流包含低级流时,当高级流关闭了,其包含的流也会自动关闭
       
bos.close();
       
bis.close();
   
}
}

三个方法复制非文本文件的效率

  1. 读一个字节,写入一个字节

复制完成时间:2147

  1. 利用缓冲字节数组

2

  1. 利用缓冲区

1

缓冲字符流(处理流)-BufferReader、BufferWriter

package com.ymj.test11IO;

import
java.io.*;

public class
Test07 {
   
public static void main(String[] args) throws IOException {
        File f1 =
new File("d:\\Test.txt");
       
File f2 = new File("d:\\Demo.txt");
       
BufferedReader br = new BufferedReader(new FileReader(f1));
       
BufferedWriter bw = new BufferedWriter(new FileWriter(f2));
//方式2;
//        char[] ch = new char[1024];
//        int n = br.read(ch);
//        while (n!=-1){
//            bw.write(ch,0,n);
//            n = br.read(ch);
//        }
        //
方式3:读取String,每次读取文本文件中一行,返回字符串
       
String str = br.readLine();
        while
(str!=null){
            bw.write(str)
;
           
bw.newLine();//新启动一行
           
str = br.readLine();
       
}

        bw.close()
;
       
br.close();
   
}
}

转换流InputStreamReader、OutputStreamWriter

  1. 转换流:作用,将字节流和字符流进行转换。
  2. 属于字符流(看结尾)
    1. InputStreamReader:字节输入流 -> 字符输入流
    2. OutputStreamWriter:字符输出流 -> 字节输出流
  3. 图解:
  4. 将输入的字节流转换为输入的字符流,然后完成文件

package com.ymj.test11IO;

import
java.io.*;

public class
Test08 {
   
public static void main(String[] args) throws IOException {
       
//将字节流FileInputStream转换为字符流InputStreamReader
       
InputStreamReader isr = new InputStreamReader(new FileInputStream(new File("d:\\Test.txt")), "utf-8");
       
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File("d:\\Demo.txt")), “gbk”);
        char
[] ch = new char[1024];
        int
len = isr.read(ch);
        while
(len!=-1){
            osw.write(ch
,0,len);
           
len = isr.read(ch);
       
}
        osw.close()
;
       
isr.close();
   
}
}

System类对IO流的支持

  1. System.in 标准流

package com.ymj.test11IO;

import
org.junit.Test;

import
java.io.FileInputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.util.Scanner;

public class
Test09 {
   
public static void main(String[] args) throws IOException {
//        //标准的输入流:从键盘输入
//        InputStream in = System.in;
//        int n = in.read();//
等待键盘的录入,该方法是一个阻塞方法
//        System.out.println(n);
//
//        //
以前案例:从键盘录入一个int类型数据
//        //System.in管子,怼到键盘上,从键盘录入的恶化,就从这个官到程序中了
//        //Scanner的作用,扫描器,起到扫描作用,扫键盘的从这根管出来的数据
//        Scanner sc = new Scanner(System.in);
//        System.out.println(sc.nextInt());
        //Scanner
也可以扫描其他管的内容
       
Scanner sc1 = new Scanner(new FileInputStream("d:\\Test.txt"));
        while
(sc1.hasNext()){
            System.
out.println(sc1.next());
       
}
    }
}

  1. System.out PrintStream

PrintStream out = System.out;
out.println("hello");

练习:键盘录入内容输出到文件中

键盘录入的 System.in 是字节流,输入的有中文和英文,所以需要先转换为字符流

  1. 解决思路

  1. 代码

package com.ymj.test11IO;

import
java.io.*;

public class
Test10 {
   
public static void main(String[] args) throws IOException {
       
//1、先准备输入方向
       
//键盘录入
       
InputStream in = System.in;//字节流
       
//字节流转换为字符流
       
InputStreamReader isr = new InputStreamReader(in);
       
//isr上套一个缓冲流
       
BufferedReader br = new BufferedReader(isr);

       
//2、再准备输出方向
       
//准备目标文件
       
File f = new File("d:\\Demo2.txt");
       
//写入流
       
FileWriter fw = new FileWriter(f);
       
//套一个缓冲流
       
BufferedWriter bw = new BufferedWriter(fw);

       
//3.开始动作
       
String s = br.readLine();
        while
(!s.equals("exit")){
            bw.write(s)
;
           
bw.newLine();
           
s = br.readLine();
       
}
       
//4.关闭流
       
bw.close();
       
br.close();
   
}
}

数据流DataInputStream、DataOutputStream

package com.ymj.test11IO;

import
java.io.*;

public class
Test11 {
   
public static void main(String[] args) throws IOException {
       
//将内存中的基本数据类型和字符串的变量 写成 文件中
       
DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("d:\\Demo2.txt")));
       
//向外将变量写到文件中
       
dos.writeUTF("你好");
       
dos.write(1);
       
dos.close();

       
DataInputStream dis = new DataInputStream(new FileInputStream(new File("d:\\Demo2.txt")));
       
System.out.println(dis.readUTF());
       
System.out.println(dis.readInt());
       
dis.close();
   
}
}

写出的类型和读入的类型顺序 要 匹配!

对象流-ObjectInputStream,ObjectOutputStream

实现Serializable接口

操作自定义类的对象

自定义的Person类:

package com.ymj.test11IO.serializabletest;

public class
Person {
   
private int age;
    private
String name;


    private
String sex;
    public
Person() {
    }

   
public Person(int age, String name, String sex) {
       
this.age = age;
        this
.name = name;
        this
.sex = sex;
   
}

   
public int getAge() {
       
return age;
   
}

   
public void setAge(int age) {
       
this.age = age;
   
}

   
public String getName() {
       
return name;
   
}

   
public void setName(String name) {
       
this.name = name;
   
}

   
public String getSex() {
       
return sex;
   
}

   
public void setSex(String sex) {
       
this.sex = sex;
   
}
}

测试类:

package com.ymj.test11IO.serializabletest;

import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.ObjectOutputStream;

public class
Test13 {
   
public static void main(String[] args) throws IOException {
       
//序列化:将内存中对象 -》 文件:
       
//有一个对象
       
Person p = new Person(36,"ryan","boy");
       
//有对象流
       
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:\\Demo4.txt")));
       
//想外写
       
oos.writeObject(p);
       
//关闭流
       
oos.close();
       
//将对象
   
}

}

运行时异常:

出现异常的原因:

想要序列化的对象对应的类,必须实现一个接口:

public interface Serializable {
}

接口内部,什么都没有,这种接口叫标识接口

起到标识作用,只要实现这个接口的类的对象才能序列化,否则不可以。

解决方法:将Person实现这个标识接口就可以:

package com.ymj.test11IO.serializabletest;

import
java.io.Serializable;

public class
Person implements Serializable {
   
private int age;
    private
String name;


    private
String sex;
    public
Person() {
    }

   
public Person(int age, String name, String sex) {
       
this.age = age;
        this
.name = name;
        this
.sex = sex;
   
}

   
public int getAge() {
       
return age;
   
}

   
public void setAge(int age) {
       
this.age = age;
   
}

   
public String getName() {
       
return name;
   
}

   
public void setName(String name) {
       
this.name = name;
   
}

   
public String getSex() {
       
return sex;
   
}

   
public void setSex(String sex) {
       
this.sex = sex;
   
}
}

测试:发现序列化成功,Person具备了序列化的能力

二进制数据,用程序实现反序列化操作,将对象恢复到内存总来:(?没有成功->序列化的文件不能修改,最好重新序列化一遍,再进行反序列化操作解决:serialVersionUID变化,原对象修改了代码,未增加serialVersionUID,解决方法,加一个serialVersionUID;

package com.ymj.test11IO.serializabletest;

import
java.io.*;

public class
Test14 {
   
public static void main(String[] args) throws IOException, ClassNotFoundException, InvalidClassException {
        ObjectInputStream ois =
new ObjectInputStream(new FileInputStream(new File("D:\\Demo4.txt")));
       
//读入内存
       
Person p = (Person) (ois.readObject());
       
System.out.println(p.toString());
//        System.out.println(o/*.toString()*/);
       
ois.close();
   
}
}

反序列化成功 将二进制 -> 内存

serialVersionUID

在Person类中加入toString方法后,反序列化会报错:

解决方法:给这个类加入一个序列版本号 serialVersionUID

IDEA中配置序列版本号

序列化细节

  1. 被序列化的类内部的所有属性,必须是可序列化的(基本数据类型都是可序列化的)
  2. static transient修饰的属性不可以被序列化(transient 保护的字段,例如密码)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值