首先我们需要知道什么是流?
流就是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。它的特性是进行数据传输。
接下来我们看看IO流的分类:
- 按流向分类:输入流、输出流
- 按操作对象分类:字节流、字符流
- 按功能分类:节点流、处理流
前方高能,坐下来请慢慢地听我说!
一:字节流和字符流
字节流:InputStream 和OutputStream 是java中可以按照最小字节单位读取的流,即每次读写一个字节,字节流是直接连接到输入源的流。
字符流:是以字符为单位进行数据处理的IO流。本质其实就是基于字节流读取时,去查找指定的码表。
二:字节流与字符流之间的区别:
- 读写单位不同:字节流式以字节(8位2进制)为单位,字符流是以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
- 一次读入或读出是8位二进制。
- 字符流:一次读入或读出是16位二进制。
结论:
Out—>将输出的字符流—>字节流—>用于输出到控制台 或者 文件
注意这个是写====输出的是来源,形容词,不是你理解的字符输出流转字节输出流
In—>将输入的字节流—>字符流—>用于读取到控制台 或 内存
注意这个是读====输入的是来源,形容词,不是你理解的字节输入流转字符输入流
要么字节流要么字符流,具体再分哪种来源的流的话,就看是In还是Out了
- InputStreamReader看似是往里写(In),其实是往外读(Reader)
- OutputStreamWriter看似是往外读(Out),其实是往里写(Writer)
三:输入流和输出流的用途:
- 输入流是指程序从数据源中读取数据。只进行读操作;
- 输出流是指将数据从程序中写到指定的文件中;
四:输入流字节流InputStream与输出字节流InputStream
- InputStream是一个抽象类,是所有输入字节流的父类。
- ByteArrayInputStream、StringBufferInputStream、FileInputStream
他们分别从数组、StringBuffer、和本地文件中读取数据。 - PipedInputStream是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
- ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
- OutputStream 是所有的输出字节流的父类,它是一个抽象类。
- ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte数组、和本地文件中写入数据。
- PipedOutputStream 是向与其它线程共用的管道中写入数据。
- ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
上代码理解一下,此代码使用缓冲数组的方法读取文件内容,提高效率
public static void readArr() {
// 1、明确源数据源
File f = new File("F:/1/菜丸子/1.txt");
// 2、构建流的对象
InputStream ins = null;
try {
ins = new FileInputStream(f);
// 3、声明缓冲数组
int i;// 表示读取了多少个字符到数组中
byte[] bt = new byte[5];// 字节缓冲数组
// 4、读取数据到数组中
//可以读多少写多少,转化成char类型,但是文件中都是英文,如果有中文则输出乱码
while ((i = (ins.read(bt))) != -1) {
for (int j = 0; j < i; j++) {
System.out.print((char) bt[j]);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
五:节点流和处理流的概念
节点流:直接与数据相连,进行数据的读写;
处理流:是指在节点流上套接了一层。
- 常用的节点流
1.文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
import java.io.FileReader;
import java.io.FileWriter;
/**
* 使用FileRead、FileWriter复制文件
*
* @author caiwan
*
*/
public class TestFieldWriter {
public static void main(String []args){
FileReader fr=null;
FileWriter fw=null;
try {
fr=new FileReader("C:\\Users\\116060\\Desktop\\eeee.txt");//要读取的文件
fw=new FileWriter("C:\\Users\\116060\\Desktop\\ffff.txt");//要复制的目的文件
int i=0;
while((i=fr.read())!=-1){
fw.write(i);
System.out.println((char)i);//将得到的ASCII码值转换成字符型
}
fr.close();
fw.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
2.数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
3.字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
4.管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
- 常用的处理流
1.缓冲流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
/**
* 字符缓冲流(使用 BufferedReader 和 BufferedWriter)
*
* @author caiwan
*
*/
public class Demo2 {
public static void main(String[] args) {
// 1、指明源和目标
File o = new File("F:/temp/java11.template");
File t = new File("F:/temp/java11.txt");
// 2、构建流的对象
Reader re = null;
Writer wt = null;
BufferedReader bfr = null;
BufferedWriter bfw = null;
try {
re = new FileReader(o);
bfr = new BufferedReader(re);
wt = new FileWriter(t);
bfw = new BufferedWriter(wt);
String msg = null;
// 读取操作
while ((msg = bfr.readLine()) != null) {// 读一行
// System.out.println(msg);
bfw.write(msg);
bfw.write("\r\n");// 执行换行,读一行 写一行 换行
// 或者 :bfw.newLine();//换行
}
bfw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (wt != null) {// 为了避免空指针异常,进行判空
wt.close();
}
if (re != null) {
re.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
3.数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。
六:转换流
InputStreamReader 、OutputStreamWriter 要InputStream或OutputStream作为参数,实现从字节流到字符流的转换。
七:常用例子
包装流设置字符集的案例:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Scanner;
/**
* 包装流设置字符集,使用InputStreamReader 和 OUtputStreamWriter:
* @author caiwan
*/
public class Demo01 {
public static void main(String[] args) {
// 确定源和目标文件
Scanner sc = new Scanner(System.in);
File o = new File("kh/java48.template");
File t = new File("kh/java48.txt");
check(o);
check(t);
// 构建流对象
InputStream ins = null;
OutputStream outs = null;
InputStreamReader insr = null;
OutputStreamWriter outsw = null;
try {
outs = new FileOutputStream(o);// 先做为目标文件写入内容
outsw = new OutputStreamWriter(outs, "UTF-8");//编码格式为UTF-8
System.out.println("输入你要写入的内容:");
String msg = sc.next();
// 写入内容
outsw.write(msg);
// 刷新
outsw.flush();
System.out.println("已经完全写入!");
ins = new FileInputStream(o);// 作为源文件
insr = new InputStreamReader(ins, "UTF-8");//编码格式为UTF-8
outs = new FileOutputStream(t);// 作为写入的目标文件
outsw = new OutputStreamWriter(outs, "UTF-8");//编码格式为UTF-8
char[] ch = new char[1024];
int i = 0;
// 执行边读边写
while ((i = insr.read(ch)) != -1) {
outsw.write(ch, 0, i);
}
// 刷新
outsw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (outs != null) {
outs.close();
}
if (ins != null) {
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void check(File file) {
try {
if (!file.exists()) {
file.getParentFile().mkdirs();// 创建文件夹
file.createNewFile();// 创建文件
System.out.println("没有该文件!已创建成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后:
欢迎各位小伙伴关注我的公众号:菜丸的程序屋。希望将我的不足之处给予指点,谢谢大家。喜欢Java,热衷学习的小伙伴可以加我微信: CaiWan_Y