Java IO流详解
JAVA IO详解
File
概述
File类可以定位文件,进行删除、获取文本本身信息等操作。但是不能读写文件。
- File类在包java.io.File下、代表操作系统的文件对象(文件、文件夹)
- File类提供了诸如:定位文件,获取文件本身的信息、删除文件、创建文件(文件夹)等功能
创建File对象
// 根据文件路径创建文件对象
public File(String pathname)
// 从父路径和子路径名字字符串创建文件对象
public File(String parent, String child)
// 根据父路径对应文件对象和子路径名字符串创建文件对象
public File(File parent, String child)
File.separator
路径连接符,用于拼接路径
new File("D:" + File.separator + "data" + File.separator + "1.txt")
常用API
获取文件信息
public boolean isDirectory()
测试此抽象路径名表示的File是否为文件夹
public boolean isFile()
测试此抽象路径名表示的File是否为文件
public boolean exists()
测试此抽象路径名表示的File是否存在
public String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串
public String getPath()
将此抽象路径名转换为路径名字符串
public String getName()
返回由此抽象路径名表示的文件或文件夹的名称
public long lastModified()
返回文件最后修改的时间毫秒值
创建、删除文件
public boolean createNewFile()
创建一个新的空的文件
public boolean mkdir()
只能创建一级文件夹
public boolean mkdirs()
可以创建多级文件夹
public boolean delete( )
删除由此抽象路径名表示的文件或空文件夹
delete方法直接删除不走回收站;如果删除的是-一个文件,且文件没有被占用则直接删除。
delete方法默认只能删除空文件夹。
遍历文件
public String[] list()
获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
public File[] listFiles()(常用)
获取当前目录 下所有的"一-级文件对象"到一个文件对象数组中去返回(重点)
listFiles方法注意事项:
- 当调用者不存在时,返回null
- 当调用者是一个文件时,返回null
- 当调用者是一个空文件夹时,返回一个长度为0的数组
- 当调用者是一个有内容的文件夹时, 将里面所有文件和文件夹的路径放在File数组中返回
- 当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容
字符集
ASCII字符集
ASCII(American Standard Code for Information Interchange, 美国信息交换标准代码):包括了数字、英文、符号.
ASCII使用1个字节存储一个字符,一个字节是8位,总共可以表示128个字符信息,对于英文,数字来说是够用的。
01100001 = 97 => a
01100010 = 98 => b
GBK
window系统默认的码表。兼容ASCI码表,也包含了几万个汉字,并支持繁体汉字以及部分日韩文字。
注意: GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字。
Unicode码
unicode (又称统一码、万国码、单一码)是计算机科学领域里的一项业界字符编码标准
容纳世界上大多数国家的所有常见文字和符号
由于Unicode会先通过UTF-8, UTF-16, 以及UTF-32的编码成二进制后再存储到计算机,其中最为常见的就是UTF-8
注意
- Unicode是万国码, 以UTF-8编码后一个中文一般以三个字节的形式存储。
- UTF-8也要兼容ASCII编码表。
- 技术人员都应该使用UTF-8的字符集编码。
- 编码前和编码后的字符集需要一致,否则会出现中文乱码。
String编码
byte[] getBytes()
使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
byte[] getBytes(String charsetName)
使用指定的字符集将该String编码为-系列字节,将结果存储到新的字节数组中
String解码
String(byte[] bytes)
通过使用平台的默认字符集解码指定的字节数组来构造新的String
String(byte[] bytes, String charsetName)
通过指定的字符集解码指定的字节数组来构造新的String
IO流
IO流概述
- I表示intput, 是数据从硬盘文件读入到内存的过程,称之输入,负责读。
- O表示output, 是内存程序的数据从内存到写出到硬盘文件的过程,称之输出,负责写。
IO流四大类
字节输入流
以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
字节输出流
以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流
字符输入流
以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流
字符输出流
以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流
字节流
FileInputStream
将磁盘文件、网络中的数据以字节的形式读取到内存中去
构造器
// 创建字节输入流管道与源文件对象接通
public FileInputStream(File file)
// 创建字节输入流管道 与源文件路径接通
public FileInputStream(String pathname)
方法
// 每次读取一个字节返回,如果字节已经没用可读的返回-1
public int read()
// 每次读取一个字节数组返回,如果字节已经没有可读的返回-1,返回的读取数组的长度
public int read(byte[] buffer)
字节流读取中文乱码问题
因为字节输入流是按照字节的方式读取的,而中文是双字节或者三字节的,可能会使得中文字节从中截断以造成中文乱码的问题。
解决
-
一次性读取文件的全部字节(但数据过大可能造成内存溢出)
-
官方提供了一个API可以直接把文件的全部数读取到一个字节数组中
public byte[] readAllBytes() throws IOException
FileOutputStream
把内存中的数据以字节写出到磁盘文件或者网络中去的流
构造器
public FileOutputStream(String name)
// append为true则追加的文件的末尾,为false则覆写文件
public FileOutputStream(String name, boolean append)
public FileOutputStream(File file)
public FileOutputStream(File file, boolean append)
方法
public void write(int a)
// 写一个字节出去
public void write(byte[] buffer)
// 写一个字节数组出去
public void write(byte[] buffer ,int pos,int len)
// 写一个字节数组的一部分出去。
流的关闭与刷新
// 刷新流,还可以继续写数据,将在缓冲区的信息刷新到文件或网络中
flush()
// 关闭流,释放资源,但是在关闭之前线刷新流。一旦关闭就不再写数据
close()
资源释放的方式
try-cath-finally
finally:在异常处理时提供finally块来执行所有清除操作,比如说IO流中的释放资源
特点:被finally控制的语句最终一定会执行, 除非JVM退出
try {
} catch (Exception e) {
} finally {
}
此方式多用于JDK7以前,JDK7和JDK9做了改进
// JDK7 资源用完会自动释放
try (定义流对象) {
} catch () {
}
// JDK9 资源用完会自动释放
定义流对象
try (流对象) {
} catch () {
}
转换流
字节流和字符流之间的桥梁
InputStreamReader
字节到字符桥梁
构造器
// 默认字符集
public InputStreamReader(InputStream in)
// 指定字符集编码
public InputStreamReader(InputStream in, String charsetName)
方法
public int read()
// 每次读取一个字符返回,如果字符已经没有可读的返回-1
public int read(char[] buffer)
// 每次读取一个字符数组,返回读取的字符数,如果字符已经没有可读的返回-1
示例:字节流System.In转为字符流
public static void main(String[] args) throws IOException {
//字节流-->字符流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("is2.txt"));
String line = null;
while((line = br.readLine())!=null){
if("over".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
OutputStreamWriter
字符到字节的桥梁
构造器
// 默认字符集
public OutputStreamWriter(OutputStream out)
// 指定字符集编码
public OutputStreamWriter(OutputStream out, String charsetName)
方法
void write(int c)
void write(char[] cbuf)
void write(char[] cbuf, int off, int len)
void write(String str)
void write(String str, int off, int len)
void write(int c)
// 刷新流,还可以继续写数据,将在缓冲区的信息刷新到文件或网络中
flush()
// 关闭流,释放资源,但是在关闭之前线刷新流。一旦关闭就不再写数据
close()
示例:字符流转为字节流System.out
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("is2.txt"));
//字符流-->字节流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ((line = br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
字符流
FileReader
来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流
FileReader继承自输入转换流,实际与输入转换流一致,并未实现更多的方法
不过提供了更多的构造器方法
public class FileReader extends InputStreamReader
构造器
不指定字符集的时候,就会使用默认的字符集来读取数据
// 构造方法与FileInputStream类似,多出了一个字符集参数
public FileReader(String fileName)
public FileReader(String fileName, Charset charset)
public FileReader(File file)
public FileReader(File file, Charset charset)
方法
public int read()
// 每次读取一个字符返回,如果字符已经没有可读的返回-1
public int read(char[] buffer)
// 每次读取一个字符数组,返回读取的字符数,如果字符已经没有可读的返回-1
FileWriter
把内存中的数据以字符写出到磁盘文件或者网络介质中去的流
FileWriter继承自转换流,实际与输出转换流一致,并未实现更多的方法
不过提供了更多的构造器方法
public class FileWriter extends OutputStreamWriter
构造器
// append: 可追加到文件末尾
// charset: 字符编码集
public FileWriter(File file)
public FileWriter(File file, boolean append)
public FileWriter(String fileName, Charset charset)
public FileWriter(String fileName, Charset charset, boolean append)
public FileWriter(String filepath)
public FileWriter(String filepath, boolean append)
public FileWriter(File file, Charset charset)
public FileWriter(File file, Charset charset, boolean append)
方法
void write(int c)
void write(char[] cbuf)
void write(char[] cbuf, int off, int len)
void write(String str)
void write(String str, int off, int len)
void write(int c)
// 刷新流,还可以继续写数据,将在缓冲区的信息刷新到文件或网络中
flush()
// 关闭流,释放资源,但是在关闭之前线刷新流。一旦关闭就不再写数据
close()
缓冲流
缓冲流也称为高效流,或者高级流。之前学习的字节流可以称为原始流。
作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能。
BufferredInputStream
字节缓冲输入流:提高字节输入流读取数据的性能,读写功能无变化,方法与字节输入流一致
构造器
将低级的字节输入流包装成一个高级的缓冲字节输入流
// 默认缓冲区8kb
public BufferedInputStream(InputStream in)
// 指定buffer的大小
public BufferedInputStream(InputStream in, int size)
BufferedOutputStream
字节缓冲输出流:提高字节输出流读取数据的性能,读写功能无变化
构造器
将低级的字节输出流包装成一个高级的缓冲字节输出流
// 默认缓冲区8kb
public BufferedOutputStream(OutputStream out)
// 指定buffer的大小
public BufferedOutputStream(OutputStream out, int size)
BufferedReader
字符缓冲输入流:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能
构造器
把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能
// 默认缓冲区8kb
public BufferedReader(Reader in)
// 指定buffer的大小
public BufferedReader(Reader in, int sz)
新增API
// 读取一行数据返回,如果读取没有完毕,无行可读返回null
public String readline()
BufferedWriter
字符缓冲输出流:提高字符输出流写数据的性能,除此之外多了换行功能
构造器
// 默认缓冲区8kb
public BufferedWriter(Writer out)
// 指定buffer的大小
public BufferedWriter(Writer out, int sz)
新增API
// 换行操作
public void newLine()
序列化
对象序列化
ObjectOutputStream
把内存中的对象存储到磁盘文件中去
构造器
// 将低级的字符输出流包装成高级的对象字节输出流
public ObjectOutputStream(OutputStream out)
方法
// 把对象写出到对象序列化流的文件中去
public final void writeObject(Object obj)
对象反序列化
ObjectInputStream
把存储到磁盘文件中去的对象数据恢复到内存中
构造器
// 将低级的字符输入流包装成高级的对象字节输入流
public ObjectInputStream(InputStream in)
方法
// 把磁盘文件中的对象数据恢复成内存中的对象
public Object readObject()
打印流
打印流可以实现方便、高效的打印数据到文件中去
可以实现打印什么数据就是什么数据
PrintStream
核心构造器
private PrintStream(boolean autoFlush, OutputStream out) {
super(out);
this.autoFlush = autoFlush;
this.charOut = new OutputStreamWriter(this, charset);
this.textOut = new BufferedWriter(charOut);
}
PrintStream会构建三个流
-
字节输出流
-
字符转换输出流
-
字符缓冲输出流
可以同时实现打印字节和字符
字节输出使用 FileOutputStream流实现
字符输出使用 BufferedWriter流实现
构造器
// 提供了三种构造器
// 文件名 文件对象 字节输出流
public PrintStream(OutputStream out)
public PrintStream(OutputStream out, boolean autoFlush)
public PrintStream(OutputStream out, boolean autoFlush, Charset charset)
public PrintStream(String fileName)
public PrintStream(String fileName, Charset charset)
public PrintStream(File file)
public PrintStream(File file, Charset charset)
方法
// 可打印任意类型数据
// 前提是类型重写了toString()方法
// int float double boolean等基本类型会使用包装类型返回string
public void print(XXX xxx)
public void println(XXX xxx)
PrintWriter
核心构造器
public PrintWriter(OutputStream os)
// 打印流直接通向字节输出流管道
public PrintWriter (Writer w)
// 打印流直接通向字符输出流管道
public PrintWriter (File f)
// 打印流直接通向文件对象
public PrintWriter (String filepath)
// 打印流直接通向文件路径
方法
// 可打印任意类型数据
// 前提是类型重写了toString()方法
// int float double boolean等基本类型会使用包装类型返回string
public void print(XXX xxx)
public void println(XXX xxx)
对比
- 打印数据功能上是一模一样的,使用方便,性能高效
- PrintStream继承自字节输出流,支持写字节数据
- PrintWriter继承自字符输出流Writer,支持写字符数据
打印流重定向
可以将输出语句的打印位置改到文件
PrintStream ps = new PrintStream("文件地址")
System.setOut(ps);
Properties
实际是一个Map集合
核心功能
- Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去
- 属性文件:后缀树
.properties
结尾的文件,里面的内容都是key=value,后续做系统配置信息
方法
// 从输入字节流读取属性列表(键和元素对)
void load(InputStream inStream)
// 从输入字符流读取属性列表(键和元素对)
void load(Reader reader)
// 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流
void store (OutputStream out, String comments)
// 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流
void store(Writer writer, String comments)
// 保存键值对(put)
public object setProperty(String key, String value)
// 使用此属性列表中指定的键搜索属性值(get)
public String getProperty(String key)
// 所有键的名称的集合(keySet()
public Set<String> stringPropertyNames()