File和IO流


1、File的概述和使用

File和IO流的概述

  IO流可以将数据从本地文件中读取出来,将数据从内存保存到本地文件。File是文件和目录路径名的抽象表示,虚拟机通过读取文件地址,对文件/文件夹进行操作;File仅仅是一个路径名,可以是存在的也可以是不存在的。绝对路径是从盘符开始的,相对路径是相对当前模块性的路径。


File的构造

方法名解释
File(String pathname)通过字符串路径获取File实体类
File(String parent, String child)在指定父文件夹路径下,根据子文件路径创建File实体类
File(File parent, String child)从父路径名和子路径字符串创建File实体类

File的创建方法

方法名解释
public boolean createNewFile()创建一个文件
public boolean mkdir()创建一个单极文件夹
public boolean mkdirs()创建一个多级文件夹

File的其他方法

方法名解释
public boolean delete()删除由此抽象路径名表示的文件或空文件夹(不走回收站)
public boolean isDirectory()根据抽象路径名判断File是否为目录
public boolean isFile()根据抽象路径名判断是否是文件
public boolean exists()根据抽象路径名判断文件是否存在
public String getName()根据抽象路径名获取文件或目录的名称
public File[] listFile()进入文件夹,获取这个文件夹里的说有文件和文件夹的File对象(包括隐藏文件),并封装到一个数组中

代码练习 删除一个文件夹,

import java.io.File;

public class Demo {

    public static void main(String[] args) {
        File file = new File("D:\\develop\\apache-maven-3.6.1");

    }

    public static void deleteDir(File src) {
        File[] files = src.listFiles();
        for (File file : files) {
            // 是文件则直接删除
            if (file.isFile()) {
                file.delete();
            } else {
                // 用递归知道src.文件和空文件夹全部删除完毕,才可以删除src
                deleteDir(file);
            }
        }
        src.delete();
    }

}

代码练习 获取一个文件夹中所有文件类型的个数

import java.io.File;
import java.util.HashMap;

public class Demo {

    public static void main(String[] args) {

        // 选择File模块下的文件
        File file = new File("File");
        // 键代表文件类型,value代表出现次数
        HashMap<String, Integer> hm = new HashMap<>();
        getCount(hm,file);
    }

    private static void getCount(HashMap<String, Integer> hm, File file) {
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isFile()) {
                String fileName = f.getName();
                String[] split = fileName.split("\\.");
                String key = split[split.length - 1];
                if (hm.containsKey(key)) {
                    // 如果键存在则进行value累加
                    Integer value = hm.get(key);
                    value ++;
                    hm.put(key,value);
                } else {
                    // 如果不存在则put
                    hm.put(key,1);
                }
            } else {
                getCount(hm,f);
            }
        }
    }

}

2、IO流

IO流的概述

  IO流的作用 为了实现数据的永久化存储,数据从内存到硬盘的过程叫读,数据从硬盘到内存的过程叫写。
  IO流的分类 Input输入流读,Output输出流写;从数据类型分为:字节流,字符流(只能操作纯文本文件)。
  纯文本文件 一般用记事本打开可以看到的非乱码文件被认为是纯文本文件。


2.1、字节流

字节流写的步骤

  创建字节输出流对象、写数据、关闭流释放资源。


字节流的构造

方法名解释
FileOutputStream(File file)创建文件输出流由指定的 File对象表示文件
FileOutputStream(FileDescriptor fdObj)创建文件输出流写入指定的文件描述符,表示与文件系统中实际文件的现有连接
FileOutputStream(File file, boolean append)创建文件输出流由指定的 File对象表示文件,参数2表示是否开启续写开关
FileOutputStream(String name)创建文件输出流以指定的名称写入文件
FileOutputStream(String name, boolean append)创建文件输出流以指定的名称写入文件,参数2表示是否开启续写开关

字节流写数据的方法

方法名解释
void write(int b)一次写一个字节数据
void write(byte[] b)一次写一个字节数组数据
void write(byte[], int off, int len)一次写一个字节数组的部分数据

代码练习 字节流写数据

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

public class FileOutputDemo1 {

    public static void main(String[] args) {
        FileOutputStream fos = null;
        // 创建字节流输入对象,操作形参中的文件
        try {
            fos = new FileOutputStream("E:\\a.txt", true);
            // 在E盘中的a.txt文件中写数据
            byte[] bytes = {78, 79, 80};
            fos.write(bytes, 1, 2);
            // fos.write("\r\n".getBytes())	// 表示换行
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                // 关闭流,释放资源
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

注意

  文件不存在则,自动创建;文件存在,读写数据时会先把文件内容清空;字节流写数据时,写入的时码表中对应的字符;close()方法是最后一步。"\r\n".getBytes() 获取字符串换行的字节数据。


字节流读的步骤

  创建字节输入流对象、读数据、关闭流释放资源。


构造方法

方法名解释
FileInputStream(File file)通过文件路径或文件对象创建一个FileInputStream对象
FileInputStream(FileDescriptor fdObj)通过文件的描述符fdObj创建一个FileInputStream对象
FileInputStream(String name)通过文件的路径名创建一个FileInputStream对象

代码练习 字节流读数据

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

public class FileInputDemo1 {

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("IO\\a.txt");
            int i;
            while ((i = fis.read()) != -1) {
                // 在读写的时候得到的都是编码中对应的字符
                System.out.println((char)i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

字节流读写练习 文件复制

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

/**
 * 文件复制- 读出来写进入
 */
public class FileInputDemo2 {

    public static void main(String[] args) {

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("E:\\a.txt");
            fos = new FileOutputStream("IO\\a.txt");

			byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
            	// 一次写一个数组的部分
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null && fos != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

2.2、字节缓存流

  字节缓冲流 相当于提供了一个缓冲区,读写数据时针对的是缓冲区的数据,用于提高效率。
  
构造方法

方法名解释
BufferedOutputStream(OutputStream out)字节缓存输出流
BufferedInputStream(InputStream in)字节缓冲输入流

文件复制 缓冲流

import java.io.*;

/**
 * 文件复制- 读出来写进入
 */
public class FileInputDemo2 {

    public static void main(String[] args) {

		// 在底层创建了一个长度为8192的字节数组
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        
        try {
            bis = new BufferedInputStream(new FileInputStream("E:\\a.jpg"));
            bos = new BufferedOutputStream(new FileOutputStream("IO\\a.jpg"));
            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null && bos != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

缓冲流提高效率的原理

  减少了硬盘与内存之间的传输次数,每次按照8192的字节数组进行传输。

2.3、字符流

   字符流的意义 在于,它可以解决文本文件的中文乱码问题。

  字符流 = 字节流 + 编码表 (一般使用GBK码表,两个字节表示一个汉字,或者UTF-8编码,三个字节表示一个汉字)。

编码

方法名解释
byte[] getBytes()使用默认字符集将该String编码为一系列字节,将结果存储到字节数组
byte[] getBytes(String charsetName)使用指定字符集将该String编码为一系列字节,将结果存储到字节数组

解码

方法名解释
String(byte[] bytes)使用默认字符集解码指定的字节数组来构造新的String
String(byte[] bytes, String charsetName)使用指定字符集解码指定的字节数组来构造新的String

  
字节流读取中文出现乱码的原因

  因为字节流一次只读取一个字节,相当于读取了一个汉字的部分,因为单个汉字由两个或三个字节组成。
  

字符流写数据的方法

方法名解释
void write(int c)写一个字符
void write(char[] cbuf)写出一个字符数组
void write(char[] cbuf, int off, int len)写一个字符数组的部分
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的部分

代码练习 字符流写数据

import java.io.FileWriter;
import java.io.IOException;

public class FileWriteDemo1 {

    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("IO\\a.txt", true);

            String s = "冲哥yyds";
            char[] chars = {19, 80, 81, 98};
            // 如果写的是字符串则写入的是字符串本身
            fw.write(s, 0, 2);
            // 如果写入的是数字或其他数据类型,则写入的是码表中对应的字符
            fw.write(chars);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
方法名解释
flush()刷新流,可以继续写入

代码练习 字符流读数据

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

public class FileReaderDemo1 {

    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("IO\\a.txt");
            char[] chars = new char[1024];
            int len;
            while ((len = fr.read(chars)) != -1) {
                System.out.println(new String(chars, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.4 字符缓冲流

字符缓冲流 读数据

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

public class BufferedReaderDemo1 {

    public static void main(String[] args) {
        BufferedReader br = null;

        try {
            br = new BufferedReader(new FileReader("IO\\a.txt"));
            char[] chars = new char[1024];
            int len;
            while ((len = br.read()) != -1) {
                System.out.println(new String(chars, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

  
字符缓冲流的特有方法

方法名解释
void newLine()写一行行分隔符,相当于写一个换行
public String readLine()读整行,读到结尾,为null

字符缓冲流 写数据

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo1 {

    public static void main(String[] args) {
        BufferedWriter bw = null;

        try {
            bw = new BufferedWriter(new FileWriter("IO\\a.txt", true));
            char[] chars = {97, 98, 99, 90};
            bw.write(chars, 0, 3);
            bw.write("你好");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3、转换流

  转换流的分类 InputStreamReader(输入流),OutputStreamWriter(输出流)。

  InputStreamReader 是从字节流到字符流的桥梁:它读取字节,并使用指定的charset将其解码为字符。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

InputStreamReader

方法名解释
InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader
InputStreamReader(InputStream in, String charsetName)创建一个使用命名字符集的InputStreamReader
InputStreamReader(InputStream in, Charset cs)创建一个使用给定字符集的InputStreamReader
InputStreamReader(InputStream in, CharsetDecoder dec)创建一个使用给定字符集解码器的InputStreamReader

  OutputStreamWriter 是从字符流到字节流的桥梁:使用指定的charset将写入的字符编码为字节。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

OutputStreamWriter

方法名解释
OutputStreamWriter(OutputStream out)创建一个使用默认字符编码的OutputStreamWriter
OutputStreamWriter(OutputStream out, String charsetName)创建一个使用命名字符集的OutputStreamWriter
OutputStreamWriter(OutputStream out, Charset sc)创建一个使用给定字符集的OutputStreamWriter
OutputStreamWriter(OutputStream out, CharsetEncoder enc)创建一个使用给定字符编码器的OutputStreamWriter

转换流 代码演示

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class BufferedWriterDemo1 {

    public static void main(String[] args) throws Exception {
        // 字节流转换为字符流, 给定字符集
        InputStreamReader irs = new InputStreamReader(new FileInputStream("E:\\a.txt","gbk"));
        int len;
        while ((len = irs.read()) != -1) {
        	// 若不给定字符集则读出的是乱码
            System.out.println((char) len);
        }
        irs.close();

        // 字符流转换为字节流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\a.txt"),"UTF-8");
        // 若不给定字符集则写入的是乱码
        osw.write("六月九号");
        osw.close();
    }
}

   jdk11之后,字符流提供了可以指定编码表的构造,可以代替转换流解决乱码。

public static void main(String[] args) throws Exception {
	FileReader fr = new FileReader("E:\\a.txt", forName("gbk"));
    int ch;
    while ((ch = fr.read()) != -1) {
  	System.out.println((char)ch);
	}
 	fr.close();
}

4、对象操作流

  对象操作流的 基本特点,把对象以字节的形式写入文件,当我们需要查看内容时再次读出来。

  对象操作流 分类,ObjectInputStream(对象操作输入流),ObjectOutputStream(对象操作输出流)。

  对象操作输出流(对象序列化流):将对象写到本地文件中,或者在网络中传输对象。对象操作输入流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象。

对象操作流 写数据

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class BufferedWriterDemo1 {

    public static void main(String[] args) throws Exception {

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));

        Student student = new Student("张三", 23);
        oos.writeObject(student);
        oos.close();
    }
}

注意

  被对象操作流操作的对象必须实现 Serializable 接口,如果想要这个类的对象被序列化,那么这个类必须实现 Serializable 接口。

对象操作流 读数据

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class BufferedWriterDemo1 {

    public static void main(String[] args) throws Exception {

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
        Student stu  = (Student) ois.readObject();
        System.out.println(stu);    // Student{name='张三', age=23}
        ois.close();
    }
}

问题

  当我们进行序列化之后,再改动文件内容后,进行反序列化时,会出现异常,原因是没有自己设置 serialVersionID 序列号时,虚拟机会自动给我们一个 serialVersionID 序列号,但是我们修改文件前后,虚拟机对给出的 serialVersionID 序列号,进行了更变,因此会出现异常,解决方案是自己设置 serialVersionID 序列号。

对象操作流 代码练习

import java.io.*;

public class BufferedWriterDemo1 {

    public static void main(String[] args) throws Exception {

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
        Student student1 = new Student("张三", 23);
        Student student2 = new Student("李四", 24);
        Student student3 = new Student("王五", 25);
        oos.writeObject(student1);
        oos.writeObject(student2);
        oos.writeObject(student3);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
        while (true) {
            try {
                Object o = ois.readObject();
            } catch (EOFException e) {
                // 这个异常表示读到结束
                break;
            }
        }
        ois.close();
    }
}
import java.io.*;
import java.util.ArrayList;

public class BufferedWriterDemo1 {

    public static void main(String[] args) throws Exception {

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
        Student student1 = new Student("张三", 23);
        Student student2 = new Student("李四", 24);
        Student student3 = new Student("王五", 25);

        ArrayList<Student> list = new ArrayList<>();
        list.add(student1);
        list.add(student2);
        list.add(student3);
        // 将序列化数据作为一个整体写入
        oos.writeObject(list);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
        // 反序列化时读集合
        ArrayList<Student> list1 = (ArrayList<Student>) ois.readObject();
        list1.forEach(s-> System.out.println(s));
        ois.close();
    }
}

5、Properties

  properties 可以被看作是一个 Map集合,一般用于存储字符串;

Properties的特有方法

方法名构造
Object setProperty(String key, String value)相当于HashMap的put方法
String getProperty(String key)根据键获取值
Set stringPropertyNames()从属性列表中返回一个不可修改的键集
void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
void load(Reader reader)从输入字符流读取属性列表(键和元素对)
void store(OutputStream out, String comments)将此属性列表(键和元素对)写入到Properties文件中
void store(Writer writer, String comments)将此属性列表(键和元素对)写入到Properties文件中

代码练习 加载

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo {

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

        Properties prop = new Properties();
        FileReader fr = new FileReader("prop.properties");
        prop.load(fr);
        fr.close();

        System.out.println(prop);
    }
}

代码练习 写入

import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo {

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

        Properties prop = new Properties();
        prop.put("李四","24");
        prop.put("王五","25");

        FileWriter fw = new FileWriter("prop.properties",true);
        prop.store(fw,"这里注释");
        fw.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值