字节流、字符流
IO概述
什么是IO
生活中,你肯定经历过这样的场景。当你编辑一个文本文件,忘记了ctrl+s
可能文件就白白编辑了。当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。
我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input
和输出 output
,即流向内存是输入流,流出内存的输出流。
java中I/O操作主要是指使用java.io
包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
IO的分类
根据数据的流向分为:输入流和输出流
- **输入流:**把数据从
其他设备
上读取到内存
中的流 - **输出流:**把数据从
内存
中写出到其他设备
上的流。
格局数据的类型分为:字节流和字符流。
顶级父类们
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流 InputStream | 字节输出流 OutputStream |
字符流 | 字符输入流 Reader | 字符输出流 Writer |
字节流
一切皆为字节
一切问价年数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任何文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
字节输出流【OutputStream】
java.io.0utputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。 它定义了字节输出流的基本共性功能方法。
public void close()
: 关闭此输出流并释放与此流相关联的任何系统资源public void flush()
: 刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[]b)
:将b.length字节从指定的字节数组写入此输出流。public void write(byte[]b, int off, intlen)
:从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。public abstract void write(int b)
:将指定的字节输出流
注意:
close方法,当完成流的操作时,必须调用此方法,释放系统资源
FileOutputStream类
OutputStream
有很多子类,我们从最简单的一个子类开始
jiava.io.FileOutputStream
类是文件输出流,用于将数据写出到文件。
构造方法
FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。FileOutputStream(FileDescriptor fdObj)
创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。
写出字节数据
import java.io.FileOutputStream;
import java.io.IOException;
/*
java.io.OutputStream:字节输出流
此抽象类是表示输出字节流的所有类的超类。
定义了一些子类共性的成员方法:
- public void close(`: 关闭此输出流并释放与此流相关联的任何系统资源
- public void flush(): 刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[]b):将b.length字节从指定的字节数组写入此输出流。
- public void write(byte[]b, int off, intlen):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
- public abstract void write(int b) :将指定的字节输出流
java.io.FileOutputStream extends OutputStream
FileOutputStream:文件字节输出流
作用:把内存中的数据写入到硬盘的文件中
构造方法:
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
参数:
String name:目的地是一个文件的路径
File file:目的地是一个文件
构造方法的作用:
1.创建一个FileOutputStream对象
2.会根据构造方法中传递的文件/文件路径,创建一个空的文件
3.会把FileOutputStream对象指向创建好的文件
写入数据的原理(内存-->硬盘)
java程序-->JVM(java虚拟机)-->os(操作系统)-->os调用写数据的方法-->把数据写入到文件中
字节输出流的使用步骤(重点):
1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的
2.调用FileOutputStream对象中的方法write,把数据写入到文件中
3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)
*/
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的
FileOutputStream fos = new FileOutputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\a.txt");
//2.调用FileOutputStream对象中的方法write,把数据写入到文件中
//public abstract void write(int b)
fos.write(97);
//3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)
fos.close();
}
}
文件存储原理
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
/*
一次写多个字节的方法
- public void write(byte[]b):将b.length字节从指定的字节数组写入此输出流。
- public void write(byte[]b, int off, intlen):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
*/
public class Demo02OutputStream {
public static void main(String[] args) throws IOException {
//创建FileOutputStream对象,构造方法中绑定要写入数据的目的地
FileOutputStream fos = new FileOutputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\b.txt");
//调用FileOutputStream对象中的方法write,把数据写入到文件中
//在文件中显示100,写3个字节
fos.write(49);
fos.write(48);
fos.write(48);
/*
public void write(byte[]b):将b.length字节从指定的字节数组写入此输出流
一次写多个字节:
如果写的第一个字节是正数,那么显示的时候会查询ASCII码表
如果写的第一个字节是负数,那么第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表
*/
byte[] bytes = {65,66,67,68,69};//ABCDE
//byte[] bytes = {-65,-66,-67,68,69};//100烤紻E
fos.write(bytes);
/*
public void write(byte[]b, int off, intlen):把字节数组的一部分写到文中
int off:数组的开始索引
int len:写几个字节
*/
fos.write(bytes,1,2);//BC
/*
写入字符串的方法:可以使用String类中的方法,把字符串转换为字节数组
byte[] getBytes() 把字符串转换为字节数组
*/
byte[] bytes2 = "你好".getBytes();
System.out.println(Arrays.toString(bytes2));//[-28, -67, -96, -27, -91, -67]
fos.write(bytes2);
//释放资源
fos.close();
}
}
数据追加续写和换行
import java.io.FileOutputStream;
import java.io.IOException;
/*
追加写/续写:使用两个参数的构造方法
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
参数:
String name,File file:写入数据的目的地
boolean append:追加写开关
true:创建对象不会覆盖原文件,会继续在文件的末尾追加写数据
false:创建一个新文件,覆盖原文件
写换行:写换行符号
windows:\r\n
Linux:/n
mac:/r
*/
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\c.txt",true);
for (int i = 0; i <= 10; i++) {
fos.write("你好".getBytes());
fos.write("\r\n".getBytes());
}
fos.close();
}
}
字节输入流【InputSream】
java.io.InputStream
抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
-
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源 -
public abstract int read()
:从输入流读取数据的下一个字节 -
public int read(byte[] b)
:从输入流中读取一些字节数,并将它们存储到字节数组b中。
注意:
close方法,当完成流的操作时,必须调用此方法,释放系统资源
FileInputStream类
java.io.FileIuputSteam
类是文件输入流,从文件中读取字节。
构造方法
FileInputStream(File file)
: 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。FileInputStream(FileDescriptor fdObj)
:通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。FileInputStream(String name)
:通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
写入字节数据
import java.io.FileInputStream;
import java.io.IOException;
/*
java.io.InputStream:字节输入流
此抽象类是表示字节输入流的所有类的超类。
定义了所有子类共性的方法:
abstract int read() 从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
void close() 关闭此输入流并释放与该流关联的所有系统资源。
java.io.FileInputStream extends InputStream
FileInputStream:文件字节输入流
作用:把硬盘文件中的数据,读取到内存中使用
构造方法:
FileInputStream(String name)
FileInputStream(File file)
参数:读取文件的数据源
String name:文件的路径
File file:文件
构造方法的作用:
1.会创建FileInputStream对象
2.会把FileInputStream对象指定构造方法中要读取的文件
读取数据的原理(硬盘-->内存)
java程序-->JVM-->OS-->OS读取数据的方法-->读取文件
字节输入流的使用步骤(重点):
1.创建FileInputStream对象,构造方法中绑定要读取的数据源
2.使用FileInputStream对象中的方法read,读取文件
3.释放资源
*/
public class Demo01InputStream {
public static void main(String[] args) throws IOException {
//1.创建FileInputStream对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\a.txt");
//2.使用FileInputStream对象中的方法read,读取文件
//int read() 读取文件中的一个字节并返回,读取到文件的末尾返回-1
/*int len = fis.read();
System.out.println(len);//97 a
len = fis.read();
System.out.println(len);//98 b
len = fis.read();
System.out.println(len);//99 c
len = fis.read();
System.out.println(len);//-1*/
/*
发现以上读取文件是一个重复的过程,所以可以使用循环优化
不知道文件有多少个字节使用while循环
while循环结束条件,读取到-1的时候
布尔表达式(len = fis.read())!=-1
1.fis.read():读取一个字节
2.len = fis.read():把读取到的字节赋值给变量len
3.(len = fis.read())!=-1:判断变量len是否不等于-1
*/
int len = 0;//记录读取到的字节
while((len = fis.read())!=-1){
System.out.print((char)len);//abc
}
//3.释放资源
fis.close();
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
/*
字节输入流一次读取多个字节的方法:
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
明确两件事:
1.方法的参数byte[]的作用?
起到缓冲作用,存储每次读取到的多个字节
数组的长度一把定义为1024(1kb)或者1024的整数倍
2.方法的返回值int是什么?
每次读取的有效字节个数
String类的构造方法
String(byte[] bytes):把字节数组转换为字符串
String(byte[] bytes, int offset,int length):把字节数组的一部分转换为字符串
int offset:数组的开始索引
int length:转换的字节个数
*/
public class Demo02InputStream {
public static void main(String[] args) throws IOException {
//创建FileInputStream对象,构造方法中绑定要读取的数据
FileInputStream fis = new FileInputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\b.txt");
//使用FileInputStream对象中的方法read读取文件
//int read(byte[] b) 从输入流中读取一定数量的字节,并且将其存储在缓存区数组b中
/*byte[] bytes = new byte[2];
int len = fis.read(bytes);
System.out.println(len);//2
//System.out.println(Arrays.toString(bytes));//[65, 66]
System.out.println(new String(bytes));//AB
len = fis.read(bytes);
System.out.println(len);//2
System.out.println(new String(bytes));//CD
len = fis.read(bytes);
System.out.println(len);//1
System.out.println(new String(bytes));//ED
len = fis.read(bytes);
System.out.println(len);//-1
System.out.println(new String(bytes));//ED*/
/*
发现以上读取是一个重复的过程,可以使用循环优化
不知道文件中有多少字节,所以使用while循环
while循环结束的条件,读取到-1结束
*/
byte[] bytes = new byte[1024];//存储读取到的多个字节
int len = 0;//记录每次读取的有效字节个数
while((len = fis.read(bytes)) != -1){
//String(byte[] bytes, int offset,int length):把字节数组的一部分转换为字符串
System.out.println(new String(bytes,0,len));
}
//释放资源
fis.close();
}
}
文件读取原理
字节流练习:图片赋值
复制原理图解
代码实现
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
文件复制练习:一读一写
明确:
数据源:c:\\1.jpg
数据的目的地:d:\\1.jpg
文件赋值的步骤:
1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
3.使用字节输入流对象的方法read读取文件
4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
5.释放资源
*/
public class Dome01CopyFile {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("c:\\1.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("d:\\1.png");
//一次读取一个字节写入一个字节的方法
//3.使用字节输入流对象的方法read读取文件
/*int len = 0;
while((len = fis.read()) != -1){
//4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}*/
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes = new byte[1024];
//3.使用字节输入流对象的方法read读取文件
int len = 0;//每次读取的有效字节个数
while((len = fis.read(bytes)) != -1){
//4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(bytes,0,len);
}
//5.释放资源(先关写,后关闭读;如果写完了,肯定读完了)
fos.close();
fis.close();
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时:" + (e-s) + "毫秒");
}
}
字符流
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以java提供一些字符流类,以字符为单位读取数据,专门用于处理文本文件。
字符输入流【Reader】
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。 它定义了字符输入
流的基本共性功能方法
public void close()
:关闭此流并释放与此流相关联的任何系统资源。public int read()
:从输入流读取一个字符public int read(char[] cbuf)
:从输入流中读取一些字符,并将它们存储到字符数组cbuf中
FileReader类
java.io.FileReader
类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区
注意:
字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。
idea中UTF-8
构造方法
FileReader(File file)
: 在给定从中读取数据的 File 的情况下创建一个新 FileReader。FileReader(FileDescriptor fd)
:在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。FileReader(String fileName)
: 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
读取字符数据
import java.io.FileReader;
import java.io.IOException;
/*
java.io.Reader:字符输入流,是字符输入流的最顶层父类,定义了一些共性的成员方法,是一个抽象类
共性的成员方法:
int read() 将字符读入数组
int read(char[] cbuf) 一次读取多个字符,将字符读入数组
void close() 关闭该流并释放与之关联的所有资源
java.io.FileReader extends InputStreamReader extends Reader
FileReader:文件字符输入流
作用:把硬盘文件中的数据以字符的方式读取到内存中
构造方法:
FileReader(String fileName)
FileReader(File file)
参数:读取的数据源
String fileName:文件的路径
File file:一个文件
FileReader构造方法的作用:
1.创建一个FileReader对象
2.会把FileReader对象指向要读取的文件
字符输入流的使用步骤:
1.创建FileReader对象,构造方法中绑定要读取的数据
2.使用FileReader对象中的中文的方法读取read读取文件
3.释放资源
*/
public class Demo01Reader {
public static void main(String[] args) throws IOException {
//1.创建FileReader对象,构造方法中绑定要读取的数据
FileReader fr = new FileReader("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\c.txt");
//2.使用FileReader对象中的中文的方法读取read读取文件
//int read() 将字符读入数组
/*int len = 0;
while((len = fr.read()) != -1){
System.out.print((char)len);
}*/
//int read(char[] cbuf) 一次读取多个字符,将字符读入数组
char[] cs = new char[1024];
int len = 0;//记录每次读取的有效字符的个数
while((len = fr.read(cs)) != -1){
/*
String类的构造方法
String(char[] value) 把字符数组转换为字符串
String(char[] value, int offset, int count) 把部分字符数组转换为字符串
*/
System.out.println(new String(cs,0,len));
}
//3.释放资源
fr.close();
}
}
字符输出流【Write】
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():
关闭此流,但要先刷新它
FileWrite类
java.io.FileWrite
类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法
FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。FileWriter(FileDescriptor fd)
构造与某个文件描述符相关联的 FileWriter 对象。FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
基本写出数据
import java.io.FileWriter;
import java.io.IOException;
/*
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():关闭此流,但要先刷新它
java.io.FileWriter extends OutputStreamWriter extends Writer
FileWriter:文件字符输出流
作用:把内存中字符数据写入到文件中
构造方法:
FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
参数:写入数据的目的地
String fileName:文件的路径
File file:是一个文件
构造方法的作用:
1.会创建一个FileWriter对象
2.会根据构造方法中传递的文件/文件的路径,创建文件
3.会把FileWriter对象指向创建好的文件
字符输出流的重要步骤(重点):
1.创建FileWriter对象,构造方法中绑定要写入的数据的目的地
2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符串转换为字节的过程)
3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
*/
public class Demo01Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\d.txt");
//2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符串转换为字节的过程)
//void write(int c):写入单个字符
fw.write(97);
//3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
//fw.flush();
//4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
fw.close();
}
}
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush
方法了。
flush
:刷新缓冲区,流对象可以继续使用。close
:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了
import java.io.FileWriter;
import java.io.IOException;
/*
flush方法和close方法的区别
- flush:刷新缓冲区,流对象可以继续使用。
- close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了
*/
public class Demo02Writer_CloseAndFlush {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\d.txt");
//2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符串转换为字节的过程)
//void write(int c):写入单个字符
fw.write(97);
//3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
fw.flush();
//刷新之后流可以继续使用
fw.write(98);
//4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
fw.close();
//close方法之后流已经关闭了,已经从内存中消失了,流就不能再使用了
fw.write(99);//IOException: Stream closed
}
}
写出其他数据
import java.io.FileWriter;
import java.io.IOException;
/*
字符输出流写数据的其他方法
- 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写的字符个数。
*/
public class Demo03Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\f.txt");
char[] cs = {'a','b','c','d','e'};
//void write(char[] cbuf):写入字符数组
fw.write(cs);//abcde
//abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
fw.write(cs,1,3);//bcd
//void write(String str):写入字符串
fw.write("黑美人");
//oid write(String str, int off,int len)写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
fw.write("黑美人花都仔",3,3);
fw.close();
}
}
续写和换行
import java.io.FileWriter;
import java.io.IOException;
/*
续写和换行
续写,追加写:使用两个参数的构造方法
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。
参数:
String fileName,File file:写入数据的目的地
boolean append:续写开关
true:不会创建新的文件覆盖源文件,可以续写
false:创建新的文件覆盖源文件
换行:
windows:\r\n
Linux:/n
mac:/r
*/
public class Demo04Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\g.txt",true);
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
fw.close();
}
}
IO异常的处理
JDK7前处理
import java.io.FileWriter;
import java.io.IOException;
/*
在JDK1.7之前使用try catch finally 处理流中的异常
格式:
try{
可能会产生异常的代码
]catch(异常类变量 变量名){
异常的处理逻辑
}finally{
一定会执行的代码
资源释放
}
*/
public class Demo01TryCatch {
public static void main(String[] args){
//提高变量fw的作用域,让finally可以使用
//变量在定义的时候可以没有值,但是使用的时候必须有值
//fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\g.txt",true);执行失败,fw没有值,fw.close会报错
FileWriter fw = null;
try{
fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\g.txt",true);
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
}catch (IOException e){
//异常的处理逻辑
System.out.println(e);
}finally {
//一定会执行的代码
//创建对象失败了,fw的默认值就是null,null是不能调用方法的,会抛出NullPointerException,需要增加一个判断,不是null再把资源释放了
if (fw != null) {
try {
//fw.close方法声明抛出IOException异常对象,所以我们旧的处理这个异常要么throws,要么try catch
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
JDK7的处理(了解)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
JDK7的新特性
在try的后边可以增加一个(),在括号中可以定义流对象
那么这个流对象的作用域就在try中有效
try中的代码执行完毕,会自动把流对象释放,不用谢finally
格式:
try(定义流对象;定义流对象...){
可能会产生异常的代码
]catch(异常类变量 变量名){
异常的处理逻辑
}
*/
public class Demo02TryCatch_JDK7 {
public static void main(String[] args) {
try(//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("d:\\1.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("f:\\1.png")){
//可能会产生异常的代码
//一次读取一个字节写入一个字节的方法
//3.使用字节输入流对象的方法read读取文件
int len = 0;
while((len = fis.read()) != -1){
//4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}
}catch(IOException e){
//异常的处理逻辑s
System.out.println(e);
}
}
}
JDK9的改进(了解)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
JDK9的新特性:
try的前边可以定义流对象
在try后边的()中可以直接引入流对象的名称(变量名)
在try代码执行完毕之后,流对象也可以释放掉,不用写finally
格式:
A a = new A();
B b = new B();
try(a,b){
可能会产生异常的代码
]catch(异常类变量 变量名){
异常的处理逻辑
}
*/
public class Demo03TryCatch_JDK9 {
public static void main(String[] args) throws IOException {
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("d:\\1.png");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("f:\\1.png")
try(fis;fos){
//可能会产生异常的代码
//一次读取一个字节写入一个字节的方法
//3.使用字节输入流对象的方法read读取文件
int len = 0;
while((len = fis.read()) != -1){
//4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}
}catch(IOException e){
//异常的处理逻辑s
System.out.println(e);
}
//fos.write(1);//Stream Closed
}
}
属性集
概述
java.util.Properties
继承Hashtable
,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多java类使用,比如获取系统属性时,System.getProperties
方法就是返回一个Properties
对象。
Properties类
构造方法
public Properties()
:创建一个空的属性列表
基本的存储方法
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。void store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。void store(Writer writer, String comments)
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。Object setProperty(String key, String value)
调用 Hashtable 的方法 put。String getProperty(String key)
通过key找到value值,此方法相当于Map集合中的get(key)方法Set<String> stringPropertyNames()
返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
import java.io.*;
import java.util.Properties;
import java.util.Set;
/*
java.util.Properties集合 extends Hashtable<K,V> implements Map<K,V>
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
Properties集合是一个唯一和IO流相结合的集合
可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘存储
可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
属性列表中每个键及其对应值都是一个字符串
Properties集合是一个双列集合,key和value默认都是字符串
*/
public class Demo01Properties {
public static void main(String[] args) throws IOException {
show03();
}
/*
可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
void load(InputStream inStream)
void load(Reader reader)
参数:
InputStream inStream:字节输入流,不能读取含有中文的键值对
Reader reader:字符输入流,能读取含有中文的键值对
使用步骤:
1.创建Properties集合对象
2.使用Properties集合对象的方法load读取保存键值对的文件
3.遍历Properties集合
注意:
1.存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
3.存储键值对的文件中,键与值默认都是字符串,不能再加引号
*/
private static void show03() throws IOException {
//1.创建Properties集合对象
Properties prop = new Properties();
//2.使用Properties集合对象的方法load读取保存键值对的文件
prop.load(new FileReader("D:\\\\IDEA2019(中文版)\\\\ZXL\\\\src\\\\com\\\\company\\\\pratise\\\\IOAndProperties\\\\prop.txt"));
//prop.load(new FileInputStream("D:\\\\IDEA2019(中文版)\\\\ZXL\\\\src\\\\com\\\\company\\\\pratise\\\\IOAndProperties\\\\prop.txt"));
//3.遍历Properties集合
Set<String> set = prop.stringPropertyNames();
for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key + "=" + value);
}
}
/*
可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘存储
void store(OutputStream out, String comments)
void store(Writer writer, String comments)
参数:
OutputStream out:字节输出流,不能写入中文
Writer writer:字符输出流,可以写入中文
String comments:注释,用来解释说明保存的文件是做什么用的?
不能使用中文,会产生乱码。默认是Unicode编码
一般使用""空字符串
使用步骤:
1.创建Properties集合对象,添加数据
2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘存储
4.释放资源
*/
private static void show02() throws IOException {
//1.创建Properties集合对象,添加数据
Properties prop = new Properties();
prop.setProperty("赵丽颖","168");
prop.setProperty("迪丽热巴","165");
prop.setProperty("古力娜扎","160");
//2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
//FileWriter fw = new FileWriter("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\prop.txt");
//3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘存储
//prop.store(fw,"save data");
//4.释放资源
//fw.close();
prop.store(new FileOutputStream("D:\\IDEA2019(中文版)\\ZXL\\src\\com\\company\\pratise\\IOAndProperties\\prop2.txt"),"save data");
}
/*
使用Properties集合存储数据,遍历取出Properties集合中的数据
Properties集合是一个双列集合,key和value默认都是字符串
Properties集合有一些操作字符串的特有方法
Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
String getProperty(String key) 通过key找到value值,此方法相当于Map集合中的get(key)方法
Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法
*/
private static void show01() {
//创建Properties集合对象
Properties prop = new Properties();
//使用setProperty网集合中添加数据
prop.setProperty("赵丽颖","168");
prop.setProperty("迪丽热巴","165");
prop.setProperty("古力娜扎","160");
//prop.put(1,true);
//使用stringPropertyNames把Properties集合中的键取出,存储到一个Set集合中
Set<String> set = prop.stringPropertyNames();
//遍历Set集合,取出Properties集合的每一个键
for (String key : set) {
//使用getProperty方法通过key获取value
String value = prop.getProperty(key);
System.out.println(key + "=" + value);
}
}
}