> 文档中心 > Java--IO流

Java--IO流


IO流


文章目录

  • IO流
  • 一、File类
    • 1.File的含义和位置
    • 2.获取File类的三种方式
    • 2.1.File类路径注意事项:
    • 3.File常见功能
      • 3.1.File类的获取功能
        • 3.1.1.常见的File类获取功能
        • 3.1.2.File对象获取对应的文件夹列表
      • 3.2.File类的重命名功能
      • 3.3.File类的判断功能
      • 3.4.File类的创建功能
      • 3.5.File类的删除功能
    • 4.File类注意事项
  • 二、IO流的原理及流的分类
    • 1.Java IO原理
    • 2.流的分类
      • 2.1.根据流向分类
      • 2.2.根据数据单位分类
      • 2.3.根据流的角色分类
    • 3.字符流
      • 3.1.Reader 读入文件数据
      • 3.2.Writer 写入数据到文件
      • 3.3.注意事项
    • 4.字节流
      • 4.1.使用字节流复制图片文件
      • 4.2.文件目录如下
    • 5.缓冲流
      • 5.1.BufferedInputStream && BufferedOutputStream
      • 5.2.BufferedReader&& BufferedWriter
    • 6.转换流(转换流提供了在字节流和字符流之间的转换)
    • 7.其他的流的使用
      • 7.1.标准的输入输出流
    • 8.对象流
      • 8.1.对象流的使用
      • 8.2.对象的序列化
      • 8.3.使用序列化跟反序列化读取和写入操作
    • 9.RandomAccessFile
      • 9.1.RandomAccessFile概述
      • 9.2.不同构造器

一、File类

1.File的含义和位置

File类对象代表一个文件或者一个文件夹;File类存放在io包下。

2.获取File类的三种方式

public static void test1()    { //1.通过相对路径或者绝对路径直接获取对应的file类 //File(String filePath) // 通过相对路径获取file类 内存层面的对象 File file1 = new File("first.txt"); System.out.println(file1); // 通过绝对路径获取file类 // File.separator 根据不同的系统区分 //路径分隔符 windows:\\ unix:/ File file2 = new File("D:" + File.separator + "myproject" + File.separator + "my-javabase-demo" + File.separator  + "javase-demo" + File.separator + " first.txt"); System.out.println(file2); //2.父文件夹的方式跟子文件夹的方式获取file类 //File(String parentPath,String childPath) File file3 = new File("D:\\myproject\\my-javabase-demo", "javase-demo"); System.out.println(file3); //3.根据file对象,还有子文件夹获取对应的file类 //File(File parentFile,String childPath) File file4 = new File(file3, "first.txt"); System.out.println(file4);    }

2.1.File类路径注意事项:

相对路径:相较于某个路径下,指明的路径。 idea @test的单元测试指在同一个module下,main方法里面指同一个工程下;
绝对路径:包含盘符在内的文件或文件目录的路径

3.File常见功能

Java--IO流
目录结构

3.1.File类的获取功能

3.1.1.常见的File类获取功能

public static void test2()    { /**  * 通过相对路径跟绝对路径的获取查看区别  */ File file1 = new File("first.txt"); File file2 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\second.txt"); System.out.println(file1.getAbsolutePath()); System.out.println(file1.getPath()); System.out.println(file1.getParent()); System.out.println(file1.getName()); System.out.println(file1.length()); System.out.println(file1.lastModified()); System.out.println("----------"); System.out.println(file2.getAbsolutePath()); System.out.println(file2.getPath()); System.out.println(file2.getParent()); System.out.println(file2.getName()); System.out.println(file2.length()); System.out.println(file2.lastModified()); // getAbsolutePath 获取绝对路径。绝对路径和相对路径获取的file类结果相同 // getPath 获取路径。相对路径获取的file类:文件名;绝对路径获取的file类:全路径 // getParent 上级目录(没有为null)。相对路径获取的file类:null;绝对路径获取的file类:全路径 // getName 获取文件名。相同 // length 获取文件长度(即:字节数)。相对路径获取的file类:0;绝对路径获取的file类:对应长度 // lastModified 最后一次的修改时间戳。相对路径获取的file类:0;绝对路径获取的file类:对应时间    }

3.1.2.File对象获取对应的文件夹列表

public static void test3()    { /**  * 获取对应的文件夹列表,只能用绝对路径  */ File file = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\di"); //file.list() 获取指定目录下的所有文件或者文件目录的名称数组 for (String s : Objects.requireNonNull(file.list())) {     System.out.println(s); } //file.listFiles() 获取指定目录下的所有文件或者文件目录的File数组 for (File listFile : Objects.requireNonNull(file.listFiles())) {     System.out.println(listFile.getAbsolutePath()); }    }

3.2.File类的重命名功能

public static void test4()    { File file1 = new File("first.txt"); // 相对路径的无法进行 重命名 false System.out.println(file1.renameTo(new File("1.txt"))); File file2 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\second.txt"); // renameTo 里面的文件路径为外层文件夹下的路径,然后对应的文件会改名字且移动位置 System.out.println(file2.renameTo(new File("D:\\myproject\\my-javabase-demo\\javase-demo\\three.txt")));    }

3.3.File类的判断功能

 public static void test5()    { // 相对路径所有的判断功能都是false 需要用 绝对路径判断 File file1 = new File("first.txt"); File file2 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\three.txt"); System.out.println(file2.isDirectory());// 判断是否是文件目录 System.out.println(file2.isFile());// 判断是否是文件 System.out.println(file2.exists());// 判断是否存在 System.out.println(file2.canRead());// 判断是否可读 System.out.println(file2.canWrite());// 判断是否可写 System.out.println(file2.isHidden());// 判断是否隐藏    }

3.4.File类的创建功能

public static void test6()    { File file1 = new File("di.txt"); File file2 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\four.txt"); File file3 = new File("di"); File file4 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\four"); try {     // 创建文件。若文件存在,则不创建,返回false     // 相对路径创建为大文件夹下面     System.out.println(file1.createNewFile());     System.out.println(file2.createNewFile());     // 创建文件目录。如果上层文件目录不存在,一并创建     System.out.println(file3.mkdir());     System.out.println(file4.mkdir()); } catch (IOException e) {     e.printStackTrace(); }    }

3.5.File类的删除功能

public static void test7()    { // 相对路径无法删除 File file1 = new File("first.txt"); System.out.println(file1.delete()); // 绝对路径删除 File file2 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\first.txt"); System.out.println(file2.delete()); // 文件夹删除如果里面包含文件无法删除 // 需要删除里面的文件 然后删除对应的文件夹,即空文件夹才可以删除 File file3 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\di"); System.out.println(file3.delete()); if (file3.isDirectory()) {     for (File file : file3.listFiles())     {  file.delete();     } } System.out.println(file3.delete());    }

4.File类注意事项

当硬盘有一个真实的文件或目录存在时,创建File对象,各个属相会显示赋值;
当硬盘中没有真实的文件或者文件夹对应时,创建对象时,除了指定的目录和路径外,其他的属性取成员变量的默认值。

二、IO流的原理及流的分类

1.Java IO原理

  • I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。
  • Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。
  • java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

2.流的分类

2.1.根据流向分类

  • 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  • 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

2.2.根据数据单位分类

  • 字节流(8 bit)
  • 字符流(16 bit)

2.3.根据流的角色分类

  • 节点流 (直接从数据源或目的地读写数据),直接作用在源文件上面的。
  • 处理流 (不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。作用在已有的流之上)
    Java--IO流

3.字符流

3.1.Reader 读入文件数据

// read()方法的操作    public static void test1()    { // 1.实例化file类的对象,指明要操纵的文件 File file = new File("javase-demo\\three.txt"); FileReader fileReader = null; try {     // 2.提供具体的流     fileReader = new FileReader(file);     // 3.数据读入     // read():返回读入的字符,如果达到文件的末尾,返回-1     // 读入的文件一定要存在,否则FileNotFoundException。     int data = fileReader.read();     // 循环的遍历文件里面的字符     while (data != -1)     {  System.out.println((char) data);  data = fileReader.read();     } } catch (FileNotFoundException e) {     e.printStackTrace(); } catch (IOException e) {     e.printStackTrace(); } finally {     // 4.关闭流     try     {  if (fileReader != null)  {      fileReader.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }
 // read(char[] cArr)    public static void test2()    { FileReader fileReader = null; try {     // 1.File类的实例化     File file = new File("javase-demo\\three.txt");     // 2.FileReader流的实例化     fileReader = new FileReader(file);     // 3.读入的操作     char[] cArr = new char[5];     int len;     while ((len = fileReader.read(cArr)) != -1)     {  // 如果用此方式会导致每次的数据覆盖原本的char数组,如果此次的char数组没有读满,会将上一次读入的也再次读取;  // for (int i = 0; i < cArr.length; i++)  // {  // System.out.println(cArr[i]);  // }  // 每次只遍历读取的长度  // for (int i = 0; i < len; i++)  // {  // System.out.print(cArr[i]);  // }  // 通过string的截取读取  System.out.print(new String(cArr, 0, len));     } } catch (IOException e) {     e.printStackTrace(); } finally {     // 4.流资源关闭     if (fileReader != null)     {  try  {      fileReader.close();  }  catch (IOException e)  {      e.printStackTrace();  }     } }    }

3.2.Writer 写入数据到文件

public static void test3()    { FileWriter fileWriter = null; try {     // 1.File类的实例化,指明写出的文件     File file = new File("javase-demo\\one.txt");     // 2.提供FileWriter对象,用于数据的写出     // File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。     // 如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖     // 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容     fileWriter = new FileWriter(file, true);     // 3.写出的操作     fileWriter.write("小白,你好\n");     fileWriter.write("小白,加油\n"); } catch (IOException e) {     e.printStackTrace(); } finally {     // 4.流的关闭     try     {  if (fileWriter != null)  {      fileWriter.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }
 public static void test4()    { // 将文件读入并写出,即复制文件 FileReader fileReader = null; FileWriter fileWriter = null; try {     // 1.创建File类的对象,指明读入和写出的文件     File file1 = new File("javase-demo\\one.txt");     File file2 = new File("javase-demo\\two.txt");     // 2.提供FileWriter,FileReader对象,用于数据的读入和写出     fileReader = new FileReader(file1);     fileWriter = new FileWriter(file2);     // 3.读取数据和写入数据的操作     // 方式一:每次一个一个的写出     // int data;     // while ((data = fileReader.read()) != -1)     // {     // fileWriter.write(data);     // }     // 方式二:批量的写出     char[] cArr = new char[5];     int len;// 记录每次读入到cbuf数组中的字符的个数     while ((len = fileReader.read(cArr)) != -1)     {  // 每次写出len个字符  fileWriter.write(cArr, 0, len);     } } catch (IOException e) {     e.printStackTrace(); } finally {     try     {  // 4.流资源的关闭  if (fileReader != null)  {      fileReader.close();  }  if (fileWriter != null)  {      fileWriter.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }

3.3.注意事项

  • 字符流无法处理图片之类格式的文件
  • 对于文本文件(.txt,.java,.c,.cpp …),使用字符流处理
  • 对于非文本文件(.jpg,.mp3,.doc,.ppt,.xls),使用字节流处理
  • 使用字节流处理文本文件,如果遇到中文等,可能出现乱码。
  • 如果是单纯的复制文件,则字节流和字符流都可以使用。

4.字节流

4.1.使用字节流复制图片文件

   public static void test2()    { // 使用字节流复制图片文件 FileInputStream inputStream = null; FileOutputStream outputStream = null; try {     // 1.实例化 file     File fileScr = new File("javase-demo\\img.png");     File fileDest = new File("javase-demo\\img1.png");     // 2.创建流     inputStream = new FileInputStream(fileScr);     outputStream = new FileOutputStream(fileDest);     // 3.数据操作     int data;     while ((data = inputStream.read()) != -1)     {  outputStream.write(data);     } } catch (IOException e) {     e.printStackTrace(); } finally {     // 4.关闭流资源     try     {  if (inputStream != null)      inputStream.close();  if (outputStream != null)      outputStream.close();     }     catch (IOException e)     {  e.printStackTrace();     } }    }

4.2.文件目录如下

Java--IO流

5.缓冲流

5.1.BufferedInputStream && BufferedOutputStream

public static void test1()    { // 利用缓冲流实现非文本文件的复制 long start = System.currentTimeMillis(); FileInputStream inputStream = null; FileOutputStream outputStream = null; BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try {     // 1.实例化file对象     File file1 = new File("javase-demo\\img.png");     File file2 = new File("D:\\img.png");     // 2.创建流对象     // 2.1.节点流     inputStream = new FileInputStream(file1);     outputStream = new FileOutputStream(file2);     // 2.2.缓冲流     bufferedInputStream = new BufferedInputStream(inputStream);     bufferedOutputStream = new BufferedOutputStream(outputStream);     // 3.文件操作,复制     byte[] bytes = new byte[1024];     int len;     while ((len = bufferedInputStream.read(bytes)) != -1)     {  bufferedOutputStream.write(bytes, 0, len);  //刷新缓冲区//  bufferedOutputStream.flush();     } } catch (IOException e) {     e.printStackTrace(); } finally {     // 4.关闭流资源,     // 由于包装了缓冲流,有一个关闭顺序,即先关闭缓冲流(外层),再关闭节点流(内层)     try     {  if (bufferedInputStream != null)      bufferedInputStream.close();  if (bufferedOutputStream != null)      bufferedOutputStream.close();  // 关闭外层流的同时,内层的流也一同关闭,可不用关闭  if (inputStream != null)      inputStream.close();  if (outputStream != null)      outputStream.close();     }     catch (IOException e)     {  e.printStackTrace();     } } long end = System.currentTimeMillis(); System.out.println(end - start);    }

5.2.BufferedReader&& BufferedWriter

public static void test2()    { // 使用BufferedReader和BufferedWriter实现文本文件的复制 long start = System.currentTimeMillis(); BufferedWriter bufferedWriter = null; BufferedReader bufferedReader = null; try {     // 1.实例化file对象     File file1 = new File("D:\\myproject\\my-javabase-demo\\javase-demo\\text.txt");     File file2 = new File("D:\\text.txt");     // 2.创建流对象     // 2.1.节点流 字符流     FileReader fileReader = new FileReader(file1);     FileWriter fileWriter = new FileWriter(file2);     // 2.2.缓冲流     bufferedReader = new BufferedReader(fileReader);     bufferedWriter = new BufferedWriter(fileWriter);     // 3.文件操作,复制     // 方式一:使用char[]数组//     char[] cbuf = new char[1024];//     int len;//     while ((len = bufferedReader.read(cbuf)) != -1)//     {//  bufferedWriter.write(cbuf, 0, len);//  // bw.flush();//     }     //方式二:使用String     String data;     while((data = bufferedReader.readLine()) != null){  //方法一://  bw.write(data + "\n");//data中不包含换行符  //方法二:  bufferedWriter.write(data);//data中不包含换行符  bufferedWriter.newLine();//提供换行的操作     } } catch (IOException e) {     e.printStackTrace(); } finally {     try     {  // 4.关闭流  if (bufferedReader != null)      bufferedReader.close();  if (bufferedWriter != null)      bufferedWriter.close();     }     catch (IOException e)     {  e.printStackTrace();     } } long end = System.currentTimeMillis(); System.out.println(end - start);    }

6.转换流(转换流提供了在字节流和字符流之间的转换)

7.其他的流的使用

7.1.标准的输入输出流

 //利用标准输入输出流,从控制台输入 字母转换成大写,    //输入e 或者 exit 结束    public static void test1()    { BufferedReader bufferedReader = null; try {     InputStreamReader inputStreamReader = new InputStreamReader(System.in);     bufferedReader = new BufferedReader(inputStreamReader);     String data;     while (true)     {  System.out.println("输入字符串:");  data = bufferedReader.readLine();  if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data))  {      System.out.println("程序结束");      break;  }  String upperCase = data.toUpperCase();  System.out.println(upperCase);     } } catch (IOException e) {     e.printStackTrace(); } finally {     try     {  if (bufferedReader != null)  {      bufferedReader.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }

8.对象流

8.1.对象流的使用

  • ObjectInputStream && OjbectOutputSteam
    用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
  • 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
  • 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
  • ObjectInputStream || OjbectOutputSteam 不能序列化static和transient修饰的成员变量

8.2.对象的序列化

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点(序列化)。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象(反序列化)。

8.3.使用序列化跟反序列化读取和写入操作

public static void test1()    { // 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去 // 使用ObjectOutputStream实现 ObjectOutputStream outputStream = null; try {     outputStream = new ObjectOutputStream(new FileOutputStream("javase-demo\\object.txt"));     outputStream.writeObject(new String("你好吗,小朋友"));     outputStream.flush();// 刷新操作     outputStream.writeObject(new Employee("小白", 1));     outputStream.flush();     outputStream.writeObject(new Employee("小红", 23, 1001, new Account(5000)));     outputStream.flush(); } catch (IOException e) {     e.printStackTrace(); } finally {     try     {  if (outputStream != null)  {      outputStream.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }
public static void test2()    { // 反序列化:将磁盘文件中的对象还原为内存中的一个java对象 // 使用ObjectInputStream来实现 ObjectInputStream objectInputStream = null; try {     objectInputStream = new ObjectInputStream(new FileInputStream("javase-demo\\object.txt"));     Object obj = objectInputStream.readObject();     String str = (String) obj;     Employee e1 = (Employee) objectInputStream.readObject();     Employee e2 = (Employee) objectInputStream.readObject();     System.out.println(str);     System.out.println(e1);     System.out.println(e2); } catch (IOException e) {     e.printStackTrace(); } catch (ClassNotFoundException e) {     e.printStackTrace(); } finally {     try     {  if (objectInputStream != null)  {      objectInputStream.close();  }     }     catch (IOException e)     {  e.printStackTrace();     } }    }
public class Employee implements Serializable{    public static final long serialVersionUID = 475461233534532L;    private String name;    private int age;    private int id;    private Account acct;    public Employee(String name, int age, int id)    { this.name = name; this.age = age; this.id = id;    }    public Employee(String name, int age, int id, Account acct)    { this.name = name; this.age = age; this.id = id; this.acct = acct;    }    @Override    public String toString()    { return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + ", acct=" + acct + '}';    }    public int getId()    { return id;    }    public void setId(int id)    { this.id = id;    }    public String getName()    { return name;    }    public void setName(String name)    { this.name = name;    }    public int getAge()    { return age;    }    public void setAge(int age)    { this.age = age;    }    public Employee(String name, int age)    { this.name = name; this.age = age;    }    public Employee()    {    }}
public class Account implements Serializable{    public static final long serialVersionUID = 4713454534532L;    private double balance;    @Override    public String toString()    { return "Account{" + "balance=" + balance + '}';    }    public double getBalance()    { return balance;    }    public void setBalance(double balance)    { this.balance = balance;    }    public Account(double balance)    { this.balance = balance;    }}

9.RandomAccessFile

9.1.RandomAccessFile概述

  • RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
  • RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
  • 如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
  • 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果

9.2.不同构造器

  • public RandomAccessFile(File file, String mode)
  • public RandomAccessFile(String name, String mode)
    创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:
  • r: 以只读方式打开
  • rw:打开以便读取和写入
  • rwd:打开以便读取和写入;同步文件内容的更新
  • rws:打开以便读取和写入;同步文件内容和元数据的更新
  • 如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,
    如果读取的文件不存在则会出现异常。 如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。