Java IO流 FileInputStream FileOutputStream BufferedRead PrintStream File 序列化版本号,transient关键字

一、IO流的分类:

1.按照流的方向进行分类:

(1) 输入流:数据硬盘到内存,叫Input输入,或者叫Read读。
(2) 输出流:数据内存到硬盘,叫做Output输出,或者叫Write写。

2. 按照读取数据方式进行分类:

(1) 字节流:一次读取1byte,等同于一次读取8个二进制位,这种流是万能的,什么类型的文件都可以读取。
(2)字符流:一次读取1个字符,这种流只能读取纯文本文件txt。

3. Java中 顶级IO流抽象类:

  • java.io.InputStream 字节输入流
  • java.io.OutputStream 字节输出流
  • java.io.Reader 字符输入流
  • java.io.Writer 字符输出流

二、IO流使用注意事项:

  1. 创建的每一个流都是在内存和硬盘之间建立连接,用完一定要调用close()方法关闭连接
  2. 所有输出流在输出之后一定要调用flush()方法刷新

三、java.io包下需要掌握的流:

以Stream结尾的叫字节流,以Reader/Writer结尾的叫字符流。

1. 文件专属:

java.io.FileInputStream 重点
java.io.FileOutputSteam 重点
java.io.FileReader
java.io.FileWriter

2. 转换流(字节流转换为字符流):

java.io.InputStreamReader
java.io.OutputStreamWriter

3. 缓冲流专属:

java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputSteam

4. 数据流专属:

java.io.DataInputStream
java.io.DataOutputSteam

5. 标准输出流:

java.io.PrintWriter
java.io.PrintStream

6. 对象专属流:

java.io.ObjectInputStream
java.io.ObjectOutputSteam

四、FileInputStream:重点

1. 步骤:

(1)创建字节输入流对象。
(2)调用对象的read()方法一个一个读取字节。
(3)关闭流。

2. 读数据代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test{
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            //创建字节输入流对象
            fis = new FileInputStream("D:\\test.txt");//这是绝对路径,相对路径则以工程所在文件夹为起始
            int readData = 0;
            while((readData = fis.read()) != -1){//循环读取,每次读取1个字节,返回值是字节本身的ASCII码
                System.out.println(readData);
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //finally语句块中确保流一定关闭
            if(fis != null){
                //关闭流的前提是:流不为空
                try {
                    fis.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}//结果:97 98 99 100 101 102

3. 注意事项:

(1)对象read()方法返回值是int类型,即字节的ASCII码。
(2)read()方法初始指针指向第一个字节,每次调用read()方法只能读取1个字节,读取完后指针自动后移一位指向下一字节。
(3)若所有字节都已经读完,下一次调用read()方法会返回-1。

(4)创建字节输入流对象、调用read()方法、调用close()方法都需要捕获异常,可以用IDEA自动生成代码。
(5)关闭流的前提是:流不为空。
(6)一开始创建的对象为null是为了判断流是否为空,方便判断流是否需要关闭。
(7)可以使用绝对路径。如果要使用相对路径,工程Project的路径即为默认起点。

4. 代码改进:

上述代码一次只能读取一个字节,效率低。我们可以一次读取多个字节,提高程序执行效率。

int read(byte[ ] b);
一次读取b.length个字节,读到byte数组中。
返回值是读取到的字节数量,读不到任何数据返回-1。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Test{
    public static void main(String[] args) {
        FileInputStream fis = null;
        byte[] bytes = new byte[4];
        try {
            //创建字节输入流对象
            fis = new FileInputStream("D:\\test.txt");
            int readCount = 0;
            while((readCount = fis.read(bytes)) != -1){
                System.out.println(new String(bytes,0,readCount));//把本次读入到bytes数组中的字节转换成字符串,本次读入的字节即数组0~readCount中的内容。
                //为什么要这样?假如有文本中6个字节abcdef,第一次读4个输出为abcd,第二次只需要输出ef,如果不限制输出0~readCount这个范围的话第二次输出的就是efcd了。
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //finally语句块中确保流一定关闭
            if(fis != null){
                //关闭流的前提是:流不为空
                try {
                    fis.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}//结果:abcd ef

5. 该类中其他常用方法:

(1)返回流中剩余的没有读到的字节数量

int available();//文件大小不是太大的情况下,可以将byte数组设置为这个大小,一次就读完了,不需要循环。

(2)跳过n个字节不读取

long skip(long n);

五、FileOutputStream:重点

1. 步骤:

(1)创建字节输出流对象。
(2)调用对象的read()方法一个一个读取字节。
(3)刷新流。
(4)关闭流。

2. 写数据代码:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test{
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //没有该文件时会自动新建
            //fos = new FileOutputStream("D:\\TestWrite.txt");//这个构造方法会将源文件清空,然后重新写入
            fos = new FileOutputStream("D:\\TestWrite.txt",true);
            byte[] bytes ={97,98,99,100};
            fos.write(bytes);
            fos.flush();//写完一定要刷新

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3. 注意事项:

(1)对象write()方法写的是byte类型,若要写字符串需要使用字符串的getVByte()方法转为字节数组 。
(2)所有write()方法执行完后一定要使用flush()方法刷新。
(3)构造方法new FileOutputStream(name)创建的对象在write()的时候会先将文件内容清空后再写(只是清空原文件内容,第二次调用write的时候第一次write的内容不清空)。而构造方法new FileOutputStream(name,append)将append置true创建的对象在write()的时候会在原文件内容的末尾追加写,不会删除原文件内容。
(4)创建字节输出流对象、调用write()方法、调用flush()方法、调用close()方法都需要捕获异常,可以用IDEA自动生成代码。
(5)关闭流的前提是:流不为空。
(6)一开始创建的对象为null是为了判断流是否为空,方便判断流是否需要关闭。
(7)可以使用绝对路径。如果要使用相对路径,工程Project的路径即为默认起点。

六、文件复制案例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test{
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\IOcopy.jpeg");
            fos = new FileOutputStream("D:\\IOcopy1.jpeg",true);
            byte[] bytes = new byte[10 * 1024];//10kb
            int readCount = 0;
            while((readCount = fis.read(bytes)) != -1){
                fos.write(bytes,0,readCount);//读多少写多少
            }
            fos.flush();//写完一定要刷新
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if (fos != null) {//分开try关闭流,不然一个流出了异常另一个流就关不了了
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

七、FileReader/FileWriter:

  1. 字符流读写,代码类似FileInputStream/FileOutputStream,不过byte数组要换成用char数组,因为读写的是字符。
  2. void write()方法里可以加字符串。
  3. 只能操作普通.txt文件.java文件.html文件,效率高。

1.字符流写数据代码:

		//产生1000个随机数并存储到txt文件中
        public static void wirteRadom(String path){
        BufferedWriter bw = null;
        Random random = new Random();
        try {
        	//这样创建的字符流可以防止写入乱码的情况
            bw = new BufferedWriter(
                    new OutputStreamWriter(
                            new FileOutputStream(path,true), "UTF-8"));
            int i = 0;
            while (i<1000){
                bw.write(String.valueOf(random.nextInt(100)));
                i++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
          if (bw != null){
              try {
                  bw.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
        }
    }

2.字符流写数据代码:

//读取格式为“52,45,12,65,87,94”的txt文件,并赋值给int[]数组
public static int[] readRadom(String path) {
        FileReader fr = null;
        int res[] = new int[1000];
        String datas = "";
        try {
            fr = new FileReader(path);
            int data = 0;
            while ((data = fr.read()) != -1) {
                datas += (char)data;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String temps[] = datas.split(",");
        for (int i = 0; i < temps.length; i++) {
            res[i] = Integer.parseInt(temps[i]);
        }
        return res;
    }

八、BufferedReader/BufferedWriter/BufferedInputStream/BufferedOutputStream:

1. 缓冲流定义:

  • 使用这些流的时候不需要创建字符数组和字节数组,自带缓冲区,缓冲区满了才读,效率高。
  • 主要学习BufferedReader类的readLine()方法:读一行,无行可读返回null。
  • 当一个流的构造方法中需要一个流的时候,被传进来的流叫节点流,外部流叫包装流关闭流时只需要关闭包装流

2. 读数据代码:

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

public class Test{
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            FileReader fw = new FileReader("D:\\test.txt");
            br = new BufferedReader(fw);
            String readCount = " ";
            while((readCount = br.readLine()) != null){
                System.out.println(readCount);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

九、InputStreamReader/OutputStreamWriter:

1.定义:

  • 字节流转字符流。

2. 代码:

FileInputStream fis = new FileInputStream("D:\\test.txt");//字节输入流
InputStreamReader reader = new InputStreamReader(fis);//转为字符输入流

FileOutputStream fos = new FileOutputStream("D:\\test.txt");//字节输出流
OutputStreamWriter writer = new OutputStreamWriter(fos);//转为字符输出流

十、DataInputStream/DataOutputStream:

1.定义:

  • 这个流可以将数据类型一并写入文件,从这个文件中读到的数据也包含数据类型。
  • DataOutputStream写的文件,只能用DataInputStream去读,读的顺序还要和写的顺序一致,记事本也打不开这种文件。

2. DataOutputStream:

在这里插入图片描述

3. DataInputStream:

在这里插入图片描述

十一、PrintStream:

1.定义:

  • 标准的字节输出流,默认输出到控制台。
  • 标准输出流不需要手动关闭。

2.代码:

import java.io.PrintStream;

public class Test{
    public static void main(String[] args){
        System.out.println("go!");
        /*等同于*/
        PrintStream ps = System.out;
        ps.println("go!");
    }
}

我们可以改变标准输出流的输出方向,标准输出流不再指向控制台,将标准输出流输出到log文件。应用:写日志文件。

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class Test{
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream(new FileOutputStream("D:\\test.txt",true));
        System.setOut(ps);//修改输出流方向
        System.out.println("go!");
    }
}

十一、File:

1. 定义:

(1)File类和四大顶级IO抽象类没有什么关系,所以File不能完成文件的读写。
(2)一个File对象是一个文件名目录名的抽象表示形式,是一个容器。例如:D:\Program Files ,D:\Program Files\test.txt都是File对象。

2. File类中常用方法:

(1)判断是否存在:

file.exists()

(2)创建文件:

file.createNewFile()

(3)创建目录:

file.mkdir()

(4)创建多重目录:

file.mkdirs()

(5)获取文件的父路径,返回String类型:

file.parentPath()

(6)获取文件的父路径,返回File类型:

file.parentFile()

(7)获取绝对路径:

file.getAbsolutePath()

(8)获取文件名:

file.getName()

(9)判断是否是目录:

file.isDirectory()

(10)判断是否是文件:

file.isFile()

(11)获取文件最后一次修改时间,返回毫秒数:

file.lastModified()

(12)获取文件字节大小:

file.length()

(13)获取当前目录下所有子文件,返回File数组:

file.listFiles()

十二、ObjectInputStream/ ObjectOutputStream:

1. 序列化:

Java对象存储到文件中,将Java对象的状态保存下来的过程。类需要继承Serializable接口。成员变量加transient关键字表示该变量不参与序列化,即保存的的对象中该变量的值为null.。

序列化版本号:实现Serializable接口时Java虚拟机会自动生成序列化版本号(唯一性),用于区分同一个包下的同名类。相同序列化版本号的类才能进行序列化和反序列化。建议手动添加序列化版本号,不然修改代码后虚拟机会修改序列化版本号:

private static final long serialVersionUID = _____;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Test{
    public static void main(String[] args) throws IOException {
        List<User> list = new ArrayList<>();
        list.add(new User("张三",001));
        list.add(new User("李四",002));
        list.add(new User("王五",003));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Users"));
        oos.writeObject(list);//序列化
        oos.flush();
        oos.close();
    }
}
class User implements Serializable{
    private String name;
    private int id;

    public User() {
    }

    public User(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

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

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }
}

2. 反序列化:

将硬盘上的数据重新恢复到内存中,恢复成Java对象。

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Test{
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Users"));
        List<User> list = (List<User>) ois.readObject();//反序列化
        for(User user:list){
            System.out.println(user.toString());
        }
    }
}
class User implements Serializable{
    private String name;
    private int id;

    public User() {
    }

    public User(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

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

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姓蔡小朋友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值