第一章 IO概念
1.1 什么是IO
- Java中I/O操作主要是指使用java.io包下的内容,进行输入,输出操作。
- 输入也叫做:读取数据
- 输出也叫做:写入数据
- 内存(RAM),硬盘(ROM)
1.2 IO的分类
1.3 IO的流向说明图解
- 根据数据的流向分为:
- 输入流
- 输出流
- 根据数据的类型分为:
- 字节流
- 字符流
1.4 顶级父类们
1.5 总结
- I/O流介绍:
- I:input 输入(读取)
- 输入:把硬盘中的数据,读取到内存中使用
- O:output 输出(写入)
- 输出:把内存中的数据,写入到硬盘中保存
- 流:数据(字符,字节)
- 1个字符 = 2个字节
- 1个字节 = 8个二进制
- 因为流中数据分为(字符,字节)所以有:
- 字节输入流
- 字节输出流
- 字符输入流
- 字符输出流
第二章 字节流
2.1 一切皆为字节
2.2 字节输出流_OutputStream类&FileOutputStream类介绍
- java.io.OutputStream:字节输出流
- 此抽象类是表示输出字节流的所有类的超类。
- 定义了一些子类共性的成员方法:
- public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
- public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
- public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
- public abstract void write(int b) :将指定的字节输出流。(1字节)
- java.io.FileOutputStream extends OutputStream
- FileOutputStream:文件字节输出流
- 作用:把内存中的数据写入到硬盘的文件中
- 构造方法:
- FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。
- FileOutputStream(File file) :创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
- 参数:写入数据的目的
- String name:目的地是一个文件的路径
- File file:目的地是一个文件
- 构造方法的作用:
- 创建一个FileOutputStream对象
- 会根据构造方法中传递的文件/文件路径,创建一个空的文件
- 会把FileOutputStream对象指向创建好的文件
2.3 字节输出流写入数据到文件
- 写入数据的原理(内存–>硬盘)
- java程序–>JVM(java虚拟机)–>OS(操作系统)–>OS调用写数据的方法–>把数据写入到文件中
- 字节输出流的使用步骤【重点】:
- 创建一个FileOutputStream对象,构造方法中传递写入数据的目的地(创建一个空的文件)
- 调用FileOutputStream对象中的方法write,把数据写入到文件中
- 释放资源[close方法](流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
- 三个步骤都会报出异常解决如下:
- 创建FileOutputStream对象会抛出–>io.FileNotFoundException
- write和close方法会抛出–>io.IOException
- 因为FileNotFoundException是IOException的子类
- 所以直接抛出IOException异常即可。(throws IOException)
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
//1. ==创建==一个==FileOutputStream对象==,==构造方法中==传递==写入数据的目的地==(创建一个空的文件)
//写入到day09路径下
FileOutputStream fos = new FileOutputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\a.txt");
//2. ==调用==FileOutputStream对象中的==方法write==,==把数据写入到文件中==
//* public abstract void ==write==(int b) :将指定的字节输出流。
fos.write(97);
//3. ==释放资源==(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
fos.close();
}
}
2.4 文件存储的原理和记事本打开文件的原理
2.5 字节输出流写多个字节的方法
- public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
- 一次写多个字节:
- 如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
- 如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)
- public void write(byte[] b, int off, int len) :把字节数组的一部分写入到文件中
- int off:数组的开始索引
- int len:写几个字节
- 写入字符的方法:可以使用String类中的方法把字符串,转换为字节数组
- byte[] getBytes() 把字符串转换为字节数组
- 注:UTF-8中3个字节为一个中文,GBK是两个字节【重点】
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class Demo02OutputStream {
public static void main(String[] args) throws IOException {
//创建FileOutputStream对象,构造方法中绑定要写入数据的目的地
FileOutputStream fos = new FileOutputStream(new File("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\b.txt"));
//调用FileOutputStream对象中的方法write,把数据写入到文件中
//在文件中显示100,写几个字节(3个)
fos.write(49);
fos.write(48);
fos.write(48);
//public void write(byte[] b)
//如果写的==第一个字节是正数==(0-127),==那么显示的时候会查询ASCII表==
byte[] bytes = {65, 66, 67, 68, 69}; //ABCDE
//如果写的==第一个字节是负数==,那==第一个字节会和第二个字节,两个字节组成一个中文显示==,查询系统默认码表(GBK)
//byte[] bytes = {-65, -66, -67, 68, 69}; //烤紻E
//fos.write(bytes);
/*
public void write(byte[] b, int off, int len) :把字节数组的一部分写入到文件中
* int off:==数组的开始索引==
* int len:==写几个字节==
*/
fos.write(bytes, 1, 2); //BC
//byte[] ==getBytes==()
byte[] bytes1 = "你好".getBytes();
System.out.println(Arrays.toString(bytes1)); //[-28, -67, -96, -27, -91, -67]
fos.write(bytes1); //你好
//释放资源
fos.close();
}
}
2.6 字节输出流的续写和换行(前面的方式再次运行会覆盖)
- 追加写/续写【重点】:使用两个参数的构造方法
- FileOutputStream(String name, boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流。
- FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
- 参数:
- String name,File file:写入数据的目的地
- boolean append:追加写开关
- true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据
- false:创建一个新文件,覆盖源文件
- 写换行:写换行符号【重点】(这个也是属于字符串:getBytes()来转为字节数组)
- windows:\r\n
- 一起写分开写都可以
- linux:/n
- mac:/r
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\c.txt", true);
for(int i = 0; i <= 2; i++){
fos.write("你好".getBytes());
fos.write("\r\n".getBytes());
}
fos.close();
}
}
//结果:
你好
你好
你好
2.7 字节输入流_InputStream类&FileInputStream类介绍
- java.io.InputStream:字节输入流
- 此抽象类是表示字节输入流的所有类的超类。
- 定义了所有子类共性的方法:
- int read():从输入流中读取数据的下一个字节。
- 读取文件中的一个字节并返回,读取到文件的末尾返回-1
- 每次读取一个字节指针向后移一位
- int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
- void close():关闭此输入流并释放与该流关联的所有系统资源
- java.io.FileInputStream extends InputStream
- FileInputStream:文件字节输入流
- 作用:把硬盘文件中的数据,读取到内存中使用
- 构造方法:
- FileInputStream(String name)
- FileInputStream(File file)
- 参数:读取文件的数据源
- String name:文件的路径
- File file:文件
- 构造方法的作用:
- 会创建一个FileInputStream对象
- 会把FileInputStream对象指向构造方法中要读取的文件
2.8 字节输入流读取字节数据
- 读取数据的原理(硬盘–>内存)
- java程序–>JVM–>OS–>OS读取数据的方法–>读取文件
- 字节输入流的使用步骤【重点】
- 创建FileInputStream对象,构造方法中绑定要读取的数据源
- 使用FileInputStream对象中的方法read,读取文件
- 释放资源
- 优化:while循环【重点】
- 读取文件是一个重复的过程,所以可以使用循环优化
- 不知道文件多少个字节,使用while循环
- while结束条件->读取到-1时候
- 格式:(固定)
int len = 0; //记录读取到的字符
while((len = fis.read())!=-1){
System.out.print((char)len); //ASCLL码转换为char类型
}
- 布尔表达式(len = fis.read())!=-1
- fis.read():读取一个字节
- len = fis.read():把读取到的字节赋值给变量len
- (len = fis.read())!=-1:判断变量len是否不等于-1
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\a.txt");
/*int read = fis.read();
System.out.println(read); //97 a
read = fis.read();
System.out.println(read); //98 b
read = fis.read();
System.out.println(read); //99 c
read = fis.read();
System.out.println(read); //-1*/
//使用循环
int len = 0;
while((len = fis.read()) != -1){
System.out.print((char)len); //abc
}
fis.close();
}
2.9 字节输入流一次读取一个字节的原理
2.10 字节输入流一次读取多个字节
- 字节输入流一次读取多个字节的方法:
- int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
- 明确两件事情:
- 方法的参数byte[]的作用?
- 起到缓冲作用,存储每次读取到的多个字节
- 数组的长度一把定义为1024(1kb)或者1024的整数倍【!】
- 方法的返回值int是什么?
- 每次读取的有效字节个数
- String类的构造方法——一次读取多个字节时使用
- String(byte[] bytes) :把字节数组转换为字符串
- String(byte[] bytes, int offset, int length):把字节数组的一部分转换为字符串
- offset:数组的开始索引
- length:转换的字节个数
byte[] bytes = new byte[1024];
int len = 0;
while((len = fr.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len));
}
- 原理
- 优化:while循环【重点】
- 注:int len = 0; //记录每次读取的有效字节个数
- 注:这里不能用上面的new String(bytes)
- 因为这里的长度是1024会有很多空格
- 要用String(byte[] bytes, int offset, int length)
- offset–>从哪里开始
- length–>有效个数(就是len)
import java.io.FileInputStream;
import java.io.IOException;
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\b.txt");
/*byte[] bytes = new byte[2];
int len = fis.read(bytes);
System.out.println(len); //2
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
byte[] bytes = new byte[1024];
int len = 0; //记录每次读取的有效字节个数
while((len = fis.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len)); //len就是他的有效字节个数
}
fis.close();
}
//结果:
ABCDE
2.11 练习_文件复制
- 原理
- 文件复制练习:一读一写
- 明确:
- 数据源: F:\picture\1.jpg
- 数据的目的地: E:\picture\1.jpg
- 文件复制的步骤:
- 创建一个字节输入流对象,构造方法中绑定要读取的数据源
- 创建一个字节输出流对象,构造方法中绑定要写入的目的地
- 使用字节输入流对象中的方法read读取文件
- 使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
- 释放资源
- 注:先关写入的(如果写入完了,读取肯定完了)
- 读写方式:
- 读取一个字节写入一个字节的方式(一)
int len = 0; //记录每次读取的有效字节个数
while((len = fis.read()) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}
- 使用数组缓冲读取多个字节,写入多个字节(二,常用)
byte[] bytes = new byte[1024];
int len = 0; //每次读取的有效字节个数
while((len = fis.read(bytes)) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(bytes, 0, len); //从几开始,到多少的有效个数
}
- 注:只要是文件都可以复制
public static void main(String[] args) throws IOException {
//1. 创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("F:\\picture\\1.jpg");
//创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("E:\\picture\\1.jpg");
///使用字节输入流对象中的方法read读取文件
/*//读取一个字节写入一个字节的方式(一)
int len = 0;
while((len = fis.read()) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}*/
//使用数组缓冲读取多个字节,写入多个字节(二)
byte[] bytes = new byte[1024];
int len = 0; //每次读取的有效字节个数
while((len = fis.read(bytes)) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(bytes, 0, len); //从几开始,到多少的有效个数
}
//释放资源(先关写入的)
fos.close();
fis.close();
}
2.12 使用字节流读取中文的问题
- 使用字节流读取中文文件
- 1个中文
- GBK:占用两个字节
- UTF-8:占用3个字节
- “你好”出来的是6个数字,一旦转成char就会乱码
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\c.txt");
int len = 0;
while((len = fis.read()) != -1){
System.out.println((char)len);
}
fis.close();
}
//结果:
ä
½
å
¥
½
- 一次读取的就是三分之一的字节
- 解决方法:
使用第三章的字符流–>一次读取一个字符
第三章 字符流
3.1 字符输入流_Reader类&FileReader类介绍
- java.io.Reader:字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类
- 共性的成员方法:
- int read():读取单个字符并返回。
- int read(char[] cbuf):一次读取多个字符,将字符读入数组。
- 例:char[] chars = new char[1024];
- void close():关闭该流并释放与之关联的所有资源。
- java.io.FileReader extends InputStreamReader extends Reader(多继承)
- FileReader:文件字符输入流
- 作用:把硬盘文件中的数据以字符的方式读取到内存中
- 构造方法:
- FileReader(String fileName)
- FileReader(File file)
- 参数:读取文件的数据源
- String fileName:文件的路径
- File file:一个文件
- FileReader构造方法的作用:
- 创建一个FileReader对象
- 会把FileReader对象指向要读取的文件
3.2 字符输入流读取字符数据(使用方式一样)
- 字符输入流的使用步骤【重点】:
- 创建FileReader对象,构造方法中绑定要读取的数据源
- 使用FileReader对象中的方法read读取文件
- 释放资源
- 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));
}
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\c.txt");
//int ==read==():读取单个字符并返回。
/*int len = 0;
while((len = fr.read()) != -1){
System.out.print((char)len);
}*/
//int ==read==(==char[] cbuf==):一次读取多个字符,将字符读入数组。
char[] chars = new char[1024]; //存储读取到的多个字符
int len = 0; //记录的是每次读取的有效字符个数
while((len = fr.read(chars)) != -1){
System.out.println(new String(chars, 0, len));
}
fr.close();
}
//结果:
你好abc123
3.3 字符输出流_Writer类&FileWriter类介绍
- 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:是一个文件
- 构造方法的作用:
- 会创建一个FileWriter对象
- 会根据构造方法中传递的文件/文件的路径,创建文件
- 会把FileWriter对象指向创建好的文件
3.4 字符输出流的基本使用_写出单个字符到文件
- 字符输出流的使用步骤(重点):
- 创建FileWriter对象,构造方法中绑定要写入数据的目的地
- 使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
- 使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
- 释放资源(会先把内存缓冲区中的数据刷新到文件中【flush可以不用写】)
- 字节流和字符流的区别
- 字节:写入到文件中
- 字符:写入到内存缓存区中
public static void main(String[] args) throws IOException {
//1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地
FileWriter fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\d.txt");
//2. 使用FileWriter中的方法==write==,把==数据写入到内存缓冲区中==(字符转换为字节的过程)
//写入单个字符方式
fw.write(97);
//3. 使用FileWriter中的方法==flush==,==把内存缓冲区中的数据,刷新到文件中==
//fw.flush();
//4. 释放资源(==会先把内存缓冲区中的数据刷新到文件中【flush可以不用写】==)
fw.close();
}
3.5 flush方法和close方法的区别
- flush方法和close方法的区别
- flush :刷新缓冲区,流对象可以继续使用。
- close: 先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
public static void main(String[] args) throws IOException {
//1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地
FileWriter fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\e.txt");
//2. 使用FileWriter中的方法==write==,把==数据写入到内存缓冲区中==(字符转换为字节的过程)
//写入单个字符方式
fw.write(97);
//3. 使用FileWriter中的方法==flush==,==把内存缓冲区中的数据,刷新到文件中==
fw.flush();
//刷新之后,流可以继续使用
fw.write(98);
//4. 释放资源(==会先把内存缓冲区中的数据刷新到文件中【flush可以不用写】==)
fw.close();
//close方法之后流已经关闭了,已经从内存中消失了,流就不能再使用了
fw.write(99); //IOException: Stream closed
}
3.6 字符输出流写数据的其他方法
- 字符输出流写数据的其他方法
- 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 static void main(String[] args) throws IOException {
//1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地
FileWriter fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\f.txt");
char[] cs = {'a', 'b', 'c', 'd', 'e'};
//void write(char[] cbuf)写入==字符数组==。
fw.write(cs); //abcde
//void write(char[] cbuf, int off, int len)==写入字符数组的某一部分==,off数组的开始索引,len写的字符个数。
//写入字符数组cs中间三个
fw.write(cs, 1, 3); //bcd
//void write(String str)==写入字符串==。
fw.write("魔鬼筋肉人"); //魔鬼筋肉人
//void write(String str, int off, int len)
//写后三个
fw.write("Java程序员", 4, 3); //程序人
fw.close();
}
3.7 字符输出流的续写和换行
- 续写,追加写:使用两个参数的构造方法
- FileWriter(String fileName, boolean append)
- FileWriter(File file, boolean append)
- 参数:
- String fileName,File file:写入数据的目的地
- boolean append:续写开关
- true:不会创建新的文件覆盖源文件,可以续写
- false:创建新的文件覆盖源文件
- 换行:换行符号
- windows:\r\n
- linux:/n
- mac:/r
- 字节流和字符流换行的区别
- 字节流:因为写入的是字节数组,所以需要把"\r\n"这个字符串转为字节数组
for(int i = 0; i < 2; i++){
fos.write("你好".getBytes());
fos.write("\r\n".getBytes());
}
- 字符流:写入的可以是字符或者字符串,所以不需要转换
for(int i = 0; i < 2; i++){
fw.write("你好" + "\r\n");
}
public static void main(String[] args) throws IOException {
//1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地
FileWriter fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\g.txt", true);
for(int i = 0; i < 2; i++){
fw.write("你好" + "\r\n");
}
fw.close();
}
//结果:
你好
你好
第四章 IO异常的处理
4.1 使用try_catch_finally处理流中的异常
- 在jdk1.7之前使用try catch finally 处理流中的异常
- 格式:
try{
可能会产出异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}finally{
一定会指定的代码
资源释放
}
- 注:变量在定义的时候,可以没有值,但是使用的时候必须有值
- 注:fw = new FileWriter(“Dark-horse-teaching\src\cn\javaadvance\day09\g.txt”, true);
- 执行失败,fw没有值,fw.close();就会报错
- 给FileWriter fw;一个null
- FileWriter fw = null;
- 注:finally中的catch也有异常的,需要单独的try…catch
- 注:finally中:创建对象失败了,fw的默认值就是null,null是不能调用方法的,会抛出NullPointerException,需要增加一个判断,不是null在把资源释放
public static void main(String[] args) {
//增大作用域
FileWriter fw = null;
try{
fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\g.txt", true);
for(int i = 0; i < 2; i++){
fw.write("你好" + "\r\n");
}
}catch (IOException e){
System.out.println(e);
}finally {
//==创建对象失败==了,==fw的默认值就是null==,==null是不能调用方法的,会抛出NullPointerException==,需要==增加一个判断,不是null在把资源释放==
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.2 JDK7和JDK9流中异常的处理
- JDK7的新特性:
- 在try的后边可以增加一个(),在括号中可以定义流对象
- 那么这个流对象的作用域就在try中有效
- try中的代码执行完毕,会自动把流对象释放,不用写finally
- 格式:
try(定义流对象;定义流对象....){
可能会产出异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}
public static void main(String[] args) {
try(//1. 创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("F:\\picture\\1.jpg");
//创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("E:\\picture\\1.jpg");){
///使用字节输入流对象中的方法read读取文件
//读取一个字节写入一个字节的方式(一)
int len = 0;
while((len = fis.read()) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}
}catch (IOException e){
System.out.println(e);
}
}
- JDK9的新特性:
- try的前边可以定义流对象
- 在try后边的()中可以直接引入流对象的名称(变量名)
- 在try代码执行完毕之后,流对象也可以释放掉,不用写finally
- 格式:
A a = new A();
B b = new B();
try(a,b){
可能会产出异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}
public static void main(String[] args) throws IOException {
//1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("c:\\1.jpg");
//2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("d:\\1.jpg");
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
}
第五章 属性集
5.1 使用Properties集合存储数据,遍历取出Properties集合中的数据
- java.util.Properties集合 extends Hashtable<k,v> implementsMap<k,v>
- Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
- Properties集合是一个唯一和IO流相结合的集合
- 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
- 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
- 属性列表中每个键及其对应值都是一个字符串
- Properties集合是一个双列集合,key和value默认都是字符串
- 所以不用写泛型
- 使用Properties集合存储数据,遍历取出Properties集合中的数据
- Properties集合是一个双列集合,key和value默认都是字符串
- Properties集合有一些操作字符串的特有方法
- Object setProperty(String key, String value):调用 Hashtable 的方法 put。
- String getProperty(String key):通过key找到value值,此方法相当于Map集合中的get(key)方法
- Set stringPropertyNames():返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet方法
public class Demo01Properties {
public static void main(String[] args) {
show1();
}
private static void show1() {
//创建Properties对象
Properties prop = new Properties();
//使用setProperty往集合中添加数据
prop.setProperty("赵丽颖", "168");
prop.setProperty("古力娜扎", "170");
prop.setProperty("迪丽热巴", "165");
//使用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);
}
}
}
//结果:
赵丽颖=168
古力娜扎=170
迪丽热巴=165
5.2 Properties集合中的方法store
- 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
- void store(OutputStream out, String comments)
- void store(Writer writer, String comments)
- 参数:
- OutputStream out:字节输出流,不能写入中文【!】
- Writer writer:字符输出流,可以写中文
- String comments:注释,用来解释说明保存的文件是做什么用的
- 不能使用中文,会产生乱码,默认是Unicode编码
- 一般使用""空字符串
- 使用步骤:
- 创建Properties集合对象,添加数据
- 创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
- 使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
- 释放资源
public class Demo01Properties {
public static void main(String[] args) throws IOException {
//show1();
shoow2();
}
//Properties集合中的方法store,集合中的临时数据,持久化写入到硬盘中存储
private static void shoow2() throws IOException {
//1.创建Properties集合对象,添加数据
Properties prop = new Properties();
prop.setProperty("赵丽颖", "168");
prop.setProperty("古力娜扎", "170");
prop.setProperty("迪丽热巴", "165");
/*
//2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
//FileOutputStream fos = new FileOutputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\g.txt");
FileWriter fw = new FileWriter("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\prop.txt");
//3. 使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
prop.store(fw, "save data");
//4. 释放资源
fw.close();
*/
//匿名对象使用完自动关了,不需要释放资源
//字节写入中文会出来乱码
prop.store(new FileOutputStream("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\prop2.txt"), "");
}
}
//字符写入中文结果:
#save data
#Tue Feb 25 11:31:00 CST 2020
赵丽颖=168
古力娜扎=170
迪丽热巴=165
//字节写入中文结果:
#
#Tue Feb 25 11:33:22 CST 2020
\u8D75\u4E3D\u9896=168
\u53E4\u529B\u5A1C\u624E=170
\u8FEA\u4E3D\u70ED\u5DF4=165
5.3 Properties集合中的方法load【重点】
- 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
- void load(InputStream inStream)
- void load(Reader reader)
- 参数:
- InputStream inStream:字节输入流,不能读取含有中文的键值对
- Reader reader:字符输入流,能读取含有中文的键值对
- 使用步骤:
- 创建Properties集合对象
- 使用Properties集合对象中的方法load读取保存键值对的文件
- 遍历Properties集合
- 注意:
- 存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
- 存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
- 存储键值对的文件中,键与值默认都是字符串,不用再加引号
- 因为字节流读取到中文会有乱码,所以我们一般都使用字符流
public class Demo01Properties {
public static void main(String[] args) throws IOException {
//show1();
//shoow2();
show3();
}
//可以使用Properties集合中的方法load,==把硬盘中保存的文件(键值对),读取到集合中使用==
private static void show3() throws IOException {
//1. 创建Properties集合对象
Properties prop = new Properties();
//2. 使用Properties集合对象中的方法load读取保存键值对的文件
prop.load(new FileReader("Dark-horse-teaching\\src\\cn\\javaadvance\\day09\\prop.txt"));
//3. 遍历Properties集合
Set<String> set = prop.stringPropertyNames();
//增强for
/*for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key + "=" + value);
}*/
//Iterator迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()){
String key = it.next();
String value = prop.getProperty(key);
System.out.println(key + "=" + value);
}
}
}
//结果:
赵丽颖=168
古力娜扎=170
迪丽热巴=165