9.IO流
流
- 概念:内存与存储设备之间传输数据的通道

流的分类
-
按方向分类【重点】
- 输入流:将<存储设备>中的内容读到<内存>中
- 输出流:将<内存>中的内容写到<存储设备>中
-
按单位分类
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
-
按功能分类
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
-
字节流的父类(抽象类):
-
InputStream:字节输入流
//InputStream 字节输入流 public int read(){} public int read(byte[] b){} public int read(byte[] b, int off, int len){} -
OutputStream:字节输出流
// OutputStream 字节输出流 public void write(int n){} public void write(byte[] b){} public void write(byte[] b, int off, int len){}
-
文件字节流
-
FileInputStream:文件字节输入流
- public int read(byte[] b) //从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,返回-1
public static void main(String[] args) throws Exception{ //因为这个文件有可能没有,所以会报检查型异常,抛出 //1.创建文件字节输入流,并指定文件路径 FileInputStream fis = new FileInputStream("D:\\Java\\code\\基础语法\\IO\\aaa.txt"); //2.读取文件 //fis.read(); //2.1单个字节读取 // int data = 0; // while ((data=fis.read())!=-1){ // System.out.println((char) data); // } //2.2一次读取多个字节 byte[] buf = new byte[3];// 大小为3的缓存区 // int count = fis.read(buf);// 一次读3个 // System.out.println(new String(buf)); // System.out.println(count); // int count1 = fis.read(buf);//再读3个 // System.out.println(new String(buf)); // System.out.println(count1); // int count2 = fis.read(buf); // System.out.println(new String(buf,0,count2));//再读三个,从0位置开始打印 // System.out.println(count2); int count = 0; while ((count=fis.read(buf))!=-1){ System.out.println(new String(buf,0,count)); } //3.关闭 fis.close(); System.out.println("执行完毕"); } -
FileOutputStream:文件字节输出流
- public void write(byte[] b) //一次写多个字节,将b数组中所有字节,写入输出流
public static void main(String[] args) throws Exception{ //1.创建文件字节流输出对象 FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\bbb.txt"); //FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\bbb.txt",true);//加true不覆盖 //2.写入文件 fos.write(97); fos.write('b'); fos.write('c'); String string = ",helloworld"; fos.write(string.getBytes()); } -
图片复制案例
public static void main(String[] args) throws Exception{
//1.创建流
//1.1文件字节输入流
FileInputStream fis = new FileInputStream("D:\\Java\\code\\基础语法\\IO\\001.png");
//1.2文件字节输出流
FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\002.png");
//2.实现复制:一边读,一边写
byte[] buf = new byte[1024];
int count = 0;
while ((count = fis.read(buf))!=-1){
fos.write(buf,0,count);
}
//3.关闭
fis.close();
fos.close();
System.out.println("复制完毕");
}
字节缓冲流
缓冲流:BufferedInputStream/ BufferedOutputStream
- 提高IO效率,减少访问磁盘次数
- 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
/*使用字节缓冲流读取
* BufferedInputStream*/
public class Demo4_HuanChong {
public static void main(String[] args) throws Exception {
//1.创建BufferedInputStream
FileInputStream fis = new FileInputStream("D:\\Java\\code\\基础语法\\IO\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
//2.读取(不使用fis读了,因为fis每次都是从硬盘里读,从缓冲区读)
int data = 0;
while ((data = bis.read())!=-1){
System.out.print((char) data);
}
//自创缓冲区
byte[] buf = new byte[1024];
int count = 0;
while ((count = bis.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
//3.关闭(关缓冲流就行,内部会自动关闭fis)
bis.close();
}
}
/*使用字节缓冲流写入文件
* BuffererOutputStream*/
public class Demo5_HuanChong_Write {
public static void main(String[] args) throws Exception{
//1.创建字节输出缓冲流
FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//2.写入文件
for (int i = 0; i < 10; i++) {
bos.write("helloword\r\n".getBytes());//写入了缓冲区,所以文件里没有内容(\r\n换行)
bos.flush();//刷新到硬盘
}
//3.关闭
bos.close();
}
}
对象流
ObjectOutputStream / ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串的功能
- 增强了读写对象的功能
- readObject() 从流中读取一个对象
- writeObject(Object obj) 从流中写入一个对象
使用流传输对象的过程称为序列化(写入)、反序列化(读取)
序列化
ObjectOutputStream(写入)
/*使用ObjcetOutputStream实现对象的序列化
* 要求:序列化的类必须要实现Serializable接口*/
public class ObjcetOutputStream {
public static void main(String[] args) throws Exception{
//1.创建对象流
FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//2.序列化(写入操作)
Student zhangsan = new Student("张三",20);
oos.writeObject(zhangsan);//想要序列化,类必须可以实现Serializable接口
//3.关闭
oos.close();
System.out.println("序列化完毕");
}
}
反序列化
/*使用ObjectInputStream实现反序列化(读取,重构成对象)*/
public class ObjectInput {
public static void main(String[] args) throws Exception{
//1.创建对象流
FileInputStream fis = new FileInputStream("D:\\Java\\code\\基础语法\\IO\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//2.读取文件
Student s = (Student) ois.readObject();
//Student s1 = (Student) ois.readObject();//异常,不能读多次
//3.关闭
ois.close();
System.out.println("反序列化完毕");
System.out.println(s.toString());
}
}
注意事项
1.某个类要想序列化必须实现Serializable接口
2.序列化类中对象属性要求实现Serializable接口
3.序列化版本号ID(serialVersionUID),保证序列化的类和反序列化的类是同一个类
4.使用transient修饰属性,这个属性就不能序列化
5.静态属性不能序列化
6.序列化多个对象,可以借助集合来实现
字符编码
- ISO-8859-1:收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号
- UTF-8: 针对Unicode码表的可变长度字符编码
- GB2313: 简体中文
- GBK: 简体中文、扩充
- BIG5: 台湾、繁体中文
注意:当编码方式和解码方式不同时会出现乱码
字符流的父类(抽象类)
- Reader:字符输入流
public int read(){}public int read(char[] c){}public int read(char[] b, int off, int len){}
- Writer:字符输出流
public void write(int n){}public void write(String str){}public void write(char[] c){}
文件字符流
-
FileReader:
-
public int read(char[] c) //从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果到达文件的尾部,返回-1 -
/*使用FileReader读取文件*/ public class Demo2_FileReader { public static void main(String[] args) throws Exception{ //1.创建FileReader文件字符输入流 FileReader fr = new FileReader("D:\\Java\\code\\基础语法\\IO\\hello.txt"); //2.读取 //2.1单个字符读取 // int data = 0; // while ((data=fr.read())!=-1){ // System.out.print((char)data); // } //2.2多个字符读取 char[] buf = new char[1024]; int count = 0; while ((count=fr.read(buf))!=-1){ System.out.println(new String(buf,0,count)); } //3.关闭 fr.close(); } }
-
-
FileWriter:
-
public void write(String str) //一次写多个字符,将b数组中所有字符写入输出流 -
/*使用FileWriter写入文件*/ public class Demo3_FileWriter { public static void main(String[] args) throws Exception{ //1.创建FileWriter对象 FileWriter fw = new FileWriter("D:\\Java\\code\\基础语法\\IO\\writer.txt"); //2.写入 for (int i = 0; i < 10; i++) { fw.write("java是世界上最好的语言\r\n"); fw.flush(); } //3.关闭 fw.close(); System.out.println("执行完毕"); } }
-
使用FileReader和FileWriter实现文件复制
注:字符流不能复制图片或二进制文件,只能复制文本文件,使用字节流可复制任意文件
/*使用FileReader和FileWriter复制文本文件,不能复制图片或二进制文件*/
public class Demo4_Copy {
public static void main(String[] args) throws Exception{
//1.创建FileReader和FileWriter
FileReader fr = new FileReader("D:\\Java\\code\\基础语法\\IO\\writer.txt");
FileWriter fw = new FileWriter("D:\\Java\\code\\基础语法\\IO\\writer2.txt");
//2.读写
int data = 0;
while ((data=fr.read())!=-1){ //读
fw.write(data); //写
fw.flush();
}
//3.关闭
fr.close();
fw.close();
System.out.println("复制完毕");
}
}
字符缓冲流
BufferedReader / BufferedWriter
- 高效读写
- 支持输入换行符
- 可一次写一行读一行
BufferedReader
/*使用字符缓冲流读取文件
* BufferedReader*/
public class Demo5_BufferedReader {
public static void main(String[] args) throws Exception{
//1.创建字符缓冲流
FileReader fr = new FileReader("D:\\Java\\code\\基础语法\\IO\\writer.txt");
BufferedReader br = new BufferedReader(fr);
//2.读取
//2.1第一种方式
// char[] buf = new char[1024];
// int count = 0;
// while ((count=br.read(buf))!=-1){
// System.out.println(new String(buf,0,count));
// }
//2.2第二种方式:一行一行的读readLine()
String line = null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
//3.关闭
br.close();
}
}
BufferedWriter
/*演示BufferedWriter的使用*/
public class Demo6_BufferedWriter {
public static void main(String[] args) throws Exception{
//1.创建BufferedWriter对象
FileWriter fw = new FileWriter("D:\\Java\\code\\基础语法\\IO\\buffer1.txt");
BufferedWriter bw = new BufferedWriter(fw);
//2.写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.flush();
}
//3.关闭
bw.close();
System.out.println("执行完毕");
}
}
打印流
PrintWriter:
- 封装了print()/println()方法,支持写入后换行
- 支持数据原装打印
/*演示PrintWriter的使用*/
public class Demo7_Print {
public static void main(String[] args) throws Exception{
//1.创建打印流
PrintWriter pw = new PrintWriter("D:\\Java\\code\\基础语法\\IO\\print.txt");
//2.调用打印方法
pw.println(97);
pw.println(true);
pw.println(3.14);
pw.println('a');
//3.关闭
pw.close();
System.out.println("执行完毕");
}
}
转换流
桥转换流:InputStreamReader/OutputStreamWriter
- 可将字节流转换为字符流
- 可设置字符的编码方式
/*演示InputStreamReader的使用:读取文件,指定使用的编码*/
public class Demo8_InputStreamReader {
public static void main(String[] args) throws Exception{
//1.创建InputStreamReader对象
FileInputStream fis = new FileInputStream("D:\\Java\\code\\基础语法\\IO\\writer.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//2.读取文件
int data = 0;
while ((data=isr.read())!=-1){
System.out.print((char) data);
}
//3.关闭
isr.close();
}
}
/*使用OutStreamWriter写入文件,使用指定的编码*/
public class Demo9_OutStreamWriter {
public static void main(String[] args) throws Exception{
//1.创建OutStreamWriter
FileOutputStream fos = new FileOutputStream("D:\\Java\\code\\基础语法\\IO\\info.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
//2.写入
for (int i = 0; i < 10; i++) {
osw.write("我爱东北\r\n");
osw.flush();
}
//3.关闭
osw.close();
System.out.println("执行成功");
}
}
File类
概念:代表物理盘符中的一个文件或者文件夹
FileFliter接口
- public interface FileFilter
- boolean accept(File pathname)
当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中。
/*File类的使用:
* (1)分隔符
* (2)文件操作
* (3)文件夹操作*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//separator();
//fileOpe();
directoryOpe();
}
//(1)分隔符
public static void separator(){
System.out.println("路径分隔符"+ File.pathSeparator);
System.out.println("名称分隔符"+File.separator);
}
//(2)文件操作
public static void fileOpe() throws Exception{
//1.创建文件
File file = new File("D:\\Java\\code\\基础语法\\IO\\file.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());//文件-属性-只读:false
System.out.println("是否是文件"+file.isFile());
System.out.println("是否隐藏:"+file.isHidden());//文件-属性-隐藏:true
}
//(3)文件夹操作
public static void directoryOpe() throws Exception{
//1.创建文件夹
File dir = new File("D:\\Java\\code\\基础语法\\IO\\aaa\\bbb\\ccc");
System.out.println(dir.toString());
if(!dir.exists()){
//dir.mkdir();//只能创建单级目录
System.out.println("创建结果"+dir.mkdirs());//创建多级目录
}
//2.删除文件夹
//2.1直接删除
//System.out.println("删除结果:"+dir.delete());//只删除最底层ccc,必须是空目录
//2.2使用jvm删除
//dir.deleteOnExit();
//Thread.sleep(5000);
//3.获取文件夹信息
System.out.println("获取绝对路径:"+dir.getAbsolutePath());
System.out.println("获取路径:"+dir.getPath());
System.out.println("获取父目录:"+dir.getParent());
System.out.println("获取文件夹名称:"+dir.getName());//最底层文件夹名称
System.out.println("获取创建时间:"+new Date(dir.lastModified()).toLocaleString());
//4.判断
System.out.println("是否是文件夹:"+dir.isDirectory());
System.out.println("是否是隐藏:"+dir.isHidden());
//5.遍历文件夹
File dir2 = new File("C:\\Users\\陶李天一\\Desktop\\学习\\3.JAVA学习\\JavaSE\\9.IO流");
String[] files = dir2.list();
System.out.println("------------------------");
for(String string : files){
System.out.println(string);
}
//fileFilter接口的使用
System.out.println("---------fileFilter----------");
File[] files1 = dir2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".md")){
return true;
}
return false;
}
});
for (File file : files1) {
System.out.println(file.getName());
}
}
}
两个案例
1)递归遍历文件夹
2)递归删除文件夹
/*案例1:递归遍历文件夹
* 案例2:递归删除文件夹*/
public class ListDemo {
public static void main(String[] args) {
//listDir(new File("C:\\Users\\陶李天一\\Desktop\\学习\\3.JAVA学习"));
deleteDir(new File("C:\\Users\\陶李天一\\Desktop\\学习\\用程序删除"));
}
//案例1:递归遍历文件夹
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());
}
}
}
}
//案例2:递归删除文件夹
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集合的使用*/
public class Demo1_Properties {
public static void main(String[] args) throws Exception {
//1.创建集合
Properties properties = new Properties();
//2.添加数据
properties.setProperty("username","zhangsan");
properties.setProperty("age","20");
System.out.println(properties.toString());
//3.遍历
//3.1----keyset----
//3.2----entryset----
//3.3----stringPropertyNames()----
Set<String> pronames = properties.stringPropertyNames();
for (String pro: pronames
) {
System.out.println(pro+"---"+properties.getProperty(pro));
}
//4.和流有关的方法
//4.1 list
// PrintWriter pw = new PrintWriter("d:\\print.txt");
// properties.list(pw);
// pw.close();
//4.2 store
// FileOutputStream fos = new FileOutputStream("d:\\print.properties");
// properties.store(fos,"注释");
// fos.close();
//4.3 load
Properties properties1 = new Properties();
FileInputStream fis = new FileInputStream("d:\\print.properties");
properties1.load(fis);
fis.close();
System.out.println(properties1.toString());
}
}

浙公网安备 33010602011771号