一、File类
    一个File类对象可以代表一个文件或目录,可以实现对文件或目录的新建、删除、重命名等操作

    1. File file = new File("C:\\test.txt");
    2. 创建File类对象时,括号被必须设置文件路径
    3. 路径可以是相对路径或者是绝对路劲
    4. 绝对路径:以根目录开头的完整路径


    FIle常用方法:

    方法 说明
    boolean createNewFile() 创建新文件
    boolean delete() 删除文件
    boolean exists() 判断文件是否存在
    Boolean isFile() 判断是否是文件
    boolean isDirectory() 判断是否是目录
    long length() 返回文件长度,单位为字节
    若文件不存在,则返回0L
    String getPath() 返回此对象文件名所对应的路径
    String getAbsolutePath() 返回此对象表示的文件的绝对路径名

    在实际开发中,如需完成对File类的更多操作,可随时查阅API帮助文档

    1. File file=new File("test.txt");
    2. //判断文件是否存在
    3. if(file.exists()){
    4. //判断是否是文件
    5. if(file.isFile()){
    6. System.out.println("文件名:"+file.getName()+",文件的长度是:"+file.length()+"字节");
    7. System.out.println("文件的路径是:"+file.getPath());
    8. System.out.println("文件的绝对路径是:"+ file.getAbsolutePath());
    9. }
    10. //判断是否是目录
    11. if(file.isDirectory()){
    12. System.out.println("该文件是目录");
    13. }
    14. }else{
    15. System.out.println("文件不存在");

    流是个抽象的概念:
    是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行。
    设备可以是文件,网络,内存等。 流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流
    java中IO流分为几种?
    1、IO流概念
    流是从一端到另一端,连接了源头和目的地。
    IO流可以理解为连接程序与文件/数组/网络连接/数据库。
    2、IO流分类
    (1)按流向分类:
    输入流
    输出流
    (2)按处理数据不同分类:
    字节流:二进制,可以处理一切文件,包括:纯文本、doc、音频、视频等。
    字符流:文本文件,只能处理纯文本。
    (3)按功能不同分类:
    节点流:包裹源头。
    处理流:增强功能,提高性能。
    IO流是指一连串流动的字符,以先进先出方式发送信息的通道
    I:input,指读入操作
    O:output,指写出操作
    Java把所有流类型都封装到java.io包中,以实现输入/输出操作
    JavaOOP I/O - 图1
    JavaOOP I/O - 图2
    有底色的为常用示例类
    如何区分字节流和字符流
    看后缀:InputStream和Output Stream结尾的分别为字节输入流和字节输出流
    Reader和Writer结尾的分别为字符输出流和字符输入流
    二、流的体系结构
    抽象基类 节点流(文件流) 缓冲流(处理流的一种)
    InputStream FlieInputStream BufferedInputStream
    OutputStream OutputStream BufferedOuputStream
    Reader FileReder BufferedReader
    Writer FileWriter BufferedWriter
    输入流
    只能从中读取数据,而不能写入数据的流,实现程序从数据源中读数据
    输出流
    只能向其写入数据,而不能从中读数据的流,实现程序向目标数据源中写数据
    输入流主要由InputStream和Reader作为基类
    输出流则主要由OutputStream和Writer作为基类
    都是抽象类,无法直接实例化对象
    JavaOOP I/O - 图3
    四、字节流和字符流的概念
    字节流:
    以8位字节为操作数据单元的流,可操作二进制数据
    可细分为字节输入流、字节输出流
    字符流:
    以16位字符为操作数据单元的流,可操作文本数据
    可细分为字符输入流、字符输出流
    区别:
    操作的数据单元不同
    使用方法几乎相同
    五、按流的角色划分:节点流和处理流的概念
    节点流
    可以直接向一个特定的存储介质(如磁盘、文件)读写数据的流
    使用节点流进行读写数据操作时,程序直接连接到数据源
    处理流
    对已存在的流进行连接和封装,通过封装后的流实现数据读写操作的流
    使用处理流进行读写操作时,程序并不会直接连接到实际的数据源
    区别:
    使用处理流包装节点流,通过处理流执行输入和输出功能,让节点流与文件或磁盘等存储设置交互,可隐藏底层节点流的差异
    六、字节流
    主要功能:
    具有输入和输出操作
    主要操作byte类型数据
    基类:
    字节输出流类: OutputStream
    字节输入流类:InputStream
    6.1、字节输出流类: OutputStream(写入):
    常用方法

    方法 说明
    void close() 关闭输出流
    void flush() 刷新缓冲区
    void write(byte[] b) 将每个byte数组写入数据流
    void write(byte[] b,int off,int len) 将每一个指定范围的byte数组写入数据流
    void write(int b) 将一个字节数据写入数据流

    常见的构造方法:

    方法 说明
    FileOutputStream(
    File file)
    创建向指定File对象写数据的文件输出流
    file:指定目标文件的对象
    FileOutputStream(
    String name)
    创建向指定路径的文件写数据的文件输出流
    name:指定目标文件的路径字符串
    FileOutputStream(
    String name,
    boolean append)
    创建一个向指定路径的文件写入数据的文件输出流
    name:指定目标文件的路径字符串
    append:表示是否在文件末尾追加数据。如果为true,则表示可以在文件末尾追加数据
    1. OutputStream fos=null;
    2. try {
    3. //FileOutputStream参数①路径 参数②是否追加内容‘true’是追加
    4. // 不加‘true’的话就是默认覆盖内容第二个参数可以省略
    5. fos=new FileOutputStream("D:\\140\\test.txt",true);
    6. String str="冲冲冲!";
    7. byte[] words=str.getBytes();//将String类型转换为byte数组类型
    8. //将转换为byte数组的值放入到write中 第一个参数代表数据类型
    9. //第二参数代表截取的下标开始
    10. //第三参数代表截取的下标结束
    11. fos.write(words ,0,words.length);
    12. System.out.println("写入成功");
    13. } catch (FileNotFoundException e) {
    14. e.printStackTrace();
    15. } catch (IOException e) {
    16. e.printStackTrace();
    17. } finally {
    18. try {
    19. if(fos!=null){
    20. fos.close();
    21. }
    22. } catch (IOException e) {
    23. e.printStackTrace();
    24. }

    注意:
    使用FileOutputStream类的构造方法创建对象时
    如果相应的文件不存在,就会自动新建一个文件
    如果参数file或name表示的文件路径是一个目录,则会抛出FileNotFoundException异常
    字节输入流类:InputStream(读取)
    从文件中读数据
    与OutputStream一样,也是抽象类
    常用方法
    常用方法:

    方法 描述
    int read() 读取一个字节数据
    int read(byte[] b) 将数据读取到字节数组中
    int read(byte[] b,int off,int len) 从输入流中读取最多len长度的字节,保存到字节数组中,保存的位置从off开始
    void close() 关闭输入流
    int available() 返回输入流读取的字节数

    使用InputStream类的FileInputStream子类实现文本文件内容的读取
    常用构造方法

    方法 描述
    FileInputStream(File file) 用于创建从指定File对象读取数据的文件输入流
    file:指定目标文件数据源对象
    FileInputStream(
    String name)
    用于创建从指定路径的文件读取数据的文件输入流
    name:指定目标文件数据源路径字符串

    创建文件输入流对象的常用方式
    JavaOOP I/O - 图4
    注意:
    按字节读取并显示数据时需进行强制类型转换
    使用read()读取文件中的数据时,当返回结果为-1时,即输入流已经读到末尾
    在创建输入流对象、读取数据、关闭流时必须进行异常处理
    InputStream.read():

    1. /把读取的内容输出
    2. fis=new FileInputStream("D:\\140\\test.txt");//放入路径
    3. byte[] words=new byte[1024];//创建字节数组
    4. System.out.println("可读取得字节数:"+fis.available());
    5. int data=0;//定义一个int类型的变量接收返回的内容
    6. System.out.println("文件内容");
    7. while((data=fis.read())!=-1){//将读取到的字节放到int变量中
    8. System.out.print((char) data+" ");//将返回的内容转换为char类型
    9. }
    10. //方式一,把读取的内容存储
    11. byte[] words=new byte[1024];
    12. int len=0;
    13. while ((len=fis.read(words))>30){
    14. System.out.println(new String(words ,0,len));
    15. }
    16. //方式二,把读取的内容存储
    17. byte[] words=new byte[1024];
    18. fis.read(words);
    19. String str=new String(words);
    20. System.out.println(str.trim());
    21. }catch (FileNotFoundException e) {
    22. e.printStackTrace();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. } finally {
    26. //关闭输出流
    27. try {
    28. if(fis!=null){
    29. fis.close();
    30. }
    31. } catch (IOException e) {
    32. e.printStackTrace();

    为什么InputStream.read()读取一个byte确返回一个int呢?
    java 字节读取流的read方法一次读一个byte但返回int的原因
    读取二进制数据按字节读取,每次读一个字节(byte)。
    read()的底层是由C++实现的,返回的是unsigned byte,取值范围为[0~255],在java中没有对应的类型,所以只能用int类型接收,由Java接收得到的就是int[0、255]。
    在java中byte只能表示[0-127]的无符号数。也对应这java中int[0-127]
    那么[128-255]怎么表示?
    在java中byte的范围是[-128,127],所以[128-255]只能由int来接收。
    字符流:
    基类
    字符输出流类: Writer
    抽象类
    常用方法

    方法 描述
    void write(String str) 将str字符串中包含的字符输出到输出流中
    void write(String str,
    int off, int len)
    将字符串中从off位置开始,长度为len的字符输出到输出流中
    void close() 关闭输出流
    void flush() 刷新输出流

    Writer类的子类:字符输出流FileWriter类

    1. Writer fw=null;
    2. try {
    3. //FileWriter参数①路径 参数②是否追加内容‘true’是追加
    4. // 不加‘true’的话就是默认覆盖内容,第二个参数可以省略
    5. fw=new FileWriter("D:\\140\\test.txt",true);
    6. fw.write("预测未来的最好方式就是创造未来");//写入操作
    7. fw.flush();//*刷新缓冲区
    8. System.out.println("文件写入成功");//写入操作
    9. } catch (IOException e) {
    10. e.printStackTrace();
    11. System.out.println("文件不存在");
    12. } finally {
    13. if(fw!=null){
    14. try {
    15. fw.close();
    16. } catch (IOException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }以字符为数据处理单元向文本文件中写数据

    BufferedReader类
    Reader类的子类
    带有缓冲区,提高文件读取的效率
    把一批数据读到缓冲区
    从缓冲区内获取数据
    常用构造方法

    方法 描述
    BufferedReader(Reader in) 创建一个缓冲字符输入流

    readLine()方法
    按行读取文件中数据
    相关代码:
    JavaOOP I/O - 图5
    序列化与反序列化
    使用序列化和反序列化,方便数据传输和存储
    序列化是将对象的状态存储到特定的存储介质中的过程,
    反序列化是将特定的存储介质中数据重新构建对象的过程
    对象输出流( ObjectOutputStream ):实现序列化
    对象输入流( ObjectInputStream):实现反序列化
    实现序例化的要素
    要实现实现java.io.Serializable接口,则该类的对象是可序列化的
    JavaOOP I/O - 图6

    方法 描述 类型
    ObjectOutputStream(OutputStream out) 创建对象输出流对象 构造方法
    final void writeObject(Object obj) 将指定对象写入流 实例方法

    如何解决序列化和反序列化的版本不一致问题?
    引入serialVersionUID常量(JVM在编译时自动生成serialVersionUID常量,也可显式定义)
    使用ObjectInputStream类实现反序列化

    方法 描述 类型
    ObjectInputStream(InputStream in) 创建对象输入流对象 构造方法
    final Object readObject() 从指定位置读取对象 实例方法

    限制序例化:
    用transient关键字声明过的对象或属性不能被序例化
    序例化与反序例化代码展示:

    1. /**
    2. *User类
    3. */
    4. public class User implements Serializable {
    5. /**
    6. * 姓名
    7. */
    8. private String name;
    9. /**
    10. * 年龄
    11. */
    12. private int age;
    13. /**
    14. * 性别
    15. */
    16. private String sex;
    17. /**
    18. * 注册时间
    19. */
    20. private String time;
    21. /**
    22. * 封装属性
    23. * @return
    24. */
    25. public String getName() {
    26. return name;
    27. }
    28. public void setName(String name) {
    29. this.name = name;
    30. }
    31. public int getAge() {
    32. return age;
    33. }
    34. public void setAge(int age) {
    35. this.age = age;
    36. }
    37. public String getSex() {
    38. return sex;
    39. }
    40. public void setSex(String sex) {
    41. this.sex = sex;
    42. }
    43. public String getTime() {
    44. return time;
    45. }
    46. public void setTime(String time) {
    47. this.time = time;
    48. }
    49. /**
    50. * 输出信息的方法
    51. */
    52. public void print(){
    53. System.out.println("姓名是:"+getName()+"年龄:"+getAge()+"性别:"+getSex()+"注册时间:"+getTime());
    54. }
    55. /**
    56. * 类的无参构造方法
    57. */
    58. public User() {
    59. }
    60. /**
    61. * 类的有参构造方法
    62. * @param name
    63. * @param age
    64. * @param sex
    65. * @param time
    66. */
    67. public User(String name, int age, String sex, String time) {
    68. this.name = name;
    69. this.age = age;
    70. this.sex = sex;
    71. this.time = time;
    72. }
    1. package chapter_test;
    2. import java.io.*;
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. public class Test4 {
    6. public static void main(String[] args) {
    7. //声明ArrayList集合存储User的对象
    8. ArrayList<User> list=new ArrayList<>();
    9. ObjectInputStream obi=null;//声明一个实现序列化的对象
    10. ObjectOutputStream obo=null;//声明一个实现反序列化的对象
    11. try {
    12. //实例化一个实现序列化的对象
    13. obo=new ObjectOutputStream(new FileOutputStream("D:\\doc\\user.dat"));
    14. //创建User类的对象作为数据
    15. User user1=new User("张三",18,"男","2021-09-09");
    16. User user2=new User("王五",18,"男","2021-08-08");
    17. User user3=new User("赵六",20,"男","2021-07-07");
    18. //添加到ArrayList集合中
    19. list.add(user1);
    20. list.add(user2);
    21. list.add(user3);
    22. //实现序例化
    23. obo.writeObject(list);
    24. System.out.println("序例化成功");
    25. //实例化一个实现反序列化的对象
    26. obi=new ObjectInputStream(new FileInputStream("D:\\doc\\user.dat"));
    27. //实现反序例化
    28. list=(ArrayList<User>)obi.readObject();
    29. //循环遍历
    30. for(User u:list){
    31. u.print();
    32. }
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. }finally{
    36. try {
    37. obi.close();//关闭实现序例化的流
    38. obo.close();//关闭实现反序例化的流
    39. } catch (IOException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. }

    JavaOOP I/O - 图7