Java学习 IO流

IO 流

一.概述

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

I : input 输入

O : output 输出

二.分类

  • 按处理数据类型的不同,分为字节流和字符流

  • 按数据流向的不同,分为输入流和输出流。(入和出是相对于内存来讲的)

  • 按功能不同,分为节点流和处理流

    • 节点流:直接操作数据源

    • 处理流:对其他流进行处理

 

三.四大抽象类

3.1 InputStream

3.2 OutputStream

3.3 Reader

3.4 Writer

四.文件流

文件流 : 用来打开文件链接, 操作数据

分为以下几类

  • FileInputStream 字节输入

  • FileOutputStream 字节输出

  • FileReader 字符输入

  • FileWriter 字符输出

4.1 FileInputStream

4.1.1 概述

FilelnputStream 字节输入流,用于把某个文件已字节的形式读取进来

找到这个文件方法:

  • 相对路径∶以当前文件为准,去找其他文件,./表示当前目录, ../表示上级目录,../ ../

  • 绝对路径∶以系统跟盘符为准,比如D盘E盘

4.1.2 常用方法

4.1.3 实例

注意 : 当读取一个后后续循环将从第二个字节开始读取

package io;
​
import java.io.FileInputStream;
​
public class IO_01_FileInputStream {
    public static void main(String[] args) {
        //在Eclipse中,./定位当前项目JavaSE_08_Io
        try (FileInputStream fis = new FileInputStream(
                "./src/io/IO_01_FileInputStream.java")) {
            //单个读取,read:读取一个字节,返回读到的字节对应的ASCII码值,到达文件末尾返回-1
            int i1 = fis.read();
            System.out.println(i1);
            
            //循环读取
            int temp = 0;
            while((temp = fis.read()) != -1){
                System.out.print((char)temp);
            }
            
            //read[]:重载的read方法,可以传入字节数组,从而提高读取效率,返回值是本次读取到的个数
            //如果到达文件末尾,返回-1
            //available 可读取的字节个数
            byte[] bytes = new byte[fis.available()];
            int temp = 0;
            while((temp = fis.read(bytes)) != -1){
                //转换为字符串
                //每一次读取,数组并不会清空,所以读到几个,就把那几个转换为字符串,避免冗余数据
                System.out.print(new String(bytes,0,temp));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.2 FileReader

4.2.1 概念

FileReader 一次读取一个字符,也就是2字节,而unicode编码也是2字节,所以读取文本文件时,不会出现乱码问题

4.2.2 实例

public class IO_02_FileReader {
public static void main(String[] args) {
    try (FileReader fr = new FileReader(
            "./src/io/IO_01_FileInputStream.java")) {
        //读取一个字符,返回对应的ASCII码值,到达文件末尾,返回-1
        int i1 = fr.read();
        
        //方法重载,读取一个字符数组,返回此次读取的个数,到达文件末尾返回-1
        char[] chars = new char[500];
        int temp = 0;
        while((temp = fr.read(chars)) != -1){
            System.out.println(new String(chars,0,temp));
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

4.3 FileOutputStream

4.3.1 概述

FileOutputStream是字节输出流,用于将内存中数据写出去,需要传入文件路径,如果该文件不存在,则会自动创建(但是不会创建目录)

4.3.2 常用方法

4.3.3 实例

public class IO_03_FileOutputStream {
    public static void main(String[] args) {
        try (
        // 只传入文件路径.,是覆盖写入,会先把对应文件内容清空
        // FileOutputStream fos = new FileOutputStream("./src/test.txt");
        // 传入一个true,表示追加写入,false或不写,代表覆盖写入
        FileOutputStream fos = new FileOutputStream("./src/test.txt");) {
​
            //写出int类型,ASCII码值
            fos.write(97);
            
            //写出字节数组(ASCII码)
            byte[] bytes = { 97, 98, 99, 100 };
            fos.write(bytes);
            
            //写出字符串需要先把字符串转换为字符串数组
            String s = "墙里秋千墙外道。墙外行人,墙里佳人笑。——苏轼《蝶恋花·春景》";
            fos.write(s.getBytes());
            
            //刷缓冲
            fos.flush();    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.4 FileWriter

4.4.1 概念

FileWriter是字符输出流,输出的是字符,用于防止中文乱码

4.4.2 实例

public class IO_04_FileWrite {
    public static void main(String[] args) {
        try (
        // 覆盖写出
        FileWriter fw = new FileWriter("./src/test.txt");) {
            // 写出int类型,ASCII码
            fw.write(97);
​
            // 写出char数组
            char[] chars = { 'a', 'b', 'c' };
            fw.write(chars);
​
            // 写出字符串
            fw.write("世界微尘里,吾宁爱与憎。——李商隐《北青萝》");
​
            // 刷缓存
            fw.flush();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

五.缓冲流

【特点】

  • 主要是为了提高效率而存在的,减少物理读取次数

  • 提供readLine()、newLine()这样的便捷的方法(针对缓冲字符流)

  • 在读取和写入时,会有缓存部分,调用flush为刷新缓存,将内存数据写入到磁盘

  • 字节缓冲流和字符缓冲流相应方法使用相同

5.1 BufferedReader

public class IO_05_BufferedReader {
    public static void main(String[] args) {
        try(
                FileReader fr = new FileReader("./src/test.txt");
                BufferedReader br = new BufferedReader(fr);
                ) {
            //新增读一行功能,返回读取到的内容String,读取到末尾返回null
            String temp = null;
            while((temp = br.readLine()) != null){
                System.out.println(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.2 BufferedWriter

public class IO_06_BufferedWriter {
    public static void main(String[] args) {
        try(
                FileWriter fw = new FileWriter("./src/test.txt",true);
                BufferedWriter bw = new BufferedWriter(fw);
                ) {
            bw.write("花非花,雾非雾。 夜半来,天明去。——白居易《花非花》");
            //新增换行操作
            bw.newLine();
            bw.write("清时有味是无能,闲爱孤云静爱僧。——杜牧《将赴吴兴登乐游原》");
            bw.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

六.转换流

【特点】

  • 转换流是指将字节流向字符流的转换,主要有lnputStreamReadex.和OutputStreamWriter

  • lnputStreamReader主要是将字节流输入流转换成字符输入流

  • OutputStreamWriter主要是将字节流输入流转换成字符输出流

6.1 lnputStreamReader

public class IO_07_InputStreamReader {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("./src/test.txt");
                InputStreamReader isr = new InputStreamReader(fis);
                BufferedReader br = new BufferedReader(isr);) {
            
            int temp = br.read();
            while(temp != -1){
                System.out.println((char)temp);
                temp = br.read();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
​

6.2 OutputStreamWriter

public class IO_08_OutputStreamWriter {
    public static void main(String[] args) {
        try (
        // 字节输出流
        FileOutputStream fos = new FileOutputStream("./src/test.txt",true);
                // 转换为字符输出流
                OutputStreamWriter osw = new OutputStreamWriter(fos);
                // 字符输出缓冲流
                BufferedWriter bw = new BufferedWriter(osw);) {
            bw.write("饮散落花流水各西东。后会不知何处是,烟浪远,暮云重。——秦观《江城子·南来飞燕北归鸿》");
            bw.newLine();
            bw.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.3 处理乱码问题

//为了防止编码不一致导致的乱码问题,在转换流中可以规定编码格式
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");

七.打印流

7.1 概念

【特点】

  • 打印流是输出最方便的类

  • 包含字节打印流PrintStream,字符打印流PrintWriter.

  • PrintStream是OutputStream的子类,把一个输出流的实例传递到打印流之后,可以更加方便地输出内容,相当于把输出流重新包装一下

  • PrintStream类的print()方法被重载很多次print(int i)、print(boolean b)、print(charc)

【示例】 使用StringReader读取字符串,然后使用打印流打印到控制台。

【标准输入/输出】 Java 的标准输入/输出分别通过System.in和System.out 来代表,在默认的情况下分别代表键盘和显示器,当程序通过System.in来获得输入时,实际上是通过键盘获得输入。当程序通过System.out执行输出时,程序总是输出到屏幕。

在System类中提供了三个重定向标准输入/输出的方法

  • static void setErr(PrintStream err)重定向"标准"错误输出流

  • static void setIn(InputStream in)重定向"标准"输入流

  • static void setOut(PrintSteam out)重定向"标准"输出流

7.2 实例

public class IO_09_Print {
    public static void main(String[] args) {
        try(
                //创建字节输出流
                FileOutputStream fos = new FileOutputStream("./src/test.txt");
                //封装打印流
                PrintStream ps = new PrintStream(fos);
                ) {
            ps.println();
            ps.println("无情有恨何人觉?月晓风清欲堕时。 ——陆龟蒙《白莲》");
            ps.println(false);
            ps.println(5.53);
            
            //out就是打印流,只不过默认打印在控制台
            System.out.println("夜发清溪向三峡,思君不见下渝州。——李白《峨眉山月歌》");
            //另外system提供了修改out打印路径的方式
            System.setOut(ps);
            System.out.println("长风几万里,吹度玉门关。——李白《关山月》");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

八.数据流

8.1 概述

  • DataOutputStream和 DatalnputStream是为了不同的平台间读取数据的统一性

  • 操作系统对数据有不同的处理和保存方式,为了弥补这些差一些,Java平台提供了两个轻量级的方法

  • 只要每个平台安装jre,就可以保证数据的一致性

  • 以二进制传输

  • 数据 --> 加密 --> 传递 --> 读取 --> 解密 --> 数据

8.2 实例

读取顺序和类型,必须和写出时一样 否则会导致读取错误

public class IO_10_DataOutputStream {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("./src/date.txt");
                DataOutputStream dos = new DataOutputStream(fos)) {
            dos.writeInt(123);
            dos.writeDouble(5.76);
            dos.writeBoolean(false);
            dos.writeUTF("谁家玉笛暗飞声,散入春风满洛城。——李白《春夜洛城闻笛》");
            dos.flush();
            // 关闭资源,先打开的后关闭
            // 关闭外层,内层也会关闭
            dos.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
​
public class IO_11_DataInputStream {
    public static void main(String[] args) {
        try(FileInputStream fis = new FileInputStream("./src/data.txt");
                DataInputStream dis = new DataInputStream(fis)) {
            //读取数据
            //读取顺序和类型,必须和写出时一样
            System.out.println(dis.readInt());
            System.out.println(dis.readDouble());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readUTF());
            dis.close();
            fis.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

九.file

9.1 概述

File类是java提供对文件和文件夹(目录)进行操作的API,与平台无关的 创建,删除,重名名都可以 lO只能操作数据,File只能操作文件和文件夹

9.2 构造方法

public File(String pathname)以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。

绝对路径:是一个固定的路径,从盘符开始

相对路径:是相对于某个位置开始

lpublic File(String parent,String child)以parent为父路径,child为子路径创建File对象。

lpublic File(File parent,String child)根据一个父File对象和子文件路径创建File对象

9.3 常用方法

获取功能:

  • public String getAbsolutePath():获取绝对路径

  • public String getPath() :获取路径

  • public String getName() :获取名称

  • public String getParent():获取上层文件目录路径。若无,返回null

  • public long length() :获取文件长度(即:字节数)。不能获取目录的长度。

  • public long lastModified() :获取最后一次的修改时间,毫秒值

  • public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组

  • public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组

重命名功能:

  • public boolean renameTo(File dest):把文件重命名为指定的文件路径

判断功能

  • public boolean isDirectory():判断是否是文件目录

  • public boolean isFile() :判断是否是文件

  • public boolean exists() :判断是否存在

  • public boolean canRead() :判断是否可读

  • public boolean canWrite() :判断是否可写

  • public boolean isHidden() :判断是否隐藏

创建删除功能:

  • public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false

  • public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。 如果此文件目录的上层目录不存在,也不创建。

  • public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建

注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目 路径下。

  • public boolean delete():删除文件或者文件夹

删除注意事项:

  • Java中的删除不走回收站。

  • 要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

9.4 实例

// 创建对象
File file = new File("E:/com/a.txt");
// 获取全路径
System.out.println(file.getAbsolutePath());
// 获取文件名,包括扩展名
// 目录只获取目录名字, 如果是文件 则获取文件名+扩展名
System.out.println(file.getName());
// 获取父路径(上级目录)
String parentPath = file.getParent();
System.out.println(parentPath);
// 获取父(上级) 对象
File parentFile = file.getParentFile();
// 判断是否是文件,如果文件不存在,也是false
System.out.println(file.isFile());
// 判断是否是目录
System.out.println(file.isDirectory());
​
// 获取最后一次修改时间,返回毫秒数
long timer = file.lastModified();
System.out.println(new Date(timer));
// 判断是否存在
System.out.println(file.exists());
// 创建文件,返回布尔型,true,表示创建好了,false表示没有创建
// 只创建文件,不会创建目录
System.out.println(file.createNewFile());
// 删除,成功返回true
System.out.println(file.delete());
​
File f1 = new File("E:/a/b/c");
// 创建目录,只会创建c,a和b不会创建
System.out.println(f1.mkdir());
// 会创建所有目录
System.out.println(f1.mkdirs());
​
// 得是目录才行
f1 = new File("E:/a/b/c/d.txt");
// 如果想要创建d.txt对应的目录,不能直接创建,否则会把d.txt也当成目录
// f1.mkdirs();
// 需要先获取父目录,对父目录进行创建
File f2 = f1.getParentFile();
if (!f2.exists()) {
    f2.mkdirs();
}
f1.createNewFile();

十.对象流

10.1 概述

创建对象:

  1. new 用的最多

  2. 反射机制

  3. clone对象克隆,已过时,被序列化代替

  4. 反序列化

序列化就是把数据持久化保存在硬盘中,比如堆内存对象,保存到本地文件

反序列化就是把硬盘中序列化的数据,反序列化到内存中

  1. 对象流,就是以java对象为传输主体的IO过程java对象必须要被序列化后才能进行传输

  2. 就是把对象转换为二进制数据流的一种实现手段,通过将对象序列化,可以方便的实现对象的传输及保存

  3. 想要实现序列化,必须实现Serializable接口,该接口没有其他方法功能,仅仅是标记可以被序列化而已

数据-->序列化-->二进制流-->加密处理-->网络传输-->解密处理-->二进制流-->反序列化-->数据

10.2 注意

  • 该类必须实现java.io.Serializable接口,否则会抛出NotSerializableException

  • 该类的所有字段都必须是可序列化的。如果一个字段不需要序列化,则需要使用transient 关键字进行修饰。

10.3 序列化

public static void ser(String serPath, Object obj) throws Exception{
    FileOutputStream fos = new FileOutputStream(serPath);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    ObjectOutputStream oos = new ObjectOutputStream(bos);
        
    oos.writeObject(obj);
    oos.flush();
    oos.close();
}

10.4 反序列化

public static Object unser(String serPath) throws Exception {
    FileInputStream fis = new FileInputStream(serPath);
    BufferedInputStream bis = new BufferedInputStream(fis);
    ObjectInputStream ois = new ObjectInputStream(bis);
​
    Object obj = ois.readObject();
    ois.close();
    return obj;
}

10.5 serialVersionUID

  • 如果不加serialVersionUID每次修改类都会重新生成一个新的

  • 该目的就是序列化对象的版本控制,当serialVersionUID对应不上的时候,就会报错

  • 如果我们此次修改较小,希望向下兼容,则不需要修改

  • 如果我们删除了一个属性,或者更改了类继承等,比如不兼容旧数据,这时候就应该手动更改版本

  • 值可以随意指定,只用于对象和类之间的一个绑定关系

private static final long serialVersionUID = 1L;

10.6 Transient

  • transient修饰后,不能被序列化,该属性的值,不会进行序列化存储

  • 可以把没必要的字段进行transient修饰,降低序列化文件大小,从而提高反序列化效率

private transient String name;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值