首页 > 编程语言 >02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集

时间:2023-02-26 19:02:11浏览次数:49  
标签:02 day09 字节 写入 len write String IO 读取


第一章 IO概念

1.1 什么是IO

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_数据结构

  1. Java中I/O操作主要是指使用java.io包下的内容,进行输入,输出操作。
  • 输入也叫做:读取数据
  • 输出也叫做:写入数据
  1. 内存(RAM),硬盘(ROM)

1.2 IO的分类

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_数据结构_02

1.3 IO的流向说明图解

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_开发语言_03

  1. 根据数据的流向分为:
  • 输入流
  • 输出流
  1. 根据数据的类型分为:
  • 字节流
  • 字符流

1.4 顶级父类们

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_输出流_04

1.5 总结

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_数据结构_05

  1. I/O流介绍:
  • I:input 输入(读取)
  • 输入:把硬盘中的数据,读取到内存中使用
  • O:output 输出(写入)
  • 输出:把内存中的数据,写入到硬盘中保存
  • 流:数据(字符,字节
  • 1个字符 = 2个字节
  • 1个字节 = 8个二进制
  • 因为流中数据分为(字符,字节)所以有:
  • 字节输入流
  • 字节输出流
  • 字符输入流
  • 字符输出流

第二章 字节流

2.1 一切皆为字节

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_输出流_06

2.2 字节输出流_OutputStream类&FileOutputStream类介绍

  1. java.io.OutputStream:字节输出流
  • 抽象类是表示输出字节流的所有类的超类。
  1. 定义了一些子类共性的成员方法:
  • 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字节)
  1. java.io.FileOutputStream extends OutputStream
  • FileOutputStream:文件字节输出流
  1. 作用:把内存中的数据写入到硬盘的文件中
  2. 构造方法:
  • FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。
  • FileOutputStream(File file) :创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
  1. 参数:写入数据的目的
  • String name:目的地是一个文件的路径
  • File file:目的地是一个文件
  1. 构造方法的作用:
  1. 创建一个FileOutputStream对象
  2. 根据构造方法中传递的文件/文件路径,创建一个空的文件
  3. 会把FileOutputStream对象指向创建好的文件

2.3 字节输出流写入数据到文件

  1. 写入数据的原理(内存–>硬盘)
  • java程序–>JVM(java虚拟机)–>OS(操作系统)–>OS调用写数据的方法–>把数据写入到文件中
  1. 字节输出流的使用步骤【重点】:
  1. 创建一个FileOutputStream对象,构造方法中传递写入数据的目的地(创建一个空的文件)
  2. 调用FileOutputStream对象中的方法write,把数据写入到文件中
  3. 释放资源[close方法](流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
  1. 三个步骤都会报出异常解决如下:
  1. 创建FileOutputStream对象会抛出–>io.FileNotFoundException
  2. write和close方法会抛出–>io.IOException
  3. 因为FileNotFoundException是IOException的子类
  4. 所以直接抛出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 文件存储的原理和记事本打开文件的原理

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_数据结构_07

2.5 字节输出流写多个字节的方法

  1. public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
  • 一次写多个字节:
  • 如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
  • 如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)
  1. public void write(byte[] b, int off, int len) :把字节数组的一部分写入到文件中
  • int off:数组的开始索引
  • int len:写几个字节
  1. 写入字符的方法:可以使用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 字节输出流的续写和换行(前面的方式再次运行会覆盖)

  1. 追加写/续写【重点】:使用两个参数的构造方法
  • FileOutputStream(String name, boolean append)创建一个向具有指定 name 的文件中写入数据的输出文件流。
  • FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
  1. 参数:
  • String name,File file:写入数据的目的地
  • boolean append:追加写开关
  • true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据
  • false:创建一个新文件,覆盖源文件
  1. 写换行:写换行符号【重点】(这个也是属于字符串: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类介绍

  1. java.io.InputStream:字节输入流
  • 抽象类是表示字节输入流的所有类的超类。
  1. 定义了所有子类共性的方法:
  • int read():从输入流中读取数据的下一个字节。
  • 读取文件中的一个字节并返回,读取到文件的末尾返回-1
  • 每次读取一个字节指针向后移一位
  • int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
  • void close():关闭此输入流并释放与该流关联的所有系统资源
  1. java.io.FileInputStream extends InputStream
  • FileInputStream:文件字节输入流
  1. 作用:把硬盘文件中的数据,读取到内存中使用
  2. 构造方法:
  • FileInputStream(String name)
  • FileInputStream(File file)
  1. 参数:读取文件的数据源
  • String name:文件的路径
  • File file:文件
  1. 构造方法的作用:
  1. 会创建一个FileInputStream对象
  2. 会把FileInputStream对象指向构造方法中要读取的文件

2.8 字节输入流读取字节数据

  1. 读取数据的原理(硬盘–>内存)
  • java程序–>JVM–>OS–>OS读取数据的方法–>读取文件
  1. 字节输入流的使用步骤【重点】
  1. 创建FileInputStream对象,构造方法中绑定要读取的数据源
  2. 使用FileInputStream对象中的方法read,读取文件
  3. 释放资源
  1. 优化:while循环【重点】
  1. 读取文件是一个重复的过程,所以可以使用循环优化
  2. 不知道文件多少个字节,使用while循环
  3. while结束条件->读取到-1时候
  4. 格式:(固定)
int len = 0;    //记录读取到的字符
while((len = fis.read())!=-1){
System.out.print((char)len); //ASCLL码转换为char类型
}
  • 布尔表达式(len = fis.read())!=-1
  1. fis.read():读取一个字节
  2. len = fis.read():把读取到的字节赋值给变量len
  3. (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 字节输入流一次读取一个字节的原理

02_09_Java语音进阶||day09_IO概念、字节流、字符流、IO异常的处理、属性集_java_08

2.10 字节输入流一次读取多个字节

  1. 字节输入流一次读取多个字节的方法:
  • int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
  1. 明确两件事情:
  1. 方法的参数byte[]的作用?
  • 起到缓冲作用,存储每次读取到的多个字节
  • 数组的长度一把定义为1024(1kb)或者1024的整数倍【!】
  1. 方法的返回值int是什么?
  • 每次读取的有效字节个数
  1. 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));
}
  1. 原理
  2. 优化: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 练习_文件复制

  1. 原理
  2. 文件复制练习:一读一写
  3. 明确:
  • 数据源: F:\picture\1.jpg
  • 数据的目的地: E:\picture\1.jpg
  1. 文件复制的步骤:
  1. 创建一个字节输入流对象,构造方法中绑定要读取的数据源
  2. 创建一个字节输出流对象,构造方法中绑定要写入的目的地
  3. 使用字节输入流对象中的方法read读取文件
  4. 使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
  5. 释放资源
  • 注:先关写入的(如果写入完了,读取肯定完了)
  1. 读写方式:
  1. 读取一个字节写入一个字节的方式(一)
int len = 0;    //记录每次读取的有效字节个数
while((len = fis.read()) != -1){
//使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
fos.write(len);
}
  1. 使用数组缓冲读取多个字节,写入多个字节(二,常用)
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. 使用字节流读取中文文件
  2. 1个中文
  • GBK:占用两个字节
  • UTF-8:占用3个字节
  1. “你好”出来的是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();
}
//结果:
ä
½

å
¥
½
  • 一次读取的就是三分之一的字节
  1. 解决方法:
    使用第三章的字符流–>一次读取一个字符

第三章 字符流

3.1 字符输入流_Reader类&FileReader类介绍

  1. java.io.Reader:字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类
  2. 共性的成员方法:
  • int read():读取单个字符并返回。
  • int read(char[] cbuf):一次读取多个字符,将字符读入数组。
  • 例:char[] chars = new char[1024];
  • void close():关闭该流并释放与之关联的所有资源。
  1. java.io.FileReader extends InputStreamReader extends Reader(多继承)
  2. FileReader:文件字符输入流
  3. 作用:把硬盘文件中的数据以字符的方式读取到内存中
  4. 构造方法:
  • FileReader(String fileName)
  • FileReader(File file)
  1. 参数:读取文件的数据源
  • String fileName:文件的路径
  • File file:一个文件
  1. FileReader构造方法的作用:
  1. 创建一个FileReader对象
  2. 会把FileReader对象指向要读取的文件

3.2 字符输入流读取字符数据(使用方式一样)

  1. 字符输入流的使用步骤【重点】:
  1. 创建FileReader对象,构造方法中绑定要读取的数据源
  2. 使用FileReader对象中的方法read读取文件
  3. 释放资源
  1. 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类介绍

  1. java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类
  2. 共性的成员方法:
  • 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() 关闭此流,但要先刷新它。
  1. java.io.FileWriter extends OutputStreamWriter extends Writer
  2. FileWriter:文件字符输出流
  3. 作用:把内存中字符数据写入到文件中
  4. 构造方法:
  • FileWriter(File file):根据给定的 File 对象构造一个 FileWriter 对象。
  • FileWriter(String fileName):根据给定的文件名构造一个 FileWriter 对象。
  1. 参数:写入数据的目的地
  • String fileName:文件的路径
  • File file:是一个文件
  1. 构造方法的作用:
  1. 会创建一个FileWriter对象
  2. 会根据构造方法中传递的文件/文件的路径,创建文件
  3. 会把FileWriter对象指向创建好的文件

3.4 字符输出流的基本使用_写出单个字符到文件

  1. 字符输出流的使用步骤(重点):
  1. 创建FileWriter对象,构造方法中绑定要写入数据的目的地
  2. 使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
  3. 使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
  4. 释放资源(会先把内存缓冲区中的数据刷新到文件中【flush可以不用写】)
  1. 字节流和字符流的区别
  • 字节:写入到文件中
  • 字符:写入到内存缓存区中
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方法的区别

  1. 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 字符输出流写数据的其他方法

  1. 字符输出流写数据的其他方法
  • 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 字符输出流的续写和换行

  1. 续写,追加写:使用两个参数的构造方法
  • FileWriter(String fileName, boolean append)
  • FileWriter(File file, boolean append)
  1. 参数:
  • String fileName,File file:写入数据的目的地
  • boolean append:续写开关
  • true:不会创建新的文件覆盖源文件,可以续写
  • false:创建新的文件覆盖源文件
  1. 换行:换行符号
  • 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处理流中的异常

  1. jdk1.7之前使用try catch finally 处理流中的异常
  1. 格式:
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流中异常的处理

  1. JDK7的新特性
  1. 在try的后边可以增加一个(),在括号中可以定义流对象
  2. 那么这个流对象的作用域就在try中有效
  3. try中的代码执行完毕,会自动把流对象释放,不用写finally
  4. 格式:
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);
}
}
  1. JDK9的新特性:
  1. try的前边可以定义流对象
  2. 在try后边的()中可以直接引入流对象的名称(变量名)
  3. 在try代码执行完毕之后,流对象也可以释放掉,不用写finally
  4. 格式:
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集合中的数据

  1. java.util.Properties集合 extends Hashtable<k,v> implementsMap<k,v>
  • Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
  • Properties集合是一个唯一和IO流相结合的集合
  • 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
  • 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
  • 属性列表中每个键及其对应值都是一个字符串
  • Properties集合是一个双列集合,key和value默认都是字符串
  • 所以不用写泛型
  1. 使用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

  1. 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
  • void store(OutputStream out, String comments)
  • void store(Writer writer, String comments)
  1. 参数:
  • OutputStream out:字节输出流,不能写入中文【!】
  • Writer writer:字符输出流,可以写中文
  • String comments:注释,用来解释说明保存的文件是做什么用的
  • 不能使用中文,会产生乱码,默认是Unicode编码
  • 一般使用""空字符串
  1. 使用步骤:
  1. 创建Properties集合对象,添加数据
  2. 创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
  3. 使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
  4. 释放资源
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【重点】

  1. 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用
  • void load(InputStream inStream)
  • void load(Reader reader)
  1. 参数:
  • InputStream inStream:字节输入流,不能读取含有中文的键值对
  • Reader reader:字符输入流,能读取含有中文的键值对
  1. 使用步骤:
  1. 创建Properties集合对象
  2. 使用Properties集合对象中的方法load读取保存键值对的文件
  3. 遍历Properties集合
  1. 注意:
  1. 存储键值对的文件中,键与值默认的连接符号可以使用=,空格(其他符号)
  2. 存储键值对的文件中,可以使用#进行注释,被注释的键值对不会再被读取
  3. 存储键值对的文件中,键与值默认都是字符串,不用再加引号
  4. 因为字节流读取到中文会有乱码,所以我们一般都使用字符流
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


标签:02,day09,字节,写入,len,write,String,IO,读取
From: https://blog.51cto.com/u_15980166/6086814

相关文章