Catalog
  1. 1. Java多线程与IO流学习笔记(四)
    1. 1.1. File类
      1. 1.1.1. 概述
      2. 1.1.2. 构造方法
      3. 1.1.3. 常用方法
      4. 1.1.4. 目录的遍历
      5. 1.1.5. 文件过滤器
    2. 1.2. IO概述
      1. 1.2.1. IO的分类
      2. 1.2.2. 字节流
      3. 1.2.3. 字节输出流
      4. 1.2.4. FileOutputStream类
      5. 1.2.5. 写出换行
      6. 1.2.6. 字节输入流
      7. 1.2.7. FileInputStream类
      8. 1.2.8. 读取字节数据
    3. 1.3. 字符流
      1. 1.3.1. 字符输入流Reader
      2. 1.3.2. FileReader类
      3. 1.3.3. 字符输出流
      4. 1.3.4. FileWriter类
      5. 1.3.5. 字符输出流的使用步骤
      6. 1.3.6. 对try-catch的改进
    4. 1.4. 属性集
      1. 1.4.1. 概述
      2. 1.4.2. Properties类
    5. 1.5. 缓冲流
      1. 1.5.1. 概述
      2. 1.5.2. 字节缓冲流
      3. 1.5.3. 字符缓冲流
Java文件操作和IO流

Java多线程与IO流学习笔记(四)

File类

概述

java.io.File类是文件和目录路径名的抽象表示,主要用于文件和目录的创建,查找和删除等操作。

File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法。

pathSeparator和separator:

  • Windows:路径分隔符是分号(;),文件名分隔符是反斜杠()
  • Linux:路径分隔符是冒号(:),文件名分隔符是斜杠(/)
  • 路径不能写死

路径:

  • 绝对路径:是一个完整的路径
  • 相对路径:是一个简化的路径,相对于当前项目的根目录

注意:

  1. 路径是不区分大小写
  2. windows系统下路径分隔符反斜杠是转义字符要写两个来表示一个。

构造方法

  • public File(String pathname): 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。
  • public File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例。
  • public File(File parent,String child):从父抽象路径名和子路径名字符串创建新的File实例

路径可以是存在也可以是不存在,创建File对象,只是把字符串封装为File对象,不考虑路径的真假情况。

常用方法

获取功能的方法:

  • public String getAbsolutePath():返回此File的绝对路径名字符串
  • public String getPath():将此File转换给路径名字符串
  • public String getName():返回由此File表示的文件或目录的名称
  • public long length():返回由此File表示的文件的长度

判断功能的方法:

  • public boolean exists():表示文件或目录是否实际存在。
  • public boolean isDirectory():判断是否为目录
  • public boolean isFile():判断是否为文件

创建和删除功能的方法:

  • public boolean createNewFile():当且仅当具有该名称的问价不存在时,创建一个新的空文件
  • public boolean delete():删除此File表示的文件或目录
  • public boolean mkdir():创建由此file表示的目录
  • public boolean mkdirs():创建由此File表示的目录,包括任何必须但不存在的父目录。

目录的遍历

  • public String[] list():返回一个String数组,表示该File目录中的所有子文件或目录。
  • public File[] listFiles():返回一个File数组,表示该File目录中所有的子文件或目录。

如果路径不存在或路径不是一个目录,会抛出空指针异常

文件过滤器

java.io.FileFilter 是一个接口,是File的过滤器。 该接口的对象可以传递给File类的 listFiles(FileFilter) 作为参数, 接口中只有一个方法。

boolean accept(File pathname) :测试pathname是否应该包含在当前File目录中,符合则返回true。

  1. 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单。
  2. accept 方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回
    false。保留规则:
    1. 要么是.java文件。
    2. 要么是目录,用于继续遍历。
  3. 通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接打
    印。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class DiGuiDemo4 {
    public static void main(String[] args) {
    File dir = new File("D:\\aaa");
    printDir2(dir);
    }
    public static void printDir2(File dir) {
    // 匿名内部类方式,创建过滤器子类对象
    File[] files = dir.listFiles(new FileFilter() {
    @Override
    public boolean accept(File pathname) {
    return pathname.getName().endsWith(".java")||pathname.isDirectory();
    }
    });
    // 循环打印
    for (File file : files) {
    if (file.isFile()) {
    System.out.println("文件名:" + file.getAbsolutePath());
    } else {
    printDir2(file);
    }
    }
    }
    }

    IO概述

    IO的分类

    根据数据的流向分为:输入流和输出流。
  • 输入流 :把数据从其他设备上读取到内存中的流。
  • 输出流 :把数据从内存中写出到其他设备上的流。

格局数据的类型分为:字节流和字符流。

  • 字节流 :以字节为单位,读写数据的流。
  • 字符流 :以字符为单位,读写数据的流。

字节流

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一 样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底 层传输的始终为二进制数据。

字节输出流

java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字
节输出流的基本共性功能方法。

  • public void close():关闭输出流并释放与此流相关的任何系统资源
  • public void flush():刷新此输出流并强制任何缓冲的输出字节流
  • public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流
  • public void write(byte[] b, int off, int length):从指定的字节暑促写入len字节,从偏移量off开始输出到此输出流。
  • public abstract void write(int b):将指定的字节输出流

close方法,当完成流的操作时,必须调用此方法,释放系统资源

数据的追加续写:

每次程序运行,创建输出流对象,都会清空目标文件中的数据。如何保留目标文件中数据,还能 继续添加新数据呢?

  • public FileOutputStream(File file, boolean append) : 创建文件输出流以写入由指定的 File对象表示的 文件。

  • public FileOutputStream(String name, boolean append) : 创建文件输出流以指定的名称写入文件。 这两个构造方法,参数中都需要传入一个boolean类型的值, true 表示追加数据, false 表示清空原有数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * FileOutputStream:文件字节输出流
    * 作用:把内存中的数据写入到硬盘的文件中
    */
    public class Demo01OutputStream {
    public static void main(String[] args) throws IOException {
    FileOutputStream fos = new FileOutputStream("/Users/zhangyun/Desktop/javaTest/a.txt",true);
    byte[] bytes = ",憨憨".getBytes();
    System.out.println(Arrays.toString(bytes));
    fos.write(bytes);
    fos.close();
    }
    }

    FileOutputStream类

    OutputStream 有很多子类,我们从最简单的一个子类开始。
    java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件。
    构造方法

  • public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。

  • public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。参数是文件的路径。

构造方法的作用:

  1. 创建一个FileOutputStream对象
  2. 会根据构造方法中传递的文件/文件路径,创建一个空的文件
  3. 会把FileOutputStream对象指向创建好的文件

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。

1
2
3
4
5
6
7
8
9
10
11
/**
* FileOutputStream:文件字节输出流
* 作用:把内存中的数据写入到硬盘的文件中
*/
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("/Users/zhangyun/Desktop/javaTest/a.txt");
fos.write(97);
fos.close();
}
}

写出换行

回车符 \r 和换行符 \n :

  • 回车符:回到一行的开头(return)。
  • 换行符:下一行(newline)。

系统中的换行:

  • Windows系统里,每行结尾是 回车+换行 ,即 \r\n ; - Unix系统里,每行结尾只有换行,即 \n ;
  • Mac系统里,每行结尾是回车,即 \r 。从 Mac OS X开始与Linux统一。

字节输入流

java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入
流的基本共性功能方法。

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read() : 从输入流读取数据的下一个字节。
  • public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组b中 。

FileInputStream类

java.io.FileInputStream 类是文件输入流,从文件中读取字节。

构造方法

  • FileInputStream(File file) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系 统中的 File对象 file命名。
  • FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件 系统中的路径名 name命名。

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException 。

读取字节数据

  1. 读取字节: read 方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1。
  2. 使用字节数组读取: read(byte[] b) ,每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读
    取到末尾时,返回-1

字符流

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为 一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

字符输入流Reader

java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入
流的基本共性功能方法。

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read() : 从输入流读取一个字符。
  • public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中。

FileReader类

java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  • FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
  • FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。

当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream。

读取字符数据

  • read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取

使用字符数组读取:
read(char[] cbuf) ,每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("/Users/zhangyun/Desktop/javaTest/a.txt");
// int len = 0;
// while((len = fr.read())!=-1){
// System.out.print((char)len);
// }
// fr.close();

char[] cs = new char[1024];
int len = 0;
while((len = fr.read(cs))!=-1){
System.out.println(new String(cs,0,len));
}
fr.close();
}
}

字符输出流

java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  • void write(int c) 写入单个字符。
  • void write(char[] cbuf) 写入字符数组。
  • abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str) 写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个
    数。
  • void flush() 刷新该流的缓冲。
  • void close() 关闭此流,但要先刷新它。

FileWriter类

java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  • FileWriter(File file) : 创建一个新的FileWriter,给定要读取的File对象。
  • FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称。

当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。

字符输出流的使用步骤

  1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地。
  2. 使用FileWriter中的write方法,把数据写入到内存缓冲区中。
  3. 使用FileWriter中的flush方法,把内存缓冲区中的数据,刷新到文件中
  4. 释放资源(会把内存缓冲区的数据刷新到文件中)
1
2
3
4
5
6
7
8
9
10
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("/Users/zhangyun/Desktop/javaTest/a.txt",true);
String str = "\n鸡你太美,口吐芬芳,奥力给";
char[] cs = str.toCharArray();
fw.write(str);
fw.write(cs,7,5);
fw.close();
}
}

实际上应该使用try-catch和finally来确保流被关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Demo01OutputStream {
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter("/Users/zhangbin/Desktop/javaTest");
String str = "\n鸡你太美,口吐芬芳,奥力给";
fw.write(str);
} catch (IOException e) {
System.out.println(e);
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

对try-catch的改进

JDK7的改进:

在try的后面增加一个括号,在括号中定义流对象,那么这个流对象的作用域就在try中有效,try中的代码执行完毕,会自动把流对象释放,不用再写finally

1
2
3
4
5
try(FileWriter fw = new FileWriter("/Users/zhangbin/Desktop/javaTest");){
//可能会产生异常的代码
}catch(IOException e){
e.printStackTrace();
}

JDK9的新特性:

try的前面可以定义流对象,在try后面的括号中可以直接引入流对象的变量名,在try代码执行完毕后,流对象也可以释放掉,不用写finally。

属性集

概述

java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。

Properties类

构造方法

  • public Properties() :创建一个空的属性列表。

基本的存储方法

  • public Object setProperty(String key, String value) : 保存一对属性。
  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。
  • public Set stringPropertyNames() :所有键的名称的集合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static void show01() {
//创建Properties集合对象
Properties prop = new Properties();
//使用setProperties往集合中添加数据
prop.setProperty("鸡你太美","坤坤");
prop.setProperty("奥力给","巨魔");
prop.setProperty("影流之主","丝般顺滑");
Set<String> set = prop.stringPropertyNames();
//遍历set集合,取出Properties集合的每一个键
for(String key:set){
//使用getProperties方法通过key获取value
String value = prop.getProperty(key);
System.out.println(key+"="+value);
}
}

与流相关的方法

  • public void load(InputStream inStream) : 从字节输入流中读取键值对。
  • public void load(Reader reader)
  • public void store(OutputStream outStream,String comments):把集合中的临时数据,持久化写入到硬盘中存储;
  • public void store(Writer writer,String comments)

参数:

OutputStream outStream:字节输出流,不能写入中文;

Writer writer:字符输出流,可以写中文。

comments:注释,用来解释说明保存的文件是做什么用的,不能使用中文,会产生乱码,默认是Unicode编码,一般使用“”空字符串

使用步骤:

  1. 创建Properties集合对象,添加数据
  2. 创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地。
  3. 使用Properties中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
  4. 释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static void show02() throws IOException {
//创建Properties集合对象
Properties prop = new Properties();
//使用setProperties往集合中添加数据
prop.setProperty("鸡你太美","坤坤");
prop.setProperty("奥力给","巨魔");
prop.setProperty("影流之主","丝般顺滑");

FileWriter fw = new FileWriter("/Users/zhangyun/Desktop/javaTest/a.txt",true);

prop.store(fw,"save data");

fw.close();
}

缓冲流

概述

缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流: BufferedInputStream , BufferedOutputStream
  • 字符缓冲流: BufferedReader , BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO 次数,从而提高读写的效率。

字节缓冲流

构造方法:

  • public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
  • public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。

参数加 int size 会指定缓冲流大小,不加为默认大小。

字符缓冲流

构造方法:

  • public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
  • public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。

特有方法:

  • BufferedReader: public String readLine() : 读一行文字。
  • BufferedWriter: public void newLine() : 写一行行分隔符,由系统属性定义符号。
Author: zycode1561
Link: https://zycode1561.github.io/2020/01/17/Java%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8CIO%E6%B5%81/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
  • 支付宝

Comment