IO流(应用广泛)
1.概念与三要素
本质是一套用于数据传输的机制
分类:
根据传输的方向(参照物–内存)
输入流:往内存传输数据
输出流:从内存往外传输数据
根据数据传输方式:
字符流:底层以字符形式进行传输
字节流:底层以字节形式进行传输
根据数据存放/获取的位置:硬盘、内存、网络、外设设备
四大基本流(对于的四个类都是抽象类)
2.硬盘
字符流
往硬盘.txt文件写入数据 字符输出流 文件—FileWriter(文件字符输出流)
package
cn.tedu.io.file;
import
java.io.FileWriter;
import
java.io.IOException;
public class FileWriterDemo1 {
public static void main(String[] args) throws IOException {
//创建文件字符输出流对象
//创建对象过程中会检测路径信息是否存在如果不存在就新建空文件
//如果指定路径信息存在则创建新的空文件进行覆盖
//为了保证输出流能往文件写入数据(之前已经有的数据不会影响新的写入数据)
FileWriter writer=new FileWriter("E:\\1.txt");
//写出数据
//底层为了提高和保证传输数据效率
//提供缓冲区来传输数据并且要求存满了才进行传输
//此时数据没有存满缓冲区就滞留在缓冲区数据丢失了
writer.write("七夕快乐");
//冲刷缓冲区
//即使数据没有存满也会进行传输
//防止数据滞留在缓冲区
writer.flush();
//关流
//含有自动冲刷的过程
writer.close();
//把流对象置为null(无用对象)
writer=null;
}
}
从硬盘.txt文件读取内容 字符输入流 文件—FileReader(文件字符输入流)
读取文件方式一:逐个字符来读取文本文件
package cn.tedu.text;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//创建文件字符输入流对象
//底层没有自带的缓冲区
FileReader reader=new FileReader("F:\\a.txt");
//返回单个字符的编码值
/*System.out.println(reader.read());
System.out.println(reader.read());
System.out.println(reader.read());
//读取完毕的标志---返回-1
System.out.println(reader.read());*/
//通过循环实现
int i=-1;
//把方法返回值(读取到的字符编码值)赋值给新变量,再让新变量和-1进行比较
while ((i=reader.read())!=-1){
//输出新变量的值(方法读取到的字符编码值)
System.out.println(i);
}
}
}
读取文件方式二:使用数组来读取文本文件
package cn.tedu.text;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo1 {
public static void main(String[] args) throws IOException {
//创建字符输入流对象
FileReader reader=new FileReader("F:\\1.txt");
//自建缓冲区
//新数组
char[] cs=new char[5];
//方法返回值就是读取字符的个数,返回-1读取结束
int len=-1;
while ((len=reader.read(cs))!=-1){
//把每次读取到的数据放到数组中
//展示数组内容
System.out.println(new String(cs,0, len));
}
//关流
reader.close();
}
}
字节流:
往硬盘.txt文件写入内容 字节输出流 文件—FileOutputStream(文件字节输出流)
package cn.tedu.text;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//创建文件字节输出流对象
//底层没有自带的缓冲区
//如果不指定append那么默认为false就是每次新建一个空文件覆盖之前的内容
//如果指定append为true那么每次就是追加数据
FileOutputStream fos=new FileOutputStream("F:\\2.txt");
//调用方法来写出数据
fos.write("你好".getBytes());
//关流
fos.close();
}
}
从硬盘.txt文件读取内容 字节输入流 文件—FileInputStream(文件字节输入流)
package cn.tedu.text;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建文件字节输入流对象
FileInputStream fis=new FileInputStream("F:\\3.txt");
//返回一个字节对应的编码值
System.out.println(fis.read());
System.out.println(fis.read());
System.out.println(fis.read());
//返回-1时说明读取完成
System.out.println(fis.read());
//自建缓冲区
byte[] bs=new byte[10];
int len=-1;
//返回的是读取到的字节数、遇到-1说明读取完毕
while ((len=fis.read(bs))!=-1){
System.out.println(new String(bs,0,len));
}
//关流
fis.close();
}
}
3.缓冲流(给别的流提供缓冲区)
BufferedReader—给字符输入流提供缓冲区
新的方法:readLine()–读取一行
package cn.tedu.buffer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferReaderDemo {
public static void main(String[] args) throws IOException {
//创建缓冲对象
BufferedReader br=new BufferedReader(new FileReader("F:\\4.txt"));
//读取数据(一行)
/*System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());*/
//用循环实现
String str="";
while ((str=br.readLine())!=null){
System.out.println(str);
}
//关流
br.close();
}
}
BufferWriter–提供一个更大的缓冲区
新的方法:newLine()–换行
package cn.tedu.buffer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferWriterDemo {
public static void main(String[] args) throws IOException {
//创建缓冲流对象
//BufferedReader和FileReader都是Reader的子类---同类
//同类对象给本类对象增强了功能---装饰者设计模式
BufferedWriter bw=new BufferedWriter(new FileWriter("F:\\1.txt"));
//写出数据
bw.write("abc");
//换行
//windows换行符:/r、/n
//Linux换行符:/n
bw.newLine();
bw.write("123");
//关流
bw.close();
}
}
解释一下装饰者模式:
模式:遇到统一问题时给出统一的解决方式
设计模式:在软件开发中,遇到同一问题给出统一的解决方案
装饰者模式:同类对象给本类对象增强(完善)功能
4.转换流
OutputStreamWriter—把字符流转成字节流
package cn.tedu.buffer;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
//转换流对象是由文件字节输出流对象来构建
//底层真正来进行传输数据的是文件字节输出流对象
//接收准备数据时用的是字符流,但是底层真正往外写出数据用的是字节流
//转换流---字符流转成字节流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\1.txt"));
//写出数据
//往外写出数据需要先准备数据
//事先需要准备数据都是字符形式的数据---需要提供一个字符流来操作数据
osw.write("你好");
//关流
osw.close();
}
}
InputStreamReader—把字节流转成字符流
package cn.tedu.buffer;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
//转换流的对象是由文件字节输入流对象来构建
//底层真正来读取数据的是文件字节输入流
//先根据文件字节输入流来读取数据
//再根据字符流来提供展示的数据
//转换流---字节流转成字符流
InputStreamReader isr=new InputStreamReader(new FileInputStream("F:\\1.txt"));
//读取数据
char[] cs=new char[10];//自建缓冲区
int len=-1;
//展示数据---字符形式数据
//展示的数据由字符流来接收
while ((len=isr.read(cs))!=-1){
System.out.println(new String(cs,0,len));
}
//关流
isr.close();
}
}
5.系统流:
out、err、in(都是字节流)
系统流都是静态的流对象,使用完毕之后不能关流
package cn.tedu.buffer;
import java.util.Scanner;
public class SystemDemo {
public static void main(String[] args) {
/* //输出正确结果(黑色)
//out---字节输出流对象
System.out.println(1);
//输出错误结果(红色)
//err---字节输出流对象
System.err.println(1);
//in---字节输入流对象
new Scanner(System.in);*/
Scanner sc1=new Scanner(System.in);
int num1=sc1.nextInt();
System.out.println(num1);
//关流
//in是静态流对象,如果关闭了其他地方都不能使用
sc1.close();
Scanner sc2=new Scanner(System.in);
int num2=sc2.nextInt();
System.out.println(num2);
}
}
6.打印流:
print方法以及println方法都是定义在打印流里
package cn.tedu.buffer;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamDemo {
public static void main(String[] args) throws IOException {
//创建打印流对象
PrintStream ps=new PrintStream("F:\\3.txt");
//写出数据
ps.print(22);
ps.println("abc");
ps.write("466".getBytes());
//关流
ps.close();
}
}
7.IO流中的异常捕获
1.在try块外声明流对象赋值为null,在try块里进行真正的初始化
2.保证流对象初始化成功之后才能进行关流
3.无论关流成功与否,流对象都要置为null让系统进行回收
4.如果关流操作失败发生在自动冲刷之前那么需要添加冲刷过程,保证数据不会滞留在缓冲区。
代码演示:
package
cn.tedu.io.file;
import
java.io.FileWriter;
import
java.io.IOException;
public class FileWriteDemo2 {
public static void main(String[] args) {
//声明IO流对象并且赋值为null
FileWriter writer=null;
try {
//流对象进行真正的初始化
writer =new FileWriter("D:2.txt");
//写出数据
writer.write("anc");
//4.手动冲刷
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//2.判断流对象是否初始化成功
if (writer!=null)
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
//无论关流是否成功都要把流对象置为null
}
}
}
}
练习:判断有多少个.java和class文件:
package cn.tedu.text;
import java.io.File;
public class FileText {
//计数变量
private static int countJava = 0;
private static int countClass = 0;
public static void main(String[] args) {
//创建代表文件类的对象
File file = new File("C:" + "\\Users\\Administrator.TEDU-20181205MG" + "\\IdeaProjects\\JAVASE2007");
//调用方法统计文件
countFiles(file);
System.out.println(".java文件:" + countJava + ".class文件:" + countClass);
}
//定义方法来统计文件个数
public static void countFiles(File file) {
//判断是否是文件夹
if (file.isDirectory()) {
//把当前文件夹下所有的信息展示
File[] fs = file.listFiles();
//遍历数组
for (File f : fs) {
//递归调用
countFiles(f);
}
} else if (file.getName().endsWith(".java")) {
countJava++;
} else if (file.getName().endsWith(".class")) {
countClass++;
}
}
}