File和IO流
- 存储&读写数据的方案
- File
- 方法的递归
- 字符集
- IO流
- io流的分类
-
- 字节流
- FileInputStream(文件字节输入流)
- FileOutputStream(文件字节输出流)
- 文件赋值
- 资源释放的方案
- 字符流
- FileReader文件字符输入流
- FileWriter文件字符输出流
- 缓冲流
-
- 其他流
- InputStreamReader 字符输入转换流
- 打印流
- IO 框架
存储&读写数据的方案
- 存储数据方案
- 变量:double money = 111.1;
- 数组:int[] age = new int[100];
- 对象:Student s = ne wStudent();
- 集合:List students = new ArrayList<>();
- 这些数据容器都在内存中,一旦程序结束,或者断电,数据就没有了.
- File
- 文件可以长久保存数据。
- 文件在电脑磁盘中保存,即便断电,或者程序终止,文件中的数据也不会丢失。
- File是java.io包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)。
- File类只能对文件本身进行操作,不能读写文件里面存储的数据。
- IO流
- 用于读写数据的(可以是读写文件,或网络中的数据…)
File
- File类的对象可以代表文件/文件夹,并可以调用其提供的方法对象文件进行操作。
- 创建File类的对象
- File对象既可以代表文件、也可以代表文件夹。
- File封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许不存在的。
构造器 | 说明 |
---|
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent, String child) | 根据父路径和子路径名字创建文件对象 |
public File(File parent, String child) | 根据父路径对应文件对象和子路径名字创建文件对象 |
- 绝对路径:从盘符开始
- 相对路径:不带盘符,默认直接到当前工程下的目录寻找文件。
- File提供的判断文件类型、获取文件信息功能
方法名称 | 说明 |
---|
public boolean exists() | 判断当前文件对象,对应的文件路径是否存在,存在返回true |
public boolean isFile() | 判断当前文件对象指代的是否是文件,是文件返回true,反之。 |
public boolean isDirectory() | 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之。 |
public String getName() | 获取文件的名称(包含后缀) |
public long length() | 获取文件的大小,返回字节个数 |
public long lastModified() | 获取文件的最后修改时间。 |
public String getPath() | 获取创建文件对象时,使用的路径 |
public String getAbsolutePath() | 获取绝对路径 |
方法名称 | 说明 |
---|
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 只能创建一级文件夹 |
public boolean mkdirs() | 可以创建多级文件夹 |
- 删除:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站。
方法名称 | 说明 |
---|
public boolean delete() | 删除文件、空文件夹 |
方法名称 | 说明 |
---|
public String[] list() | 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。 |
public File[] listFiles() | 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点) |
- 使用listFiles方法时的注意事项:
- 当主调是文件,或路径不存在时,返回null。
- 当主调是空文件夹时,返回一个长度为0的数组。
- 当主调是一个有内容的文件夹时,将里面所有的以及文件和文件夹的路径放在File数组中返回。
- 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件。
- 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null。
方法的递归
- 递归是一种算法,在程序设计语言中广泛应用。
- 从形式上说:方法调用自身的形式称为方法递归(recursion)。
- 递归的形式
- 直接递归:方法自己调用自己。
- 间接递归:方法调用其他方法,其他方法有回调方法自己。
- 递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误。
- 递归算法三要素
- 递归的公式:f(n) = f(n-1) * n;
- 递归的终结点:f(1)
- 递归的方向必须走向终结点。
字符集
- 标准ASCII字符集
- ASCLL(American Standard Code for Information Interchange):美国信息交换标准代码。
- 标准ASCII使用1个字节存储一个字符,首位是0,因此,总共可表示128个字符。
- GBK(汉字内码扩展规范,国标)
- 汉字编码字符集,包含了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储。
- GBK兼容了ASCII字符集。
- 汉字的第一个字节的第一位必须是1
- Unicode字符集(统一码,也叫万国码)
- Unicode是国际组织制定的,可以容纳世界上所有文字、符号的字符集。
- UTF-32用4个字节表示一个字符。
- UTF-8字符集
- 是Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节
- 英文字符、数字等只占1个字节(兼容标准ASCII编码),汉字字符占用3个字节。
字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码
英文,数字一般不会乱码,因为很多字符集都兼容了ASCII编码。
- 使用程序对字符进行编码和解码操作
String提供了如下方法 | 说明 |
---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
String提供了如下方法 | 说明 |
---|
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的 String |
IO流
- 内存 --> 网络/磁盘/…
- 网络/磁盘/… --> 内存
- I指Input,称为输入流:负责把数据读到内存中。
io流的分类
- 按照流的方向:IO流分为
- 按照流的内容:IO流分为
io流的体系
字节流
FileInputStream(文件字节输入流)
- 作用:有内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
- 网络/磁盘/… --> FileInputStream ->内存
构造器 | 说明 |
---|
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通 |
方法名称 | 说明 |
---|
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1. |
public int read(byte[] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1. |
- 使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码。
- 使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
- 解决汉字乱码
方法名称 | 说明 |
---|
public byte[] readAllBytes() throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
FileOutputStream(文件字节输出流)
- 作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。
- 内存 --> FileOutputStream -->网络/磁盘/…
构造器 | 说明 |
---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileOutputStream(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
public void close() throws IOException | 关闭流。 |
- 字节输出流实现写出去的数据换行
`os.write(“\r\n”.getBytes());
文件赋值
- 任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题。
资源释放的方案
- try-catch-finally
- finally代码区的特点:无论try中的程序是正常执行了,还是出现异常,最后都一定会执行finally区,除非JVM终止。
- 作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)。
try {
...
...
} catch (IOException e) {
e.printStackTrace();
}finally{
...
}
- try-with-resource:JDK 7开始提供了更简单的资源释放方案:try-with-resource
- 该资源使用完毕后,会自动调用其close()方法,完成对资源的释放。
- () 中只能放置资源,否则报错
- 资源一般指的是最终实现了AutoCloseable接口。
try(定义资源1;定义资源2;…){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
public abstract class InputStream implements Closeable{ }
public abstract class OutputStream implements Closeable, Flushable { }
public interface Closeable extends AutoCloseable { }
字符流
FileReader文件字符输入流
- 作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
- 网络/磁盘/… --> FileReader ->内存
构造器 | 说明 |
---|
public FileReaderFile file) | 创建字符输入流管道与源文件接通 |
public FileReaderString pathname) | 创建字符输入流管道与源文件接通 |
方法名称 | 说明 |
---|
public int read() | 每次读取一个字符返回,如果发现没有数据可读会返回-1. |
public int read(char[] buffer) | 每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1. |
FileWriter文件字符输出流
- 作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
- 内存 -> FileWriter ->网络/磁盘/…
构造器 | 说明 |
---|
public FileWriter(File file) | 创建字节输出流管道与源文件对象接通 |
public FileWriter(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileWriter(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
---|
void write(int c) | 写一个字符 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
- 字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。
方法名称 | 说明 |
---|
public void flush() throws IOException | 刷新流,就是将内存中缓存的数据立即写到文件中去生效! |
public void close() throws IOException | 关闭流的操作,包含了刷新! |
缓冲流
缓冲字节流
- BufferedInputStream缓冲字节输入流
- 作用:可以提高字节输入流读取数据的性能
- 原理:缓冲字节输入流自带了8KB缓冲池;缓冲字节输出流也自带了8KB缓冲池。
构造器 | 说明 |
---|
public BufferedInputStream(InputStream is) | 把低级的字节输入流包装成一个高级的缓冲字节输入流,从而提高读数据的性能 |
public BufferedOutputStream(OutputStream os) | 把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
缓冲字符流
- BufferedReader缓冲字符输入流
- 作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。
构造器 | 说明 |
---|
public BufferedReader(Reader r) | 把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流读字符数据的性能 |
字符缓冲输入流新增的功能:按照行读取字符
方法 | 说明 |
---|
public String readLine() | 读取一行数据返回,如果没有数据可读了,会返回null |
- BufferedWriter缓冲字符输出流
- 作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能。
构造器 | 说明 |
---|
public BufferedWriter(Writer r) | 把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 |
字符缓冲输出流新增的功能:换行
方法 | 说明 |
---|
public void newLine() | 换行 |
其他流
InputStreamReader 字符输入转换流
- 解决不同编码时,字符流读取文本内容乱码的问题。
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
构造器 | 说明 |
---|
public InputStreamReader(InputStream is) | 把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
public InputStreamReader(InputStream is,String charset) | 把原始的字节输入流,按照指定字符集编码转成字符输入流(重点) |
打印流
- PrintStream/PrintWriter(打印流)
- 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
- PrintStream提供的打印数据的方案
构造器 | 说明 |
---|
public PrintStream(OutputStream/File/String) | 打印流直接通向字节输出流/文件/文件路径 |
public PrintStream(String fileName, Charset charset) | 可以指定写出去的字符编码 |
public PrintStream(OutputStream out, boolean autoFlush) | 可以指定实现自动刷新 |
public PrintStream(OutputStream out, boolean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
方法 | 说明 |
---|
public void println(Xxx xx) | 打印任意类型的数据出去 |
public void write(int/byte[]/byte[]一部分) | 可以支持写字节数据出去 |
构造器 | 说明 |
---|
public Print****Writer(OutputStream/Writer/File/String) | 打印流直接通向字节输出流/文件/文件路径 |
public PrintWriter(String fileName, Charset charset) | 可以指定写出去的字符编码 |
public PrintWriter(OutputStream out/Writer, boolean autoFlush) | 可以指定实现自动刷新 |
public PrintWriter(OutputStream out, boolean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
方法 | 说明 |
---|
public void println(Xxx xx) | 打印任意类型的数据出去 |
public void write(int/String/char[]/…) | 可以支持写字符数据出去 |
- PrintStream和PrintWriter的区别
- 打印数据的功能上是一模一样的:都是使用方便,性能高效。
- PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
- PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
##特殊数据流
- DataOutputStream(数据输出流)
构造器 | 说明 |
---|
public DataOutputStream(OutputStream out) | 创建新数据输出流包装基础的字节输出流 |
方法 | 说明 |
---|
public final void writeByte(int v) throws IOException | 将byte类型的数据写入基础的字节输出流 |
public final void writeInt(int v) throws IOException | 将int类型的数据写入基础的字节输出流 |
public final void writeDouble(Double v) throws IOException | 将double类型的数据写入基础的字节输出流 |
public final void writeUTF(String str) throws IOException | 将字符串数据以UTF-8编码成字节写入基础的字节输出流 |
public void write(int/byte[]/byte[]一部分) | 支持写字节数据出去 |
构造器 | 说明 |
---|
public DataInputStream(InputStream is) | 创建新数据输入流包装基础的字节输入流 |
方法 | 说明 |
---|
Public final byte readByte() throws IOException | 读取字节数据返回 |
public final int readInt() throws IOException | 读取int类型的数据返回 |
public final double readDouble() throws IOException | 读取double类型的数据返回 |
public final String readUTF() throws IOException | 读取字符串数(UTF-8)据返回 |
public int readInt()/read(byte[]) | 支持读字节数据进来 |
IO 框架
- 框架(Framework)是一个预先写好的代码库或一组工具,皆在简化和加速工程。
- 框架的形式:一般是吧类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。
- IO 框架:封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
- Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
FileUtils类提供的部分方法展示 | 说明 |
---|
public static void copyFile(File srcFile, File destFile) | 复制文件。 |
public static void copyDirectory(File srcDir, File destDir) | 复制文件夹 |
public static void deleteDirectory(File directory) | 删除文件夹 |
public static String readFileToString(File file, String encoding) | 读数据 |
public static void writeStringToFile(File file, String data, String charname, boolean append) | 写数据 |
IOUtils类提供的部分方法展示 | 说明 |
---|
public static int copy(InputStream inputStream, OutputStream outputStream) | 复制文件。 |
public static int copy(Reader reader, Writer writer) | 复制文件。 |
public static void write(String data, OutputStream output, String charsetName) | 写数据 |