【Java】IO 流
2021/12/29 1:07:21
本文主要是介绍【Java】IO 流,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
【Java】IO 流
1 File 类
File 类是文件或目录的抽象表示,通过它可以实现对文件或目录信息的操作和管理。File 类能新建、删除、重命名文件和目录,但 File 类不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。想要在 Java 程序中表示一个真实存在的文件或目录,那么必须有一个 File 对象,但是 Java 程序中的一个 File 对象,可能没有一个真实存在的文件或目录。File 对象可以作为参数传递给流的构造器。
1.1 File 类的常用构造器
File(String pathname)
以 pathname 为路径创建 File 对象,可以是绝对路径或者相对路径,如果 pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储。
- 绝对路径:是一个固定的路径,从盘符开始。
- 相对路径:是相对于某个位置开始。
File(String parent, String child)
以 parent 为父路径,child 为子路径创建 File 对象。
File(File parent, String child)
根据一个父 File 对象和子文件路径创建 File 对象
@Test public void test1() { // 构造器1 File file1 = new File("hello.txt"); // 相当于当前 module File file2 = new File("D:\\document\\he.txt"); // "\\" 第一个为转义字符 // 构造器2 File file3 = new File("D:\\document\\md文档", "Java 学习笔记"); // 构造器3 File file4 = new File(file3, "hi.txt"); }
1.2 路径分隔符
路径中的每级目录之间用一个路径分隔符隔开。
路径分隔符和系统有关:
- windows 和 DOS 系统默认使用 “” 来表示。
- UNIX 和 URL 使用 “/” 来表示。
注意:Java 程序支持跨平台运行,因此路径分隔符要慎用。为了解决这个隐患,File 类提供了一个常量:public static final String separator。它可以根据操作系统,动态的提供分隔符。
// 下列两种情况效果相同 File file1 = new File("d:\\document\\hello.txt"); File file2 = new File("d:" + File.separator + "document" + File.separator + "hello.txt");
1.3 File 类的常用方法
通过 File 类中的方法可以实现对文件和目录的操作和管理。下面是 File 类中常用的方法。
File 类的获取功能:
-
public String getName():返回文件或目录的名称。
-
public String getPath():获取路径。
-
public String getParent():获取上层文件目录路径。若无,返回 null。
-
public String getAbsolutePath():获取绝对路径。
-
public long length():获取文件长度(即:字节数)。不能获取目录的长度。
-
public long lastModified():获取最后一次的修改时间,毫秒值。
如下两个方法适用于文件目录:
-
public String[] list():获取指定目录下的所有文件或者文件目录的名称数组。
-
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的 File 数组。
File 类的重命名功能:
- public boolean renameTo(File dest):把文件重命名为指定的文件路径,成功则返回 true,否则返回 false。
比如以 file1.renameTo(file2) 为例,想要保证返回 true,需要 file1 在硬盘中是存在的,且 file2 不能在硬盘中存在。
File 类的判断功能:
- public boolean isDirectory():判断是否是文件目录。
- public boolean isFile():判断是否是文件。
- public boolean exists():判断是否存在。
- public boolean canRead():判断是否可读。
- public boolean canWrite():判断是否可写。
- public boolean isHidden():判断是否隐藏。
File 类的创建功能:
- public boolean createNewFile():创建文件。若文件存在,则不创建,返回 false。
- public boolean mkdir():创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
- public boolean mkdirs():创建文件目录。如果上层文件目录不存在,一并创建。
注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目路径下。
File 类的删除功能:
- public boolean delete():删除文件或者文件夹。
注意事项:
Java 中的删除不走回收站。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录。
2 IO 流及流的分类
2.1 IO 流概述
I/O 是 Input/Output 的缩写, I/O 技术是非常实用的技术,用于处理设备之间的数据传输。如:读/写文件,网络通讯等。在 Java 程序中,对于数据的输入/输出操作以 “流 (stream)” 的方式进行。
流 (stream) 是一组有序的数据序列。根据操作的类型,分为输入流和输出流两种。输入流的指向称为源,程序从指向源的输入流中读取源中的数据。当程序需要读取数据时,就会开启一个通向数据源的流,这个数据源可以是文件、内存或是网络连接。而输出流的指向是字节要去的目的地,程序通过向输出流中写入数据把信息传递到目的地。当程序需要写入数据时,就会开启一个通向目的地的流。
Java 本身不包含 I/O 语句,而是通过 Java API 提供的 Java.io 包完成 I/O。java.io 包下提供了各种 “流” 类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
- 输入 input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出 output:将程序(内存)数据输出到磁盘、光盘等存储设备中。
注意:输入输出是相对的,需要清楚是站在谁的角度说明问题。比如:甲借给乙 100 块,对甲来说,甲是输出端;对乙来说,乙是输入端。
2.2 流的分类
按照 流的方向 划分可以分为输入流 (InputStream) 和输出流 (OutputStream) 。
- 输入流:Java 程序可以打开一个从某种数据源(文件、内存等)到程序的一个流,从这个流中读取数据,这就是输入流。因为流是有方向的,所以只能从输入流中读取数据,而不能向它写数据。
- 输出流:Java 程序可以打开到某种目标的流,把数据顺序写到该流中,从而把程序中的数据保存在目标中。只能将数据写到输出流中,而不能从输出流中读取数据。
按照 流所关联的是否为最终数据源或目标 来划分,流可以分为节点流 (node stream) 和处理流 (processing stream)。
- 节点流:直接与最终数据源或目标关联的流为节点流。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGtLc6L0-1640706447490)(D:\单宇楠\md文档\md插图\IO流2.png)]
- 处理流:不直接连到数据源或目标,而是对其他 I/O 流进行连接和封装的流为处理流。节点流一般只提供一些基本的读写操作方法,而处理流会提供一些功能比较强大的方法。所以,在实际应用中通常将节点流与处理流结合起来使用以满足不同的 I/O 需求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ZUO6c4l-1640706447492)(D:\单宇楠\md文档\md插图\IO流3.png)]
按照 流所操作的数据单元 来划分,流可以分为字节流和字符流。
- 字节流:以字节为基本单元进行数据的 I/O,可用于二进制数据的读写。
- 字符流:以字符为基本单元进行数据的 I/O,可用于文本数据的读写。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6CsB6Pci-1640706447493)(D:\单宇楠\md文档\md插图\IO流1.png)]
2.3 流的体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hq0nxSY8-1640706447494)(D:\单宇楠\md文档\md插图\io流4.jpg)]
2.4 输入输出流
输入输出流一般分为字节输入流、字节输出流、字符输入流和字符输出流 4 种。
2.4.1 字节流 InputStream & OutputStream
InputStream(典型实现类:FileInputStream):
抽象类 java.io.InputStream 是所有字节输入流的父类,该类定义了读取字节数据的基本方法。下面是 InputStream 类中常用的方法。
- public abstract int read():读一个字节作为方法的返回值。返回 0 到 255 范围内的 int 字节值。如果返回 -1,则表示到达流的末尾。
- public int read(byte[] b):将读取的数据保存在一个字节数组中,并返回读取的字节数。
- public int read(byte[] b, int off, int len):从输入流中读取 len 个字节存储在初始偏移量为 off 的字节数组中,返回实际读取的字节数。如果因为流位文件末尾而没有可用的字节,则返回 -1。
- public long skip(long n):从输入流中最多跳过 n 个字节,返回跳过的字节数。
- public int available():返回此输入流中可以不受阻塞地读取(跳过)的字节数。
- public void close() throws IOException:关闭输入流,释放与流相关联的所有系统资源。
- public void mark(int readlimit):标记当前的位置,参数 readlimit 用于设置从标记位置处开始可以读取的最大字节数。
- public void reset():将输入流重新定位到最后一次 mark 方法标记的位置。
- public boolean markSupported():如果输入流支持 mark 和 reset 方法,则返回 true;否则返回false。
OutputStream(典型实现类:FileOutputStream):
抽象类 java.io.OutputStream 是所有字节输出流的父类,该类定义了输出字节数据的基本方法。下面是 OutputStream 类中常用的方法。
- public abstract void write(int b):将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 即写入 0~255 范围的。
- public void write(byte[]b):将 b.length 个字节从指定的 byte 数组写入此输出流。write(b) 的常规协定:与调用 write(b, 0, b.length) 的效果完全相同。
- public void write(byte[] b, int off, int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
- public void flush() throws IOException:刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立即写入它们预期的目标。
- public void close() throws IOException:关闭输出流,并释放与流关联的所有系统资源。
注意:
- 异常的处理:问了保证流资源一定可以执行关闭操作。需要使用 try-catch-finally 处理。
- 读入的文件一定要存在,否则就会报 FileNotFoundException。
- 程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
- FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream 用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader。
- FileOutputStream 从文件系统中的某个文件中获得输出字节。FileOutputStream 用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter
2.4.2 字符流 Reader & Writer
Reader(典型实现类:FileReader):
抽象类 java.io.Reader 是所有字符输入流的父类,该类定义了读取字符数据的基本方法。下面是 Reader 类中常用的方法。
- public int read():读一个字符作为方法的返回值,如果返回 -1,则表示到达流的末尾。
- .public int read(char[] cbuf):读字符保存在数组中,并返回读取的字符数。如果已到达流的末尾,则返回 -1。
- public abstract int read(char[] cbuf, int off, int len):读字符存储在数组的指定位置,存到数组 cbuf中,从off处开始存储,最多读 len 个字。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。
- public long skip(long n):从输人流中最多跳过n个字符,返回跳过的字符数。
- public boolean ready():当输入流准备好可以读取数据时返回 true,否则返回 false。
- public boolean markSupported():当输入流支持 mark 方法时返回 true,否则返回 false。
- public void mark(int readAheadLimit): 标记当前的位置,参数用于设置从标记位置处开始可以读取的最大字符数。
- public void reset():将输入流重新定位到最后一次 mark 方法标记的位置。
- public abstract void close() throws IOException:关闭输人流并释放与流关联的所有系统资源。
Writer(典型实现类:FileWriter):
抽象类 java.io.Writer 是所有字符输出流的父类,该类定义了输出字符数据的基本方法。下面是 Writer 类中常用的方法。
- public void write(int c):写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。 即写入0 到 65535 之间的 Unicode 码。
- public void write(char[]cbuf):写入字符数组。
- public abstract void write(char[]cbuf, int off, int len):写入字符数组的某一部分。从 off 开始,写入 len 个字符。
- public void write(String str)::将字符串 str 中的全部字符写入输出流。
- public void write(String str, int off, int len):将字符串 str 中,从偏移量 off 开始的 len 个字符写人输出流。
- public abstract void flush():刷新输出流,强制写出所有缓冲的输出字符。
- public void close() throws IOException:关闭此输出流并释放与该流关联的所有系统资源。
注意:
因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数。
- void write(String str);
- void write(String str, int off, int len);
2.4.3 输入输出的标准化过程
输入过程:
- 创建 File 类的对象,指明读取的数据的来源。(要求文件一定要存在)。
- 创建相应的输入流,将 File 类的对象作为参数,传入流的构造器中。
- 具体的读入过程:创建相应的 byte[] 或 char[]。
- 关闭流资源。(程序中出现异常需要使用 try-catch-finally 处理)
输出过程:
- 创建 File 类的对象,指明写出的数据的来源。(不要求文件一定存在)。
- 创建相应的输出流,将 File 类的对象作为参数,传入流的构造器中。
- 具体的写出过程:write(char[] / byte[] buffer, 0, len)。
- 关闭流资源。(程序中出现异常需要使用 try-catch-finally 处理)
2.5 节点流(或文件流)
2.5.1 读取文件
-
建立一个流对象,将已存在的一个文件加载进流。
FileReader fr = new FileReader(new File(“Test.txt”));
-
创建一个临时存放数据的数组。
char[] ch = new char[1024];
-
调用流对象的读取方法将流中的数据读入到数组中。
fr.read(ch);
-
关闭资源。
fr.close();
示例:
FileReader fr = null; try { fr = new FileReader(new File("c:\\test.txt")); char[] buf = new char[1024]; int len; while ((len = fr.read(buf)) != -1) { System.out.print(new String(buf, 0, len)); } } catch (IOException e) { System.out.println("read-Exception :" + e.getMessage()); } finally { if (fr != null) { try { fr.close(); } catch (IOException e) { System.out.println("close-Exception :" + e.getMessage()); } } }
2.5.2 写入文件
-
创建流对象,建立数据存放文件
FileWriter fw = new FileWriter(new File(“Test.txt”));
-
调用流对象的写入方法,将数据写入流
fw.write(“atguigu-songhongkang”);
-
关闭流资源,并将流中的数据清空到文件中。
fw.close();
示例:
FileWriter fw = null; try { fw = new FileWriter(new File("Test.txt")); fw.write("atguigu-songhongkang"); } catch (IOException e) { e.printStackTrace(); } finally { if (fw != null) try { fw.close(); } catch (IOException e) { e.printStackTrace(); } }
2.5.3 注意点
- 定义文件路径时,注意:可以用 “/” 或者 “\” 。
- 在写入一个文件时,如果使用构造器 FileOutputStream(file),则目录目录下有同名文下有同名文
件将被覆盖。 - 如果使用构造器 FileOutputStream(file, true),则目录下的同名文件不会被覆盖,在文件内容末尾追加内容。
- 在读取文件时,必须保证该文件已存在,否则报异常。
- 字节流操作字节,比如:.mp3,.avi,.rmvb,mp4,.jpg,.doc,.ppt。
- 字符流操作字符,只能操作普通文本文件。最常见的文本文件:.txt,.java,.c,.cpp 等语言的源代码。尤其注意 .doc,.excel,.ppt 这些不是文本文件。
2.5.4 文件流测试
1. FileReader 读入数据的基本操作:将 hello.txt 文件内容读入程序中,并输出到控制台。
@Test public void testFileReader() { FileReader fr = null; try { // 1.实例化 File 类的对象,指明要操作的文件 File file = new File("hello.txt"); // 相较于当前 Module // 2.提供具体的流 fr = new FileReader(file); // 3.数据的读入 // read():返回读入的一个字符。如果达到文件末尾,返回 -1 int data; while ((data = fr.read()) != -1) { System.out.print((char)data); } } catch (IOException e) { e.printStackTrace(); } finally { // 4.流的关闭操作 try { if (fr != null) { fr.close(); } } catch (IOException e) { e.printStackTrace(); } } } // FileReader 中使用 read(char[] cbuf) 读入数据 // 对 read() 操作升级:使用 read 的重载方法 @Test public void testFileReader1() throws IOException { FileReader fr = null; try { // 1.File 类的实例化 File file = new File("hello.txt"); // 2.FileReader 流的实例化 fr = new FileReader(file); // 3.读入的操作 // read(char[] cbuf):返回每次读入 cbuf 数组中的字符数。如果达到文件末尾,返回 -1。 char[] cbuf = new char[5]; int len; while ((len = fr.read(cbuf)) != -1) { // 方式一: // for (int i = 0; i < len; i++) { // len 不能写成 cbuf.length // System.out.print(cbuf[i]); // } // 方式二: String str = new String(cbuf, 0, len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally { if (fr != null) { try { // 4.资源的关闭 fr.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2. FileWriter 写出数据的操作:从内存中写出数据到硬盘文件里。
/* 说明: 1.输出操作,对应的 File 可以不存在。并不会报异常。 2. File 对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。 File 对应的硬盘中的文件如果存在: 如果流使用的构造器是:FileWriter(file, false) / FileWriter(file):对原有的文件覆盖 如果流使用的构造器是:FileWriter(file, true):不会对原有文件覆盖,二十在原有文件基础上追加内容 */ @Test public void testFileWriter() { FileWriter fw = null; try { // 1.提供 File 类的对象,指明写出到的文件 File file = new File("hello1.txt"); // 2.提供 FileWriter 的对象,用于数据的写出 fw = new FileWriter(file, true); // 3.写出的操作 fw.write("I have a dream!\n"); fw.write("you need to have a dream!"); } catch (IOException e) { e.printStackTrace(); } finally { // 4.资源流的关闭 if(fw != null) { try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
3. 使用 FileReader 和 FileWriter 实现文本文件的复制
@Test public void testFileReaderFileWriter() throws IOException { FileReader fr = null; FileWriter fw = null; try { // 1.创建 File 类的对象,指明读入和写出的文件 // 注意:不能使用字符流来处理图片等字节数据 File srcFile = new File("hello.txt"); File destFile = new File("hello2.txt"); // 2.创建输入流和输出流的对象 fr = new FileReader(srcFile); fw = new FileWriter(destFile); // 3.数据的读入和写出操作 char[] cbuf = new char[5]; int len; // 记录每次读入到 cbuf 数组中的字符数 while ((len = fr.read(cbuf)) != -1) { // 每次写出 len 个字符 fw.write(cbuf, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { // 4.关闭流资源 try { if (fw != null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (fr != null) { fr.close(); } } catch (IOException e) { e.printStackTrace(); } } }
4. 使用 FileInputStream 不能读取文本文件的测试
@Test // 使用字节流 FileInputStream 处理文本文件,可能出现乱码 public void testFileInputStream() { FileInputStream fis = null; try { // 1.造文件 File file = new File("hello.txt"); // 2.造流 fis = new FileInputStream(file); // 3.读数据 byte[] buffer = new byte[5]; int len; // 记录每次读取的字节个数 while ((len = fis.read(buffer)) != -1) { String str = new String(buffer, 0, len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { // 4.关闭资源 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5. 使用 FileInputStream 和 FileOutputStream 读写非文本文件
// 实现对图片的复制操作 @Test public void testFileInputOutputStream() { FileInputStream fis = null; FileOutputStream fos = null; try { // File srcFile = new File("image.jpg"); File destFile = new File("image2.jpg"); // fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); // 复制的过程 byte[] buffer = new byte[5]; int len; while ((len = fis.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if(fos != null) { // try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
6. 使用 FileputStream 和 FileOutputStream 复制文件的方法测试
// 指定路径下文件的复制 public void copyFile(String srcpath, String destpath) { FileInputStream fis = null; FileOutputStream fos = null; try { // File srcFile = new File(srcpath); File destFile = new File(destpath); // fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); // 复制的过程 byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if(fos != null) { // try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void testCopyFile() { long start = System.currentTimeMillis(); String srcPath = "C:\\Users\\Desktop\\01-视频.mp4"; String destPath = "C:\\Users\\Desktop\\02-视频.mp4"; copyFile(srcPath, destPath); long end = System.currentTimeMillis(); System.out.println("复制操作花费的时间为:" + (end - start)); } }
2.6 缓冲流(处理流)
- 为了提高数据读写的速度,Java API 提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用 8192 个字节 (8Kb) 的缓冲区。
private static int DEFAULT_BUFFER_SIZE = 8192;
-
缓冲流要 “套接” 在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
-
BufferedInputStream 和 BufferedOutputStream
-
BufferedReader 和 BufferedWriter
-
-
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区。
-
当使用BufferedInputStream读取字节文件时,BufferedInputStream 会一次性从文件中读取 8192 个 (8Kb) 存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个 8192 个字节数组。
-
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法 flush() 可以强制将缓冲区的内容全部写入输出流。
-
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,因为关闭外层流的的同时,内层流也会自动的进行关闭。所以关于内层流的关闭,我们可以省略。
-
flush() 方法的使用:刷新缓冲区,调用后缓冲区未满也直接写出,清空缓冲区。即:手动将 buffer 中内容写入文件。
-
如果是带缓冲区的流对象的 close() 方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出。
2.6.1 缓冲流的测试:
1. 缓冲流(字节型)实现非文本文件的复制
@Test public void BufferedStreamTest() { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { // 1. 造文件 File srcFile = new File("image.jpg"); File destFile = new File("image3.jpg"); // 2. 造流 // 2.1 造节点流 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); // 2.2 造缓冲流 bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); // 3. 复制的细节:读取、写入 byte[] buffer = new byte[10]; int len; while ((len = bis.read(buffer)) != -1) { bos.write(buffer, 0, len); // bos.flush(); // 刷新缓冲区,调用后缓冲区未满也直接写出,清空缓冲区 } } catch (IOException e) { e.printStackTrace(); } finally { // 4. 资源关闭 // 要求:先关闭外层的流,再关闭内层的流 if(bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if(bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } // 说明:关闭外层流的的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略。 // fos.close(); // fis.close(); }
2. 缓冲流(字符型)实现文本文件的复制
/* 使用 BufferedReader 和 BufferedWriter 实现文本文件的复制(言外之意:不能处理非文本文件) */ @Test public void testBufferedReaderBufferedWriter() { BufferedReader br = null; BufferedWriter bw = null; try { // 创建文件和相应的流:造文件,造节点流,造缓冲流合成一步 br = new BufferedReader(new FileReader(new File("dbcp.txt"))); bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt"))); // 读写操作 // 方式一:使用 char[] 数组 // char[] cbuf = new char[1024]; // int len; // while ((len = br.read(cbuf)) != -1) { // bw.write(cbuf, 0, len); // // bw.flush(); // } // 方式二:使用 String String data; while ((data = br.readLine()) != null) { // 方法一 // bw.write(data + "\n"); // data 中不包含换行符 // 方法二 bw.write(data); bw.newLine(); // 提供换行的操作 } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (bw != null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2.7 转换流(处理流)
- 转换流提供了在字节流和字符流之间的转换。
- Java API 提供了两个转换流:
- InputStreamReader:将 InputStream 转换为 Reader。
- OutputStreamWriter:将 Writer 转换为 OutputStream。
- 当字节流中的数据都是字符时,转成字符流操作更高效。
- 很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。
- 解码:字节、字节数组 → 字符数组、字符串
- 编码:字符数组、字符串 → 字节、字节数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vv3MI4h6-1640706447495)(D:\单宇楠\md文档\md插图\IO流5.jpg)]
InputStreamReader
实现将字节的输入流按指定字符集转换为字符的输入流。需要和 InputStream “套接”。
构造器:
- public InputStreamReader(InputStream in)
- public InputSreamReader(InputStream in, String charsetName)
charsetName 为字符集的名称,如:InputStreamReader isr = new InputStreamReader(fis, “UTF-8”);
OutputStreamWriter
实现将字符的输出流按指定字符集转换为字节的输出流。需要和 OutputStream “套接”。
构造器:
- public OutputStreamWriter(OutputStream out)
- public OutputSreamWriter(OutputStream out, String charsetName)
2.7.1 转换流的测试
InputStreamReader 的使用,实现字节的输入流到字符的输入流的转换
/* 此时处理异常仍应该使用 try-catch-finally(偷懒写法) */ @Test public void test1() throws IOException { FileInputStream fis = new FileInputStream("dbcp.txt"); // InputStreamReader isr = new InputStreamReader(fis); // 使用系统默认的字符集 // 参数 2 指明了字符集,具体使用哪个字符集取决于文件 dbcp.txt 保存时使用的字符集 InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); char[] cbuf = new char[20]; int len; while((len = isr.read(cbuf)) != -1) { String str = new String(cbuf, 0, len); System.out.print(str); } isr.close(); }
转换流实现文件的读入和写出,综合使用 InputStreamReader 和 OutputStreamWriter
/* 此时处理异常仍应该使用 try-catch-finally(偷懒写法) */ @Test public void test2() throws Exception { // 1.造文件、造流 File file1 = new File("dbcp.txt"); File file2 = new File("dbcp_gbk.txt"); FileInputStream fis = new FileInputStream(file1); FileOutputStream fos = new FileOutputStream(file2); InputStreamReader isr = new InputStreamReader(fis, "utf-8"); OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk"); // 2.读写过程 char[] cbuf = new char[20]; int len; while ((len = isr.read(cbuf)) != -1) { osw.write(cbuf, 0, len); } // 3.关闭资源 isr.close(); osw.close(); }
2.8 标准输入、输出流(处理流)
在 java.lang.System 类中,定义了系统标准输入流 in 和 标准输出流 out。系统标准流在 Java 程序运行时会自动提供,标准输入流 System.in 将会读取键盘的输入,标准输出流将数据在控制台窗口中输出。
- System.in 的类型是 InputStream。
- System.out 的类型是 PrintStream,其是 OutputStream 的子类。
重定向:通过 System 类的 setIn,setOut 方法对默认设备进行改变。setIn(InputStream is) / setOut(PrintStream ps) 重新指定输入和输出的流。
- public static void setIn(InputStream in)
- public static void setOut(PrintStream out)
2.8.1 标准输入、输出流的测试
从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,直至当输入 “e” 或者 “exit” 时,退出程序。
public static void main(String[] args) { BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr); while (true) { System.out.println("请输入字符串:"); String data = br.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 { if(br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2.9 打印流(处理流)
实现将基本数据类型的数据格式转换为字符串输出。
打印流:PrintStream 和 PrintWriter
- 提供了一系列重载的 print() 和 println() 方法,用于多种数据类型的输出。
- PrintStream 和 PrintWriter 的输出不会抛出 IOException 异常。
- PrintStream 和 PrintWriter 有自动 flush 功能。
- PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
- System.out 返回的是 PrintStream 的实例。
2.9.1 打印流的测试
将 ASCII 码打印到 D: \IO\text.txt 文件中。
PrintStream ps = null; try { FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt")); // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区) ps = new PrintStream(fos, true); if (ps != null) {// 把标准输出流(控制台输出)改成文件 System.setOut(ps); } //如果只有 for 循环中的内容,就是在控制台中打印 ASCII 码 for (int i = 0; i <= 255; i++) { // 输出ASCII字符 System.out.print((char) i); if (i % 50 == 0) { // 每50个数据一行 System.out.println(); // 换行 } } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (ps != null) { ps.close(); } }
2.10 数据流(处理流)
为了方便地操作 Java 语言的基本数据类型和 String 的数据,可以使用数据流。
数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
- 数据输入流 DataInputStream 类,“套接” 在 InputStream 子类的流上。
- 数据输出流 DataOutputStream 类,“套接” 在 OutputStream 子类的流上。
DataInputStream 中的常用方法:
- boolean readBoolean()
- byte readByte()
- char readChar()
- char readChar()
- double readDouble()
- short readShort()
- long readLong()
- int readInt()
- String readUTF():返回使用 UTF-8 编码的字符串。
DataOutputStream 中的常用方法:
- boolean writeBoolean()
- byte writeByte()
- char writeChar()
- char writeChar()
- double writeDouble()
- short writeShort()
- long writeLong()
- int writeInt()
- String writeUTF()
2.10.1 数据流的测试
将内存中的字符串、基本数据类型的变量写出到文件中。
@Test public void test3() throws IOException { // 偷懒抛异常 // 1. DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt")); //2. dos.writeUTF("中国人"); // dos.flush(); // 刷新操作,将内存中的数据写入文件 dos.writeInt(18); // dos.flush(); dos.writeBoolean(true); // dos.flush(); //3. dos.close(); }
将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
@Test public void test4() throws IOException { // 偷懒抛异常 // 注意:读取不同类型的数据的顺序要与当初写入文件时,保存的数据顺序一致。 // 1. DataInputStream dis = new DataInputStream(new FileInputStream("data.txt")); // 2. String name = dis.readUTF(); int age = dis.readInt(); boolean isMale = dis.readBoolean(); System.out.println("name = " + name); System.out.println("age = " + age); System.out.println("isMale = " + isMale); // 3. dis.close(); }
2.11 对象流(处理流)
对象流包括 ObjectInputStream 和 OjbectOutputSteam 。用于存储和读取基本数据类型或对象的处理流。它的强大之处就是可以把 Java 中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化与反序列化
- 序列化:用 ObjectOutputStream 类保存基本类型数据或对象的机制。
- 反序列化:用 ObjectInputStream 类读取基本类型数据或对象的机制。
注意:ObjectOutputStream 和 ObjectInputStream 不能序列化 static 和 transient 修饰的成员变量。
对象的序列化
对象序列化机制允许把内存中的 Java 对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的 Java 对象。序列化的好处在于可将任何实现了 Serializable 接口的对象转化为字节数据,使其在保存和传输时可被还原。
注意:如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出 NotSerializableException 异常。
- Serializable
- Externalizable
凡是实现 Serializable 接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID。serialVersionUID 用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象
进行版本控制,有关各版本反序列化时是否兼容。如果类没有显示定义这个静态常量,它的值是 Java 运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,
显式声明。
简单来说,Java 的序列化机制是通过在运行时判断类的 serialVersionUID 来验证版本一致性的。在进行反序列化时,JVM 会把传来的字节流中的 serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
2.11.1 对象流的测试
对象流序列化与反序列化字符串操作
/* 序列化过程:将内存中的 java 对象保存到磁盘中或通过网络传输出去 使用 ObjectOutputStream 实现 */ @Test public void testObjectOutputStream() { ObjectOutputStream oos = null; try { // 1.造流 oos = new ObjectOutputStream(new FileOutputStream("object.dat")); // 2.造对象 oos.writeObject(new String("我爱北京天安门")); oos.flush(); // 刷新操作 } catch (IOException e) { e.printStackTrace(); } finally { if(oos != null) { try { // 3.关闭流 oos.close(); } catch (IOException e) { e.printStackTrace(); } } } /* 反序列化:将磁盘文件中的对象还原为内存中的一个 java 对象 使用 ObjectInputStream 来实现 */ @Test public void testObjectInputStream() { ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream("object.dat")); Object obj = ois.readObject(); String str = (String) obj; System.out.println(str); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if(ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
自定义类实现序列化与反序列化操作
若某个类实现了 Serializable 接口,该类的对象就是可序列化的:
- 一个创建一个 ObjectOutputStream
- 调用调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象
- 注意写出一次,操作 flush() 一次
反序列化:
- 创建一个 ObjectInputStream
- 调用 readObject() 方法读取流中的对象
注意:如果某个类的属性不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化。
Person 类
/** * Person 需要满足如下要求,方可序列化 * 1.需要实现接口:Serializable * 2.当前类提供一个全局常量:serialVersionUID * 3.除了当前 Person 类需要实现 Serializable 接口之外,还必须保证其内部所有属性也是可序列化的。 (默认情况下,基本数据类型是可序列化) 注意:ObjectOutputStream 和 ObjectInputStream 不能序列化 static 和 transient 修饰的成员变量。 */ public class Person implements Serializable { public static final long serialVersionUID = 435345324535L; private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } 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; } }
测试类
// 序列化 @Test public void testObjectOutputStream() { ObjectOutputStream oos = null; try { // 1. oos = new ObjectOutputStream(new FileOutputStream("object.dat")); // 2. oos.writeObject(new String("我爱北京天安门")); oos.flush(); // 刷新操作 oos.writeObject(new Person("张三", 23)); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if(oos != null) { try { // 3. oos.close(); } catch (IOException e) { e.printStackTrace(); } } } } // 反序列化 @Test public void testObjectInputStream() { ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream("object.dat")); Object obj = ois.readObject(); String str = (String) obj; Person p = (Person) ois.readObject(); System.out.println(str); System.out.println(p); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if(ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2.12 随机存取文件类(RandomAccessFile 类)
RandomAccessFile 声明在 java.io 包下,但直接继承于 java.lang.Object 类。并且它实现了 DataInput、DataOutput 这两个接口,也就意味着这个类既可以读也可以写。RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件。
- 支持只访问文件的部分内容。
- 可以向已存在的文件后追加内容。
RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。
RandomAccessFile 类对象可以自由移动记录指针:
- long getFilePointer():获取文件记录指针的当前位置。
- void seek(long pos):将文件记录指针定位到 pos 位置。
构造器
- public RandomAccessFile(File file, String mode)
- public RandomAccessFile(String name, String mode)
创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式:
- r:以只读方式打开。
- rw:打开以便读取和写入。
- rwd:打开以便读取和写入;同步文件内容的更新。
- rws:打开以便读取和写入;同步文件内容和元数据的更新。
如果模式为只读 r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。 如果模式为rw读写,如果文件不存在则会去创建文件,如果存在则不会创建。
2.12.1 随机存取文件类的测试
RandomAccessFile 实现数据的读写操作
/** * RandomAccessFile 的使用 * 1.RandomAccessFile 直接继承于 java,lang.Object 类,实现了 DataInput 和 DataOutput 接口 * 2.RandomAccessFile 既可以作为一个输入流,又可以作为一个输出流 * 3.如果 RandomAccessFile 作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。 * 如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下从头覆盖) * * 4.可以通过相关的操作,实现 RandomAccessFile ”插入“数据的效果 */ @Test public void test1() throws FileNotFoundException { RandomAccessFile rad1 = null; RandomAccessFile rad2 = null; try { // 1. rad1 = new RandomAccessFile(new File("image.jpg"), "r"); rad2 = new RandomAccessFile(new File("image1.jpg"), "rw"); // 2. byte[] buffer = new byte[1024]; int len; while((len = rad1.read(buffer)) != -1) { rad2.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { // 3. if(rad1 != null) { try { rad1.close(); } catch (IOException e) { e.printStackTrace(); } } if(rad2 != null) { try { rad2.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test2() throws IOException { RandomAccessFile raf1 = new RandomAccessFile("hi.txt", "rw"); raf1.write("xyz".getBytes()); raf1.close(); }
RandomAccessFile 实现数据的插入操作
/* 使用 RandomAccessFile 实现数据的插入效果 */ @Test public void test3() throws IOException { RandomAccessFile raf1 = new RandomAccessFile("hi.txt", "rw"); raf1.seek(3); // 将指针调到角标为 3 的位置 // 保存指针 3 后面的所有数据到 StringBuilder 中 StringBuilder builder = new StringBuilder((int) new File("hi.txt").length()); // 指定 builder 的长度 byte[] buffer = new byte[20]; int len; while((len = raf1.read(buffer)) != -1) { builder.append(new String(buffer, 0, len)); } // 调回指针,写入 ”xyz“ raf1.seek(3); raf1.write("xyz".getBytes()); // 将 StringBuilder 中的数据写入到文件中 raf1.write(builder.toString().getBytes()); // 先 toString 得到一个字符串 }
3 字符编码集的说明
编码表的由来
计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表
- ASCII:美国标准信息交换码。用一个字节的 7 位表示 128 个字符。
- ISO-8859-1:拉丁码表。欧洲码表。用一个字节的 8 位表示,单字节编码,向下兼容 ASCII。
- GB2312:信息交换用汉字编码字符集(中国的中文编码表)。最多两个字节编码所有字符。
- GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码。GBK 等双字节编码方式,用最高位是 1 或 0 表示两个字节和一个字节。
- Unicode:统一码,也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。Unicode 只是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的编号,具体存储成什么样的字节流,取决于字符编码方案。推荐的 Unicode 编码是 UTF-8 和 UTF-16 。
- UTF-8:为了提高 Unicode 的编码效率,于是就出现了 UTF-8 编码。变长的编码方式,UTF-8 可以根据不同的符号自动选择编码的长短。
4 Java NIO
4.1 Java NIO 概述
Java NIO (New IO,Non-Blocking IO) 是从 Java 1.4 版本开始引入的一套新的 IO API,可以替代标准的Java IO API。NIO 与原来的 IO 有同样的作用和目的,但是使用的方式完全不同,NIO 支持面向缓冲区的(IO 是面向流的)、基于通道的 IO 操作。NIO 将以更加高效的方式进行文件的读写操作。
Java API 中提供了两套 NIO,一套是针对标准输入输出 NIO,另一套就是网络编程 NIO。
- java.nio.channels.Channel
- FileChannel:处理本地文件
- SocketChannel:TCP 网络编程的客户端的 Channel
- ServerSocketChannel:TCP 网络编程的服务器端的 Channel
- DatagramChannel:UDP 网络编程中发送端和接收端的 Channel
随着 JDK 7 的发布,Java 对 NIO 进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2。因为 NIO 提供的一些功能,NIO 已经成为文件处理中越来越重要的部分。
4.2 Path、Paths 和 Files 核心 API
早期的 Java 只提供了一个 File 类来访问文件系统,但 File 类的功能比较有限,所提供的方法性能也不高。而且大多数方法在出错时仅返回失败,并不会提供异常信息。NIO. 2 为了弥补这种不足,引入了 Path 接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path 可以看成是 File类 的升级版本,实际引用的资源也可以不存在。
在以前 IO 操作都是这样写的:
import java.io.File; File file = new File("index.html");
但在 Java 7 中,可以这样写:
import java.nio.file.Path; import java.nio.file.Paths; Path path = Paths.get("index.html");
同时,NIO.2 在 java.nio.file 包下还提供了 Files、Paths 工具类,Files 包含了大量静态的工具方法来操作文件;Paths 则包含了两个返回 Path 的静态工厂方法。
Paths 类提供的静态 get() 方法用来获取 Path 对象:
- static Path get(String first, String … more):用于将多个字符串串连成路径。
- static Path get(URI uri):返回指定 uri 对应的 Path 路径。
Path 接口
Path 常用方法:
- String toString():返回调用 Path 对象的字符串表示形式 。
- boolean startsWith(String path):判断是否以 path 路径开始。
- boolean endsWith(String path):判断是否以 path 路径结束。
- boolean isAbsolute():判断是否是绝对路径。
- PathgetParent():返回 Path 对象包含整个路径,不包含 Path 对象指定的文件路径。
- Path getRoot():返回调用 Path 对象的根路径。
- Path getFileName():返回与调用 Path 对象关联的文件名。
- int getNameCount():返回 Path 根目录后面元素的数量。
- Path getName(int idx):返回指定索引位置 idx 的路径名称。
- Path toAbsolutePath():作为绝对路径返回调用 Path 对象。
- Path resolve(Pathp):合并两个路径,返回合并后的路径对应的 Path 对象
- File toFile():将 Path 转化为 File 类的对象。
Files 类
java.nio.file.Files 用于操作文件或目录的工具类。
Files 常用方法:
- Path copy(Path src,Path dest,CopyOption … how):文件的复制。
- Path createDirectory(Path path, FileAttribute<?>… attr):创建一个目录。
- Path createFile(Path path, FileAttribute<?>… arr):创建一个文件。
- void delete(Path path):删除一个文件/目录,如果不存在,执行报错。
- void deletelfExists(Path path):Path 对应的文件/目录如果存在,执行删除
- Path move(Path src,Path dest,CopyOption…how):将 src 移动到 dest 位置。
- long size(Path path):返回 path 指定文件的大小。
Files 常用方法:用于判断
- boolean exists(Path path, LinkOption … opts) :判断文件是否存在。
- boolean isDirectory(Path path, LinkOption … opts):判断是否是目录。
- boolean isRegularFile(Path path, LinkOption … opts):判断是否是文件。
- boolean isHidden(Path path):判断是否是隐藏文件。
- boolean isReadable(Path path):判断文件是否可读。
- boolean isWritable(Path path):判断文件是否可写。
- boolean notExists(Path path, LinkOption … opts):判断文件是否不存在。
Files 常用方法:用于操作内容
- SeekableByteChannel newByteChannel(Path path, OpenOption…how):获取与指定文件的连接,how 指定打开方式。
- DirectoryStream
newDirectoryStream(Path path):打开 path 指定的目录。 - InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象。
- OutputStream newOutputStream(Path path, OpenOption…how):获取 OutputStream 对象。
调用 Path 对象的根路径。 - Path getFileName():返回与调用 Path 对象关联的文件名。
- int getNameCount():返回 Path 根目录后面元素的数量。
- Path getName(int idx):返回指定索引位置 idx 的路径名称。
- Path toAbsolutePath():作为绝对路径返回调用 Path 对象。
- Path resolve(Pathp):合并两个路径,返回合并后的路径对应的 Path 对象
- File toFile():将 Path 转化为 File 类的对象。
Files 类
java.nio.file.Files 用于操作文件或目录的工具类。
Files 常用方法:
- Path copy(Path src,Path dest,CopyOption … how):文件的复制。
- Path createDirectory(Path path, FileAttribute<?>… attr):创建一个目录。
- Path createFile(Path path, FileAttribute<?>… arr):创建一个文件。
- void delete(Path path):删除一个文件/目录,如果不存在,执行报错。
- void deletelfExists(Path path):Path 对应的文件/目录如果存在,执行删除
- Path move(Path src,Path dest,CopyOption…how):将 src 移动到 dest 位置。
- long size(Path path):返回 path 指定文件的大小。
Files 常用方法:用于判断
- boolean exists(Path path, LinkOption … opts) :判断文件是否存在。
- boolean isDirectory(Path path, LinkOption … opts):判断是否是目录。
- boolean isRegularFile(Path path, LinkOption … opts):判断是否是文件。
- boolean isHidden(Path path):判断是否是隐藏文件。
- boolean isReadable(Path path):判断文件是否可读。
- boolean isWritable(Path path):判断文件是否可写。
- boolean notExists(Path path, LinkOption … opts):判断文件是否不存在。
Files 常用方法:用于操作内容
- SeekableByteChannel newByteChannel(Path path, OpenOption…how):获取与指定文件的连接,how 指定打开方式。
- DirectoryStream
newDirectoryStream(Path path):打开 path 指定的目录。 - InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象。
- OutputStream newOutputStream(Path path, OpenOption…how):获取 OutputStream 对象。
这篇关于【Java】IO 流的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-06小米11i印度快充版ROM合集:极致体验,超越期待
- 2024-10-06【ROM下载】小米11i 5G 印度版系统, 疾速跃迁,定义新速度
- 2024-10-06【ROM下载】小米 11 青春活力版,青春无极限,活力全开
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求