摘要:字节流、字符流;图片、文本复制;IO流异常处理;Properties配置读写
一、IO的分类
1.输入流、输出流
以内存为基准
- 输入流:内存 <----硬盘
- 输出流:内存 ----->硬盘
2.字节流、字符流
- 字节流:以字节为单位,读写数据的流
主要处理图片、视频类
- 字符流:以字符为单位,读写数据的流
主要处理文本数据
二、字节流
顶级父类:
- java.io.InputStream
- java.io.OutputStream
常用实现类:
- FileInputStream
- FileOutputStream
(1)FileInputStream fis
使用demo:
/**
* 以字节流的形式读取文件:java.io.FileInputStream;
* (1)创建输入流:FileInputStream fis = new FileInputStream(File/pathName);
* (2)用字节数组作为缓存,读取文件:
* byte[] b = new byte[1024];
* while ((len = fis.read(b)) != -1){
* fos.write(b,0,len); //将文件写到目标文件中。
* }
*
*/
public class FISRead {
public static void main(String[] args) throws IOException {
createFile();
writeFile();
//read1(); // 通过fis.read()读取单个字节,并返回字节int形式
read2();
}
/*以字节数组的形式:读文件*/
private static void read2() throws IOException {
FileInputStream fis = new FileInputStream("read.txt");
int len ; //每次读取有效字节的长度
byte[] bytes = new byte[2]; // 定义字节数组,作为装字节数据的容器
while ((len = fis.read(bytes)) != -1){
System.out.println(new String(bytes,0,len)); //这里从0写到len长度的数据。因为最后一次读取的数据len有效长度不定。
}
}
}
(2)FileOutputStream fos
使用demo:
/**
* 文件输出流:java.io.FileOutputStream;
* 构造方法:
* (1)FileOutputStream fos = new FileOutputStream(new File("a.txt")); //文件对象
* (2)FileOutputStream fos = new FileOutputStream("a.txt"); //文件路径
* (3)public FileOutputStream(File file, boolean append); //append = true (追加写) false (覆盖写)
* 基本方法:
* (1)public void close() : 关闭此输出流并释放与此流相关联的任何系统资源。
* (2)public void flush() : 刷新此输出流并强制任何缓冲的输出字节被写出。
* (3)public void write(byte[] b) : 将 b.length字节 从指定的字节数组写入此输出流。
* (***) (4)public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流。(常用)
*/
public class FOSWrite {
public static void main(String[] args) throws IOException {
//使用文件对象创建文件流对象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
//创建字节数组
byte[] bytes = {97,98,99,100,101};
for (int i = 0; i < bytes.length; i++) {
//写入单个字节
fos.write(bytes[i]);
//mac下的换行符
fos.write("\n".getBytes());
}
fos.close();
}
}
(3)图片复制demo
:字节流读写
public class PicCopy {
public static void main(String[] args) throws IOException {
//1.创建文件io流
FileInputStream fis = new FileInputStream("/Users/caowei/Desktop/屏幕快照/1.jpg");
FileOutputStream fos = new FileOutputStream("pictureCopy.jpg");
//2.读写文件
//读取的有效数据的长度
int len ;
//数据缓冲区
byte[] b = new byte[1024];
while ((len = fis.read(b)) != -1){
fos.write(b,0,len);
//System.out.println(Arrays.toString(b));
}
//3.关闭流
fos.close();
fis.close();
}
}
三、字符流
顶级父类:
- java.io.Reader
- java.io.Writer
常用实现类:
- FileReader
- FileWriter
(1)FileReader使用
import java.io.FileReader;
import java.io.IOException;
/**
* 字符输入流:java.io.Reader
* 实现类:java.id.FileReader extends OutputStreamReader extends Reader
* 构造方法:
* FileReader(File file) :
* FileReader(String fileName) :
* 常用方法:
* read():每次读取一个字符,返回:字符的int型,游标自动下移,读至末尾,返回-1
* read(char[] cbuf) 使用字符数组,作为容器。每次读取cbuf.length()的长度个字符到数组中,返回读取到的有效字符个数.
*
*/
public class FileRead {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("read.txt"); // 字符流,常用来处理文本信息。
int len;
char[] c = new char[1024]; //字符数组作为数据容器
while ((len = fr.read(c)) != -1){
System.out.println(new String(c,0 ,len)); //打印有效数据,len为有效数据长度。
//这里也可以定义一个输出流,将数据写到硬盘中。
}
}
}
(2)FileWriter
的使用步骤
/**
* 字符输入流:java.io.Writer
* 实现类:java.id.FileWriter
* 构造方法:
* FileWriter(File file) :
* FileWriter(String fileName) :
* 常用方法:
* //写字符数组
* write(char[] cbuf)
* write(char[] cbuf, int off, int len)
* //写字符串
* fs.write("字符串");
* fs.write("字符串,startIndex ,len")
*
* 使用步骤:
* 1.创建FileWriter对象,构造方法绑定数据写入的目的地
* 2.使用writer方法将数据写入到内存缓冲区中(不同于字节流)-->字符转换为字节的过程
* 3.使用flush()方法,将内存缓冲区的数据刷新到文件中(大文件读写,应该及时刷新数据,不要占用内存缓冲区)
* 4.释放资源:close()会先将缓冲区数据刷新到内存,再关闭资源。
*
*/
public class FileWrite {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("read.txt"); // 字符流,常用来处理文本信息。
FileWriter fw = new FileWriter("write.txt");
int len;
char[] c = new char[1024]; //字符数组作为数据容器
while ((len = fr.read(c)) != -1){
fw.write(c,0,len); //将数据写到了内存的缓冲区。还没有刷新到硬盘中,不同于字节流!
}
//在使用字符流时,没有使用时flush,或者close是无法将数据从缓冲加到硬盘的。
fw.close();
fr.close();
}
}
flush() 和 close()的区别: flush 刷新缓冲区,流对象可以继续使用; close 先刷新缓冲区,然后通知系统释放资源,流对象关闭
四、IO的异常处理
在实际的开发中,通常不会将异常抛出,而是捕获处理。
1.在jdk1.7之前,使用try catch finally 处理流中的异常的,步骤
try{
//可能产生异常的代码
}catch(){
//异常的处理逻辑
}finally{
//一定会执行的代码
//释放资源
}
例子
public static void main(String[] args) {
//提高变量的作用域,让finally可以使用
//定义变量的时候可以没有值,但是使用的时候必须有值。
FileReader fr = null;
FileWriter fw = null;
try{
//可能会产生异常的代码
fr = new FileReader("read.txt");
fw = new FileWriter("a.txt",false);
int len = 0;
char[] c = new char[1024];
while ((len = fr.read(c)) != -1){
fw.write(c,0,len);
}
}catch (IOException e){
//异常的处理逻辑
System.out.println(e);
}finally {
try {
//执行close()的时候也有可能产生异常,捕获抛出异常
fw.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.JDK7异常处理
JDK7新特性:try(){}catch(){} 在try后新增加()括号,可以在其中定义流对象,作用范围为try{},try{}中代码执行完毕后,自动释放资源。不用写finally了。
public class TryCatchByJDK7 {
public static void main(String[] args) {
//提高变量的作用域,让finally可以使用
//定义变量的时候可以没有值,但是使用的时候必须有值
try(FileReader fr = new FileReader("read.txt");
FileWriter fw = new FileWriter("a.txt",false);
){
//可能会产生异常的代码
int len = 0;
char[] c = new char[1024];
while ((len = fr.read(c)) != -1){
fw.write(c,0,len);
}
}catch (IOException e){
//异常的处理逻辑
System.out.println(e);
}
}
}
- JDK9: 可以在try前面定义流对象,在try()的小括号中接收参数。
五、属性集Properties类
1.概念:
java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其 对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时, System.getProperties 方法就是返回 一个 Properties 对象。
2.基本方法
- 构造函数:
public Properties() :创建一个空的属性列表。 - 存键值对:
public Object setProperty(String key, String value) : 保存一对属性。 - 取值:
public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。 - 获取键的集合:遍历取值;
public Set stringPropertyNames() :所有键的名称的集合。
使用,类似其超类Map的put()/get()/keySet()方法
3.与IO流相关的两个重要方法
load()/store():两种方法都有不同的重载形式,主要区别在于是否支持中文参数与。
- 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 表中的属性列表(键和元素对)写入输出字符。
读写配置文件的示例
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
writeProp(); //写配置文件
readProp(); //读取配置文件
}
/*读取配置文件,并打印*/
private static void readProp() throws IOException {
//1.创建Properties集合对象
Properties prop = new Properties();
//2.使用load()方法读取,并保存文件为键值对。
prop.load(new FileReader("prop.txt"));
//3.遍历prop集合
Set<String> strings = prop.stringPropertyNames();
for (String key : strings) {
String value = prop.getProperty(key);
System.out.println(value);
}
}
/*写配置文件*/
public static void writeProp() throws IOException {
//1.创建Properties集合,添加数据
Properties prop = new Properties();
prop.setProperty("ip","127.0.0.1");
prop.setProperty("port","442");
//2.创建字符输出流,构造函数绑定输出地址
FileWriter fw = new FileWriter("prop.txt");
//3.使用Properties集合中的store()方法,将集合中的临时数据写入到硬盘中
prop.store(fw,"save data");
//4.释放资源
fw.close();
}
}