java.io.OutputStream:此抽象类是表示输出字节流的所有类的超类
定义了一些子类共性的成员方法:
void close() 关闭此输出流并释放与此流有关的所有系统资源。
void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b) 将指定的字节写入此输出流。
FilterOutputStream extends OutputStream
FilterOutputStream:文件字节输出流
作用:把内存中的数据写入到硬盘的文件中
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
参数: String name:目的地是一个文件的路径
File file: 目的地是一个文件
构造方法的作用:
1.创建一个FileOutput对象
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("Day16-code\\a.txt");
// 2.调用FileOutputStream对象中的方法write,把数据写入到文件中
// void write(int b) 将指定字节写入此文件输出流。
fos.write(97);
// 3.释放资源(流使用会占用一定内存,使用完毕要把内存清空,提高程序效率)
fos.close();
}
}
一次写多个字节的方法:
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
public class Demo02OutputStream {
public static void main(String[] args) throws IOException {
// 1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
FileOutputStream fos = new FileOutputStream("Day16-code\\b.txt");
// 2.调用FileOutputStream对象中的方法write,把数据写入到文件中
// 在文件中显示100
/* fos.write(49);
fos.write(48);
fos.write(48);*/
/*
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
一次写多个字节:如果写的第一个字节是正数,那么显示的时候会查询ASCII表
:如果写的第一个字节是负数,那么第一个字节和第二个字节组成一个中文显示,
查询系统默认码表(GBK)
*/
byte[] bytes = {65,66,67,68,69};//ABCDE
// byte[] bytes = {-65,-66,-67,-68,69};//烤郊E
fos.write(bytes);
/*
void write(byte[] b, int off, int len) 把字节数组的一部分写入到文件中
int off:数组的开始索引
int len : 写几个字节
*/
fos.write(bytes,1,2);//BC
/*
写入字符的方法:可以使用String类中方法,把字符串,转换为字节数组
byte[] getBytes() 把字符串转换为字节数组
*/
byte[] bytes1 = "你好".getBytes();
System.out.println(Arrays.toString(bytes1));//[-28, -67, -96, -27, -91, -67]
fos.write(bytes1);
//释放资源
fos.close();
}
}
追加/续写:使用两个参数的构造方法:
FileOutputStream(String name, boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流。
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
参数:
String name,File file :写入数据的目的地
boolean append:追加开关,创建对象不会覆盖原文件,继续在末尾追加写数据。
false:创建一个新文件,覆盖源文件。
写换行:写换行符号
windows:\r \n
Linux: /n
mac : /r
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("Day16-code\\c.txt",true);
for (int i = 0; i < 10; i++) {
fos.write("你好".getBytes());
fos.write("\n".getBytes());
}
fos.close();
}
}
InputStream类和FileInputStream类
java.io.InputStream此抽象类是表示字节输入流的所有类的超类。
abstract int read()从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
void close() 关闭此输入流并释放与该流关联的所有系统资源。
java.io.FileInputStream extends InputStream
FileInputStream:文件字节输入流
作用:把硬盘中的数据,读取到内存当中
构造方法:
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 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("Day16-code\\b.txt");
//2.使用FileInputStream对象中的方法read,读取文件
/* int read = fis.read();
System.out.println(read);//65 A
int read1 = fis.read();
System.out.println(read1);//66 B 如果读到最后没有值会显示-1*/
/*
读取文件是一个重复的过程,可以使用循环 ,不知道次数,使用while循环,读到-1结束
布尔表达式(len = fis.read()) != -1
1.fis.read()读取一个字节
2.把读取到的字节赋值给len
3.判断len是否等于-1
*/
//【重点】用一个变量来接收值然后遍历
int len = 0;//记录读取到的字节
while((len = fis.read()) != -1){//读完后指针后移
System.out.println(len);//65 66 67
//System.out.println((char)len);//ABC
}
// 3.释放资源
fis.close();
}
}
字节输入流一次读取多个字节的方法:
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
明确两件事情:
1.方法的参数byte[]的作用?
起到缓冲的作用,存储每次读到的多个字节
数组的长度一般定义为1024(1kb)或者是1024的整数倍
2.方法的返回值int是什么?
每次读取的字节数
String类的构造方法:
String(byte[] bytes):把字节数组转换为字符串
String(byte[] bytes,int offset,int length)把字节数组的一部分转换为字符串
offset数组的开始索引。length转换的字节个数
public class Demo02InputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Day16-code\\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]
// String类的构造方法:String(byte[] bytes):把字节数组转换为字符串
System.out.println(new String(bytes));//AB
len = fis.read(bytes);
System.out.println(len);//2 每次读取的字节个数
// String类的构造方法:String(byte[] bytes):把字节数组转换为字符串
System.out.println(new String(bytes));//CD
len = fis.read(bytes);
System.out.println(len);//2 每次读取的字节个数
// String类的构造方法:String(byte[] bytes):把字节数组转换为字符串
System.out.println(new String(bytes));// -1 CD*/
/*
使用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();
}
}
/*
文件复制练习:一读一写
明确:数据源:
数据的目的地:
文件复制的步骤:
1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
3.使用字节输入流的read读取文件
4.使用字节输出流的write,把读取到的字节写入到目的地文件中
5.释放资源
*/
public class Demo03Practice {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("Day16-code\\b.txt");
// 2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("f:\\b.txt");
//一次读取/写入一个字节
//3.使用字节输入流的read读取文件
/* int len = 0 ;
while ((len = fis.read()) != -1){
//4.使用字节输出流的write,把读取到的字节写入到目的地文件中
fos.write(len);
}*/
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read())!= -1){//len 每次读取的有效字节个数
fos.write(bytes,0,len);
}
//5.释放资源(先关闭写的,后关闭读的,如果写完了,肯定读完了)
fos.close();
fis.close();
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时"+ (e - s )+"毫秒");
}
}
/*
使用字节流读取中文文件
1个中文
GBK:占用两个字节
UTF-8:占用三个字节
*/
public class Demo04InputStream {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Day16-code\\c.txt");
int len = 0;
while ((len = fis.read()) != -1){//一次读入一个数据,相当于一次读三分之一个中文,会乱码
System.out.println(len);
}
fis.close();
}
}
java.io.Reader:字符输入流,是字符输入流最顶层的父类,定义了一些共性的成员方法,是一个抽象类
共性的成员方法:
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
abstract void close() 关闭该流并释放与之关联的所有资源。
java.io.FileReader extends InputStreamReader extends Reader
FileReader:文件字符输入流
作用:把硬盘文件中的数据以字符的方式读取到内存当中。
构造方法:
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName)在给定从中读取数据的文件名的情况下创建一个新 FileReader。
参数:读取文件的数据源
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("Day16-code\\c.txt");
//2.使用FileReader对象中的方法read读取文件 (读取单个)
/* int len = 0;
while ((len = fr.read())!= -1){
System.out.print((char)len);//你好abc
}*/
/*
String类的构造方法:
String(char[] value) :把字符数组转换为字符串
String(char[] value, int offset, int count) :把字符数组的一部分转化为字符串
offset 开始索引 count 个数
*/
//一次读取多个字符
char[] chars = new char[1024];
int len = 0;//记录的是每次读取有效数据的个数
while ((len = fr.read(chars))!= -1){
System.out.println(new String(chars,0,len));
}
// 3.释放资源
fr.close();
}
}
java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类
共性的成员方法:
abstract void close()
关闭此流,但要先刷新它。
abstract void flush()
刷新该流的缓冲。
void write(char[] cbuf)
写入字符数组。
abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
void write(int c)
写入单个字符。
void write(String str)
写入字符串。
void write(String str, int off, int len)
写入字符串的某一部分。
java.io.FileWriter extends OutputStreamWriter extends Writer
FileWriter:文件输出流
作用:把内存中的字符数据写入到文件中
构造方法:
FileWriter(String fileName) :根据给定的文件名构造一个 FileWriter 对象。
FileWriter(File file): 根据给定的 File 对象构造一个 FileWriter 对象。
参数:写入数据的目的地
String fileName 文件的路径
File file:是一个文件
构造方法的作用:
1.创建FileWriter对象
2.会根据构造方法中传递的文件/文件路径,创建文件
3.会把FileWriter对象指向创建好的文件。
字符输出流的使用步骤:
1.创建FileWriter对象,构造方法中绑定要写入的数据的目的地
2.使用FileWriter对象中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
4.释放资源(会先把内存缓冲区中的数据,刷新到文件中)
public class Demo02Writer {
public static void main(String[] args) throws IOException {
// 1.创建FileWriter对象,构造方法中绑定要写入的数据的目的地
FileWriter fw = new FileWriter("Day16-code\\d.txt");
//2.使用FileWriter对象中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
fw.write(97);
// 3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
fw.flush();
// 4.释放资源(会先把内存缓冲区中的数据,刷新到文件中)
fw.close();
}
}
flush: 刷新缓冲区,流对象可以继续使用
close: 先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了
/*
字符输出流写数据的其他方法:
void write(int c) 写入单个字符。
void write(char[] cbuf, int off ,int len) 写入字符数组的某一部分
void write(String str)写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分。
*/
public class Demo03Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("Day16-code\\f.txt");
//写入字符数组
char[] cs = {'a','b','c','d','e'};
fw.write(cs);
fw.write(cs,1,3);//cbd
fw.write("cccccc");
fw.write("程序员",1,2);//序员
fw.close();
}
}
/*
续写和换行
FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。
boolean append :续写开关 true:不会创建新文件覆盖原文件,可以续写
false:创建新的文件覆盖原文件
*/
public class Demo04Writer {
public static void main(String[] args) throws IOException {
FileWriter fw= new FileWriter("Day16-code\\f.txt",true);
for (int i = 0; i < 6; i++) {
fw.write("Hello"+"\r");
}
fw.close();
}
}
/*
在jdk1.7之前,使用trycatch finally处理流中的异常
格式:
try{
可能会产生异常的代码
}catch(异常变量 变量名){
异常的处理逻辑
}finally{
一定会执行的代码
资源释放
}
*/
public class Demo01TryCatch {
public static void main(String[] args) {
//提高变量fw的作用域
//变量在定义的时候可以没有值,使用的时候必须有值
//fw= new FileWriter("Day16-code\\f.txt",true);执行失败 fw就没有值了
FileWriter fw = null;
try{
//可能会出现异常的代码
fw= new FileWriter("Day16-code\\f.txt",true);
for (int i = 0; i < 6; i++) {
fw.write("Hello"+"\r");
}
}catch (IOException e){
System.out.println(e);
}finally {
//创建对象失败了,fw的默认值就是null,null是不能调用方法的,会抛出空指针异常,
// 需要增加一个判断,不是null再吧资源释放
//资源释放
try {
//fw.close方法声明抛出了IOException,所以我们就得处理这个异常对象
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
JDK7
/*
JDK7的新特性:
在try的后边可以增加一个(),在括号中可以定义流对象
那么这个流对象的作用域就在try中有效
try中的代码执行完毕,会自动吧流对象释放,不用写finally
格式:
try(定义流对象;....){
可能会产生异常的代码
}catch(异常变量 变量名){
异常的处理逻辑
*/
public class Demo02JDK7 {
public static void main(String[] args) {
try (
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("Day16-code\\b.txt");
// 2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("f:\\b.txt");
){
//一次读取/写入一个字节,可能会出现异常的代码
//3.使用字节输入流的read读取文件
int len = 0;
while((len =fis.read()) !=-1){
//4.使用字节输出流的write,把读取到的字节写入到目的地文件中
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
}
}
JDK9
/*
JDK9新特性
try的前边可以定义流对象
在try后边的()中可以直接引入流对象的名称(变量名)
在try代码执行完毕之后流对象也可以释放,不用写finally
格式:
A a = new A();
B a = new B();
try(a;b){
可能会产生异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}
*/
public class Demo03JDK9 {
public static void main(String[] args) throws IOException {
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("Day16-code\\b.txt");
// 2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("f:\\b.txt");
try (fis;fos){
//一次读取/写入一个字节,可能会出现异常的代码
//3.使用字节输入流的read读取文件
int len = 0;
while((len =fis.read()) !=-1){
//4.使用字节输出流的write,把读取到的字节写入到目的地文件中
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
//fos.write(1);//Stream Closed 不能再写入了
}
}
/*
Properties extends Hashtable implements Map
表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
Properties集合是唯一一个与IO流相结合的集合
可以使用properties集合中的方法,把集合中的临时数据,持久化写入到硬盘中存储
可以使用Properties集合中的方法load,吧硬盘中保存的文件(键值对),读取到集合使用
属性列表中每个键及其对应值都是一个字符串。
properties集合是一个双列集合,key和value默认都是字符串
*/
public class Demo01Properties {
public static void main(String[] args) {
show01();
}
/*
使用Properties集合存储数据,遍历取出集合中的数据
Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
String getProperty(String key) 通过key找到value值,相当于Map集合中的get(key)
Set stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串, 此方法相当于Map集合中的keySet方法
*/
private static void show01() {
Properties prop = new Properties();
prop.setProperty("赵丽颖","168");
prop.setProperty("迪丽热巴","165");
prop.setProperty("迪丽","160");
// Set stringPropertyNames()把集合中的键取出
Set<String> set = prop.stringPropertyNames();
//遍历set集合,取出Properties集合中的每个键
for (String key: set
) {
String value = prop.getProperty(key);
System.out.println(key +"="+ value);
}
}
}
public class Demo01Properties {
public static void main(String[] args) throws IOException {
show02();
}
/*
可以使用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("Day16-code\\prop.txt");
//3.使用Properties集合中的方法store,把集合中的临时数据持久化写入到硬盘中存储
// prop.store(fw,"save data");
//4.释放资源
//fw.close();
//字节流/乱码,因为字节流不能写中文
prop.store(new FileOutputStream("Day16-code\\prop2.txt")," ");
}
}
/*
可以使用Properties集合中的方法load,吧硬盘中保存的文件(键值对),读取到集合使用
void load(InputStream inStream)
void load(reader reader)
参数:
InputStream:字节输入流
reader:字符输入流含中文
使用步骤:
1.创建Properties集合对象
2.使用Properties集合对象中的方法load读取保存键值对的文件
3.遍历Properties集合
注意:
1.存储键值对的文件中,键与值默认的链接符号可以使用=,空格(其他符号)
2.存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
3.存储键值对的文件中,键与值默认都是字符串,不用再加引号。
*/
public class Demo02Load {
public static void main(String[] args) throws IOException {
// 1.创建Properties集合对象
Properties prop = new Properties();
// 2.使用Properties集合对象中的方法load读取保存键值对的文件
prop.load(new FileReader("Day16-code\\prop.txt"));
//字节流 因为包含中文,所以会乱码
// prop.load(new FileInputStream("Day16-code\\prop.txt"));
//3.遍历Properties集合
Set<String> set = prop.stringPropertyNames();
for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key+"="+value);
}
}
}