I/O框架
什么是流
- 内存与存储设备之间传输数据的通道
数据借助于流传输
按方向分
【重点】
内存 <------(输入流)------(流入) 存储设备
内存 ---------(输出流)—>(流出) 存储设备
程序就在内存中
按单位分
- 字节流
- 以字节为单位,可以读写所有数据
- 字符流
- 以字符为单位,只能读写文本数据
按功能分
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
字节流的父类(抽象类)
- InputStream
- read()
- OutputStream
- write()
文件字节流
- FileInputStream
- FileOutputStream
FileInputStream
例子
package com.qf.chap15_1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 演示FileInputStream
*/
public class Demo1 {
public static void main(String[] args) throws IOException {
//创建文件字节输入流,并指定文件路径
FileInputStream fis = new FileInputStream("f:\\test\\aaa.txt");
//读取文件
//第一种方式:读一个字节打印一个字节
//int data = 0;
//while((data=fis.read())!=-1) {
// System.out.println((char)data);
//}
//第二种方式:一次性把读到的多个字节放到数组里面
// byte[] buff = new byte[3];
//
// int count = fis.read(buff);
// System.out.println(count);
// System.out.println(new String(buff));
//
// int count2 = fis.read(buff);
// System.out.println(count2);
// System.out.println(new String(buff));
//
// int count3 = fis.read(buff);
// System.out.println(count3);
// System.out.println(new String(buff,0,count3));
//
//第三种方式
byte[] buff = new byte[1024];
int count = 0;
while((count=fis.read(buff))!=-1) {
System.out.println(new String(buff,0,count));
}
//关闭流
fis.close();
System.out.println("执行完毕");
}
}
FileOutputStream
例子
package com.qf.chap15_1;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 文件字节输出流
* FileOutputStream
*/
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("f:\\test\\bbb.txt",true);//加个true则不会覆盖内容
//写入文件
// fos.write(97);
// fos.write('b');
// fos.write('c');
String str = "helloworld";
fos.write(str.getBytes());
//关闭
fos.close();
System.out.println("执行完毕");
}
}
字节流复制文件
大概思路
- 先输入,读入内存中
- 再输出,写到硬盘上
package com.qf.chap15_1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 使用文件字节流实现文件复制
*/
public class Demo3 {
public static void main(String[] args) throws IOException {
//创建文件字节输入流
FileInputStream fis = new FileInputStream("f:\\test\\39.jpg");
//创建文件字节输出流
FileOutputStream fos = new FileOutputStream("f:\\test\\001.jpg");
//实现复制
//一边读一边写
byte[] buf = new byte[1024];
int count = 0;
while((count=fis.read(buf))!=-1) {
fos.write(buf,0,count);
}
fis.close();
fos.close();
System.out.println("复制成功");
}
}
字节缓冲流
-
BufferedInputStream
-
BufferedOutputStream
-
提高IO效率,减少访问磁盘的次数
-
数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close
BufferedInputStream
例子
package com.qf.chap15_1;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 使用字节缓冲流读取
*/
public class Demo4 {
public static void main(String[] args) throws IOException {
//创建BufferInputStream
FileInputStream fis = new FileInputStream("f:\\test\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
//读取
//1、
// int data = 0;
// while((data=bis.read())!=-1) {
// System.out.print((char)data);
// }
//2、我们可以自己决定缓冲区大小
byte[] buf = new byte[1024];
int count = 0;
while((count=bis.read(buf))!=-1) {
System.out.println(new String(buf,0,count));
}
//关闭
bis.close();//关闭bis就行,fis会自动关闭
}
}
BufferedOutputStream
例子
package com.qf.chap15_1;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 使用字节缓冲流写出文件
*/
public class Demo5 {
public static void main(String[] args) throws IOException {
//创建字节输出缓冲流
FileOutputStream fos = new FileOutputStream("f:\\test\\buf.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//写入文件
for (int i = 0; i < 10; i++) {
//先写入默认的8k缓冲区中
bos.write("helloworld\r\n".getBytes());
//每次写都刷新到硬盘里面
bos.flush();
}
//关闭(内部会调用flush方法)
bos.close();
}
}
对象流
-
ObjectInputStream
-
ObjectOutputStream
-
增强缓冲区功能‘
-
增强了读写8种基本数据类型和字符串功能
-
增强了读写对象的功能
- readObject() 从流中读入一个对象
- writeObject() 向流中写出一个对象
使用流传输对象的过程称为序列化、反序列化
序列化
- 把内存中的对象写出到文件中
反序列化
- 从文件中读入对象到内存中
序列化**(序列化对象的类(包括类中的属性)必须实现Serializable接口)**
例子
package com.qf.chap15_1;
import java.io.Serializable;
//实现Serializable接口仅仅标志可以序列化,这个接口中本身没有任何方法
//相当于标志接口
//使用transient修饰属性,这个属性就不能被序列化
//静态属性也不能序列化
//序列化多个对象,可以借助集合来实现
public class Student implements Serializable{
/**
* serialVersionUID:序列化版本号ID
* 作用:可以保证序列化的类和反序列化的类为同一个类
*/
private static final long serialVersionUID = 100L;
private String name;
private int aeg;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int aeg) {
super();
this.name = name;
this.aeg = aeg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAeg() {
return aeg;
}
public void setAeg(int aeg) {
this.aeg = aeg;
}
@Override
public String toString() {
return "Student [name=" + name + ", aeg=" + aeg + "]";
}
}
package com.qf.chap15_1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/*
* 使用ObjectOutputStream实现对象的序列化
*
*/
public class Demo6 {
public static void main(String[] args) throws IOException {
//创建对象流
FileOutputStream fos = new FileOutputStream("f:\\test\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//序列化(写出操作)
Student s1 = new Student("张三",18);
oos.writeObject(s1);
//关闭
oos.close();
System.out.println("序列化完毕");
}
}
反序列化
例子
package com.qf.chap15_1;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
* 使用ObjectInputStream实现反序列化(重构对象)
*
*/
public class Demo7 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//创建对象流
FileInputStream fis = new FileInputStream("f:\\test\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//读取文件(反序列化)不能读多次
Student s = (Student) ois.readObject();
//关闭
ois.close();
System.out.println("执行完毕");
System.out.println(s.toString());
}
}
知道序列化和反序列化的注意事项
常见字符编码
- ISO-8859-1
- UTF-8
- GB2312
- GBK
- BIG5
当编码方式和解码方式不一致时,就会出现乱码
字符流
字符流的父类(抽象类)
- Reader 字符输入流
- read()
- Writer 字符输出流
- write()
文件字符流
- FileReader
- read()
- FileWriter
- write()
FileReader
例子
package com.qf.chap15_2;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* 使用FileReader读取文件
*/
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建FileReader 文件字符输入流
FileReader fr = new FileReader("f:\\test\\hello.txt");
//读取文件
//1、单个字符读取
// int data = 0;
// while((data=fr.read())!=-1) {//读取一个字符
// System.out.print((char)data);
// }
//2、
char[] buf = new char[2];
int count = 0;
while((count=fr.read(buf))!=-1) {
System.out.println(new String(buf,0,count));
}
//关闭
fr.close();
}
}
FileWriter
例子
package com.qf.chap15_2;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用FileWrite写入文件
*/
public class Demo3 {
public static void main(String[] args) throws IOException {
//创建FileWriter对象
FileWriter fw = new FileWriter("f:\\test\\write.txt");
//写入
for (int i = 0; i < 10; i++) {
fw.write("java是世界上最好的语言\n");
fw.flush();
}
//关闭
fw.close();
System.out.println("执行完毕");
}
}
字符流复制文件
例子
package com.qf.chap15_2;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用FileReader和FileWriter复制文本文件
* 注意:不能复制图片或二进制文件(因为它们没有字符编码)
*/
public class Demo4 {
public static void main(String[] args) throws IOException {
//创建对象
FileReader fr = new FileReader("f:\\test\\write.txt");
FileWriter fw = new FileWriter("f:\\test\\write2.txt");
//读写
int data = 0;
while((data=fr.read())!=-1) {
fw.write(data);
fw.flush();
}
//关闭
fr.close();
fw.close();
System.out.println("复制完毕");
}
}
字符缓冲流
-
BufferedReader
- read()
- readLine()
-
BufferedWriter
- write()
- flush()
- newLine()
-
高效读写
-
支持输入换行符
-
可一次写一行,读一行
BufferedReader
例子
package com.qf.chap15_2;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* 使用字符缓冲流读取文件
* BufferedReader
*/
public class Demo5 {
public static void main(String[] args) throws IOException {
//创建缓冲流
FileReader fr = new FileReader("f:\\test\\write.txt");
BufferedReader br = new BufferedReader(fr);
//读取
//1、
// char[] buf = new char[1024];
// int count = 0;
// while((count=br.read(buf))!=-1) {
// System.out.print(new String(buf,0,count));
// }
//2、一行一行地读
String rl = null;
while((rl=br.readLine())!=null) {
System.out.println(rl);
}
//关闭
br.close();
}
}
BufferedWriter
例子
package com.qf.chap15_2;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*
* 演示BufferedWriter
*/
public class Demo6 {
public static void main(String[] args) throws IOException {
//创建BufferedWriter对象
FileWriter fw = new FileWriter("f:\\test\\buffer.txt");
BufferedWriter bw = new BufferedWriter(fw);
//写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine();//写入一个换行
bw.flush();
}
//关闭
bw.close();
}
}
打印流
- PrintWriter(继承Writer)
- 封装了print()/println()方法,支持写入后换行
- 支持数据原样打印
package com.qf.chap15_2;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
/*
* 演示PrintWriter的使用
*/
public class Demo7 {
public static void main(String[] args) throws FileNotFoundException {
//创建打印流
PrintWriter pw = new PrintWriter("f:\\test\\print.txt");
//打印
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
//关闭
pw.close();
System.out.println("执行完毕");
}
}
转换流
桥转换流
-
InputStreamReader
- 字节流通向字符流的桥梁
-
OutputStreamWriter
- 字符流通向字节流的桥梁
-
可将字节流转换为字符流
-
可设置字符的编码方式
InputStreamReader
例子
package com.qf.chap15_3;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
/*
* 演示InputStreamReader读取文件,可以指定使用的编码
*/
public class Demo1 {
public static void main(String[] args) throws IOException {
//创建InputStreamReader对象
FileInputStream fis = new FileInputStream("f:\\test\\write.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//读取文件
int data = 0;
while((data=isr.read())!=-1) {
System.out.print((char)data);
}
//关闭
isr.close();
}
}
OutputStreamWriter
例子
package com.qf.chap15_3;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
/*
* OutputStreamWriter写出文件,可以使用指定编码
*/
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建流
FileOutputStream fos = new FileOutputStream("f:\\test\\haha.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
//写入
for (int i = 0; i < 10; i++) {
osw.write("我爱北京,我爱故乡\n");
osw.flush();
}
//关闭
osw.close();
System.out.println("执行成功");
}
}
File类
- 代表物理盘符中的一个文件或者文件夹
File类的一些方法
- createNewFile()
- mkdir() 创建新目录
- delete()
- exists()
- getAbsolutePath()
- getName()
- getParent()
- isDirectory()
- isFile()
- length()
- listFiles() 列出目录中所有内容
- renameTo()
文件操作
例子
package com.qf.chap15_4;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import javax.swing.JPopupMenu.Separator;
/*
* File类的使用
* 1、分隔符
* 2、文件操作
* 3、文件夹操作
*/
public class Demo1 {
public static void main(String[] args) throws IOException, InterruptedException {
separator();
fileOpe();
}
//分隔符
public static void separator() {
System.out.println("路径分隔符:" + File.pathSeparator);
System.out.println("名称分隔符:" + File.separator);
}
//文件操作
public static void fileOpe() throws IOException, InterruptedException {
//1、创建文件对象
File file = new File("f:\\test\\kiki.txt");
// System.out.println(file.toString());
if (!file.exists()) {
boolean b = file.createNewFile();//真正创建文件
System.out.println("创建结果:" + b);
}
//2、删除文件
//2.1直接删除
//System.out.println("删除结果:" + file.delete());
//2.2使用JVM退出时删除文件
//file.deleteOnExit();
//Thread.sleep(5000);
//3、获取文件
System.out.println("获取文件的绝对路径:" + file.getAbsolutePath());
System.out.println("获取路径:" + file.getPath());
System.out.println("获取文件名称:" + file.getName());
System.out.println("获取父目录:" + file.getParent());
System.out.println("获取文件长度" + file.length());
System.out.println("文件创建时间:" + new Date(file.lastModified()).toLocaleString());
//4、判断
System.out.println("是否可写" + file.canWrite());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
}
}
文件夹操作
例子
package com.qf.chap15_4;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import javax.swing.JPopupMenu.Separator;
/*
* File类的使用
* 1、分隔符
* 2、文件操作
* 3、文件夹操作
*/
public class Demo1 {
public static void main(String[] args) throws IOException, InterruptedException {
//separator();
//fileOpe();
directoryOpe();
}
//分隔符
public static void separator() {
System.out.println("路径分隔符:" + File.pathSeparator);
System.out.println("名称分隔符:" + File.separator);
}
//文件操作
public static void fileOpe() throws IOException, InterruptedException {
}
//文件夹操作
public static void directoryOpe() throws InterruptedException {
//创建文件夹
File dir = new File("f:\\aaa\\vvv\\bbb");
System.out.println(dir.toString());
if(!dir.exists()) {
//dir.mkdir();//只能创建单级目录
System.out.println("创建结果:" + dir.mkdirs());//可以创建多级目录
}
//删除文件夹
//直接删除
//System.out.println("删除结果:" + dir.delete());//这里只能删除空目录
//使用JVM删除
//Thread.sleep(5000);
//dir.deleteOnExit();
//获取文件夹信息
System.out.println("获取绝对路径:" + dir.getAbsolutePath());
System.out.println("获取路径:" + dir.getPath());
System.out.println("获取文件夹名称:" + dir.getName());
System.out.println("获取父目录:" + dir.getParent());
System.out.println("获取创建时间:" + new Date(dir.lastModified()).toLocaleString());
//判断
System.out.println("是否是文件夹:" + dir.isDirectory());
System.out.println("是否是隐藏:" + dir.isHidden());
//遍历文件夹
File dir2 = new File("f:\\test");
String[] list = dir2.list();
System.out.println("-------------");
for (String string : list) {
System.out.println(string);
}
}
}
FileFilter接口
当调用File类中的listFiles()方法时,支持传入FileFilter接口的实现类,对获取文件进行过滤,只有满足条件的文件才可以出现在listFiles()的返回值中
例子
package com.qf.chap15_4;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Date;
import javax.swing.JPopupMenu.Separator;
/*
* File类的使用
* 1、分隔符
* 2、文件操作
* 3、文件夹操作
*/
public class Demo1 {
public static void main(String[] args) throws IOException, InterruptedException {
directoryOpe();
}
//文件夹操作
public static void directoryOpe() throws InterruptedException {
//遍历文件夹
File dir2 = new File("f:\\test");
String[] list = dir2.list();
System.out.println("-------------");
for (String string : list) {
System.out.println(string);
}
System.out.println("-------------");
//FileFilter接口的使用
File[] files2 = dir2.listFiles(new FileFilter() {
//返回jpg格式的文件
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".jpg")) {
return true;
}
return false;
}
});
for (File file : files2) {
System.out.println(file.toString());
}
}
}
递归遍历和递归删除
例子
package com.qf.chap15_4;
import java.io.File;
public class Demo2 {
public static void main(String[] args) {
//listDir(new File("f:\\aaa"));
deleteDir(new File("f:\\aaa"));
}
//递归遍历文件夹
public static void listDir(File dir) {
File[] files = dir.listFiles();
System.out.println(dir.getAbsolutePath());
if (files!=null&&files.length>0) {
for (File file : files) {
if(file.isDirectory()) {
//递归
listDir(file);
}else {
System.out.println(file.getAbsolutePath());
}
}
}
}
//递归删除文件夹
public static void deleteDir(File dir) {
File[] files = dir.listFiles();
if(files!=null&&files.length>0) {
for (File file : files) {
if(file.isDirectory()) {
//递归
deleteDir(file);
}else {
//删除文件
System.out.println(file.getAbsolutePath() + "删除:" + file.delete());
}
}
}
System.out.println(dir.getAbsolutePath() + "删除:" + dir.delete());
}
}
补充:Properties
Properties:属性集合 继承HashTable
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型(因为它的类型已经确定)
- 和流有关
例子
package com.qf.chap15_4;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
/*
* 演示Properties集合的使用
*/
public class Demo3 {
public static void main(String[] args) throws IOException {
//创建集合
Properties properties = new Properties();
//添加数据
properties.setProperty("username", "zhangsan");
properties.setProperty("age", "20");
System.out.println(properties.toString());
//遍历
//1、keySet
//2、entrySet
//3、stringPropertyNames
Set<String> proNames = properties.stringPropertyNames();
for (String pro : proNames) {
System.out.println(pro + "---" + properties.getProperty(pro));
}
//和流有关的方法
//1、----------list方法-----------
// PrintWriter printWriter = new PrintWriter("f:\\test\\print2.txt");
// properties.list(printWriter);
//
// printWriter.close();
//2、----------store方法 保存-----------
// FileOutputStream fos = new FileOutputStream("f:\\test\\store.properties");
// properties.store(fos, "注释");
//
// fos.close();
//3、----------load方法 加载-----------
Properties properties2 = new Properties();
FileInputStream fis = new FileInputStream("f:\\test\\store.properties");
properties2.load(fis);
fis.close();
System.out.println(properties2.toString());
}
}