I/O流概述
IO流(Input/Output)流,即是输入输出流,是java中实现输入输出的基础
,他可以方便的实现数据的输入和输出操作,他们有很多种,按照不同的分
类方式,可以分为以下三类。
1.字节流和字符流
字节流以字节为单位进行数据的读写,字符流则以字符为单位进行数据的读写。
2.输入流和输出流
按照流传输的方向的不同,又可以分为输入流和输出流。
3.节点流和处理流
按照流的功能的不同,可以分为节点流和处理流。其中节点流也被称为低级流,
它直接连接数据源,进行数据的读写。处理流也被称为高级流,它用于对一个
已存在的节点流进行连接和封装,通过封装后的流来实现流的读写能力。当使
用处理流时,程序不会直接连接实际的数据源,而是连接已存在的流之上。
大致的结构如图
一、字节流
1.InputStream
1.结构图
2.fileInputStream
代码
package com.hkd.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* FileInputStream例子
*/
public class Test1 {
public static void main(String[] args) {
File file=new File("D:\\博客\\test\\a.txt");
if (file.exists()){
try {
FileInputStream fileInputStream=new FileInputStream(file);
int b=0;
while ((b=fileInputStream.read())!=-1){
//一次读一个字节
//显示的是字符的ASCII值
System.out.println(b);
}
//记得关闭输入流
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.OutputStream
1.结构图
2.代码
package com.hkd.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
/**
* FileOutputStream例子
*/
public class Test2 {
public static void main(String[] args) {
File file=new File("D:\\博客\\test\\b.txt");
try {
FileOutputStream fileOutputStream=new FileOutputStream(file);
//定义一个字符串
String str="Hello World";
//因为write方法的传入参数是byte类型的数组,所有要通过String类的方法转换
fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
//关闭输出流
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.文件的拷贝
1.使用到输入流和输出流
2.代码
package com.hkd.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class Test3 {
public static void main(String[] args) {
try {
//创建文件输入流对象读取指定目录下的文件
FileInputStream in=new FileInputStream("D:\\博客\\test\\icon.png");
//创建文件输出流对象将读取到的文件内容写入到指定目录的文件下
FileOutputStream out=new FileOutputStream("D:\\博客\\test\\copy.png");
//定义一个int类型的变量len
int len=0;
//获取拷贝文件前的系统时间
long beginTime=System.currentTimeMillis();
//通过循环将读取到的文件字节信息写入到新文件
while((len=in.read())!=-1){
out.write(len);
}
//获得拷贝完成之后的系统时间
long endTime=System.currentTimeMillis();
//输出拷贝花费时间
System.out.println("花费时间为:"+(endTime-beginTime)+"毫秒");
//关闭流
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.字节流的缓冲区
1.目的:上面虽然实现了文件的拷贝,但是由于是一个一个字节的拷贝,频繁的操作文件导致这样的效率是很低的,为了解决这一个问题,我们有了字节流缓冲区,一次读入多个字节,每个字节数组即是缓冲区。
2.代码
package com.hkd.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 字节缓冲流
*/
public class Test4 {
public static void main(String[] args) throws Exception {
//创建文件输入流对象读取指定目录下的文件
FileInputStream in=new FileInputStream("D:\\博客\\test\\icon.png");
//创建文件输出流对象将读取到的文件内容写入到指定目录下的文件中(注 若该输出文件不存在,则会直接创建)
FileOutputStream out=new FileOutputStream("D:\\博客\\test\\copy1.png");
//定义一个int类型的变量len
int len=0;
//定义一个长度为1024d的字节数组
byte [] buff=new byte[1024];
//获取拷贝之前的系统时间
long beginTime=System.currentTimeMillis();
while ((len=in.read(buff))!=-1){
out.write(buff,0,len);
}
//获取拷贝之后的系统时间
long endTime=System.currentTimeMillis();
//输出打印时间
System.out.println("你复制这个文件花费了"+(endTime-beginTime)+"毫秒");
//关闭流
in.close();
out.close();
}
}
5.字节缓冲流
1.例子
package com.hkd.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 字节缓冲流
*/
public class Test8 {
public static void main(String[] args) throws Exception {
//创建用于输入和输出的字节缓冲流对象
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("D:\\博客\\test\\icon.png"));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\博客\\test\\copy4.png"));
//定义一个int类型的变量len
int len=0;
//获取拷贝文件前的系统时间
long beginTime=System.currentTimeMillis();
//通过循环读取输入字节缓冲流的数据,并通过输出字节缓冲流写入到新文件中
while ((len=bis.read())!=-1){
bos.write(len);
}
//获取拷贝完成之后的系统时间
long endTime=System.currentTimeMillis();
//输出拷贝花费的时间
System.out.println("花费时间为:"+(endTime-beginTime)+"毫秒");
//关闭流
bis.close();
bos.close();
}
}
二、字符流
1.FileReader
1.例子
package com.hkd.io;
import java.io.FileReader;
/**
* FileReader例子
*/
public class Test5 {
public static void main(String[] args) throws Exception {
//创建FileReader字符输入流对象
FileReader reader=new FileReader("D:\\博客\\test\\a.txt");
//定义一个int类型的变量len
int len=0;
//通过循环判断是否到达文件的末尾
while ((len=reader.read())!=-1){
//输出字符
System.out.println((char) len);
}
//关闭流对象
reader.close();
}
}
2.FileWriter
1.例子
package com.hkd.io;
import java.io.FileWriter;
/**
* 字符输出流例子
*/
public class Test6 {
public static void main(String[] args) throws Exception{
//创建字符输出流对象,并指定输出文件
//默认第二个参数是false 覆盖,true代表是追加
FileWriter writer=new FileWriter("D:\\博客\\test\\d.txt");
//将定义的字符写入文件
writer.write("世界\r\n");
writer.write("你好\r\n");
//关闭流
writer.close();
}
}
3.文件的拷贝
1.例子
package com.hkd.io;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 通过字符流缓冲区实现文件的拷贝
*/
public class Test7 {
public static void main(String[] args) throws Exception {
//创建字符输入流对象
FileReader reader=new FileReader("D:\\博客\\test\\a.txt");
//创建字符输出流对象
FileWriter writer=new FileWriter("D:\\博客\\test\\e.txt");
//获得当前系统时间
long beginTime=System.currentTimeMillis();
//定义int类型的len变量
int len=0;
//使用循环判断是否到达文件的末尾
while((len=reader.read())!=-1){
writer.write(len);
}
//获得复制结束系统时间
long endTime=System.currentTimeMillis();
//输出打印时间
System.out.println("复制这个txt文件你花费了"+(endTime-beginTime)+"毫秒");
//关闭流对象
reader.close();
writer.close();
}
}
4.字符流的缓冲区
1.除了上述字符流文件拷贝的缓冲区方法,字符流还自带了缓冲区方法--
例子如下
package com.hkd.io;
import java.io.FileReader;
import java.io.FileWriter;
/**
*
*/
public class Test9 {
public static void main(String[] args) throws Exception {
//创建字符输入流对象
FileReader reader=new FileReader("D:\\博客\\test\\a.txt");
//创建字符输出流对象
FileWriter writer=new FileWriter("D:\\博客\\test\\f.txt");
//获得当前系统时间
long beginTime=System.currentTimeMillis();
//定义int类型的len变量
int len=0;
//定义一个长度为1024的字符数组
char [] buff=new char[1024];
//使用循环判断是否到达文件的末尾
while((len=reader.read(buff))!=-1){
writer.write(buff,0,len);
}
//获得复制结束系统时间
long endTime=System.currentTimeMillis();
//输出打印时间
System.out.println("复制这个txt文件你花费了"+(endTime-beginTime)+"毫秒");
//关闭流对象
reader.close();
writer.close();
}
}
5.字节缓冲流
1.例子如下
package com.hkd.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 字符缓冲流
*/
public class Test10 {
public static void main(String[] args) throws Exception {
//创建一个字符输入缓冲流对象
BufferedReader br=new BufferedReader(new FileReader("D:\\博客\\test\\a.txt"));
//创建一个字符输出缓冲流对象
BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\博客\\test\\f.txt"));
//声明一个字符串变量
String str=null;
//循环时每次读取一行文本,如果不为null(即到了文件的末尾),则继续循环
while ((str=br.readLine())!=null){
bw.write(str);
//写入一个换行符
bw.newLine();
}
//关闭流
br.close();
bw.close();
}
}
三、转换流
1.转换流的意义:有时字节流和字符流需要进行转换,在JDK中,提供了两个类用于实现
将字节流转换为字符流,他们分别是InputStreamReader和OutputStreamWriter。
2.大致的转换结构如图
3.例子如下
package com.hkd.io;
import java.io.*;
/**
* 转换流例子
*/
public class Test11 {
public static void main(String[] args) throws Exception {
//1.创建字节输入流对象,获取源文件
FileInputStream in=new FileInputStream("D:\\博客\\test\\a.txt");
//将字节输入流转换为字符输入流对象
InputStreamReader isr=new InputStreamReader(in);
//创建字符输入缓冲流对象
BufferedReader br=new BufferedReader(isr);
//2.创建字节输出流对象,指定目标文件
FileOutputStream out=new FileOutputStream("D:\\博客\\test\\g.txt");
//将字节输出流对象转换为字符输出流对象
OutputStreamWriter osw=new OutputStreamWriter(out);
//创建字符输出缓冲流对象
BufferedWriter bw=new BufferedWriter(osw);
//定义一个字符串变量
String strLine=null;
//通过循环判读是否到达文件的末尾
while ((strLine=br.readLine())!=null){
bw.write(strLine);
//写入换行符
bw.newLine();
}
//关闭流对象
br.close();
bw.close();
}
}
四、字节流和字符流的使用环境
1.字节流的使用环境:
照片等文件
2.字符流的使用环境:
最常见的应用场景是:程序的配置文件,不管是json,yaml,properties,
读取这些文件时,你肯定不想拿到一堆字节,来处理字符转换和编码问题。
五、为什么用字符流复制的图片打不开,而用字节流复制的却可以打开?
这是编码、解码的问题:
字符流按字符读数据:一次读两个字节,返回了这两个字节所对应的字符的int型数值(编码)。
写入文件时把这两个字节的内容解码成这个字符在Unicode码下对应的二进制数据写入。
即把原始文件中的二进制数据以字符形式读出,再将字符以二进制形式写入,所以得到的文件以字符方式存储。而图片的数据是按字节存储的,所以打开图片时解码出错了!
字节流按字节读数据:而字节不需要编码、解码,只有字节与字符之间转换时才需要编码、解码!所以可以正常读取图片数据。
所以,非纯文本不要用字符流。
————————————————
版权声明:本文为CSDN博主「山淼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43229056/article/details/106137920