IO流原理
一、流的分类
- 操作数据单位:字节流、字符流
- 数据流向:输入流、输出流
- 流的角色:字节流、处理流
二、流的体系结构
抽象基类 | 节点流(或文件流) | 缓冲流(处理流的一种) |
---|---|---|
InputStream | FileInputStream | BufferedInputStream |
OutputStream | FileOutputStream | BufferedOutputStream |
Reader | FileReader | BufferedReader |
Writer | FileWriter | BufferedWriter |
三、具体代码分析
3.1 FileReader字符流的使用
3.1.1 read的简单使用
public class FileReaderWriterTest {
@Test
public void testFileReader() {
//1、实例化File类的对象,指明要操作的文件
File file=new File("hello");
//2、提供具体的流
FileReader fr= null;
try {
fr = new FileReader(file);
//数据的读入
//read():返回读入的字符。如果到达文件的末尾则返回-1;
int data;
while((data=fr.read())!=-1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//流的关闭
try {
//当fr = new FileReader(file);出现异常时,可能会导致没有造好对象,有可能导致空指针
if(fr!=null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.1.2 总结说明
- read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
- 异常处理:为了保证资源一定可以执行关闭操作,需要使用try-catch-finally处理。
- 读入的文件一定要存在,否则会报FileNotFoundException异常。
3.1.3 read的重载方法
public class FileReaderWriterTest {
@Test
public void testFileReader1(){
//1、File类的实例化
File file=new File("hello");
//2、FileReader流的实例化
FileReader fr=null;
try {
fr=new FileReader(file);
//3、读入操作
//read(char[] tmp):返回每次读入tmp数组中的字符的个数。如果达到文件末尾返回-1.
char [] tmp=new char[5];
int len;
while((len=fr.read(tmp))!=-1){
//方式一:
//错误写法
// for (int i = 0; i <tmp.length ; i++) {
// System.out.print(tmp[i]);
// }
//正确写法
// for (int i = 0; i <len ; i++) {
// System.out.print(tmp[i]);
// }
//方式二:
//错误写法
// String str=new String(tmp);
// System.out.print(str);
//正确写法
String str=new String(tmp,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//3、资源的关闭
if(fr!=null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2 FileWriter字符流的使用
3.2.1 writer方法的使用
public class FileReaderWriterTest {
@Test
public void testFileWriter() {
//1、提供File类的对象,指明写出到的文件
File file=new File("helloworld");
FileWriter fw=null;
try {
//2、提供FileWriter的对象,用于数据的写出
fw=new FileWriter(file);
//3、写出
fw.write("I have a dream!\n");
fw.write("you need to have a dream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、流的关闭
try {
if(fw!=null){
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2.2 总结说明
- 输出操作对应文件可以不存在,并不会报异常
- File对应的硬盘中的文件如果存在:
- 如果使用构造器:FileWriter(file,false)/FileWriter(file):对原有文件进行覆盖
- 如果使用构造器:FileWriter(file,true):不会对原有文件进行覆盖,而是在原有文件基础上追加内容。
3.3 文件的复制操作
3.3.1 代码实现
- FileReader和FileWriter
public class FileReaderWriterTest {
@Test
public void testFileReaderWriter() {
//1、创建File类的对象,指明读入和写出的文件
File srcFile=new File("helloworld");
File desFile=new File("hello1");
FileReader fr= null;
FileWriter fw= null;
try {
//2、创建输入和输出流对象
fr = new FileReader(srcFile);
fw = new FileWriter(desFile);
//3、数据的读入和写出操作
char [] cbuf=new char[5];
int len;
while((len=fr.read(cbuf))!=-1){
fw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//4、关闭流资源
if(fw!=null){
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fr!=null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.3.2 总结说明
- 相当于是对一个文件进行复制
- 不能去操作图片等字节数据
3.4 FileInputStream的使用
-
字节流
-
代码实现
public class FileInputOutputStreamTest {
@Test
public void teatFileInputStream() {
//1、创建文件
File file=new File("hello");
FileInputStream fis= null;
try {
//2、创建输入流
fis = new FileInputStream(file);
//3、读入数据
byte[] buffer=new byte[5];
int len;//记录每次读取的字节的个数
while((len=fis.read(buffer))!=-1){
String str=new String(buffer,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fis!=null){
//4、关闭资源
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.5 图片复制
- FileOutputStream
public class FileInputOutputStreamTest {
//实现对图片的复制操作
@Test
public void testFileInputOutputStream() {
//创建文件
File srcFile=new File("1000610.jpg");//源路径
File desFile=new File("2.jpg");//目的路径
FileInputStream fis= null;
FileOutputStream fos= null;
try {
//创建流
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(desFile);
//复制的过程
byte[] buffer=new byte[5];
int len;
while((len=fis.read(buffer))!=-1){
fos.write(buffer,0,len);
}
System.out.println("复制成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fos!=null){
//关闭流
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.6 总结
- 对于文本文件(.txt .java .c .cpp…),使用字符流处理。
- 对于非文本文件(.jpg .mp3 .mp4 .avi .doc .ppt …)使用字节流处理。
- 步骤:
- 创建文件
- 创建流
- 读或写数据
- 关闭流
四、流的转换
4.1 处理流到缓冲流
4.1.1 概述
- 缓冲流在内部提供了一个缓冲区,会提高读写速率
- 处理流,就是“套接”在已有流之上
4.1.2 具体分类
- BufferedInputStream(字节流)
- BufferedOutputStream(字节流)
- BufferedReader(字符流)
- BufferedWriter(字符流)
4.1.3 代码实现
- 字节流
public class BufferedTest {
@Test
public void BufferedStreamTest() {
BufferedInputStream bis= null;
BufferedOutputStream bos= null;
try {
//1、造文件
File srcFile=new File("2.jpg");
File desFile=new File("3.jpg");
//2、造流
//2.1 造节点流
FileInputStream fis=new FileInputStream(srcFile);
FileOutputStream fos=new FileOutputStream(desFile);
//2.2 造缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3、复制的细节:读取、写入
byte[] buffer=new byte[10];
int len;
while((len=bis.read(buffer))!=-1){
bos.write(buffer,0,len);
// bos.flush();//刷新缓冲区
}
System.out.println("复制成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、资源关闭
//先关闭外层,后关闭内层
try {
if(bis!=null){
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bos!=null){
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//说明:在关闭外层流的同时,内层流会自动关闭。
// fis.close();
// fos.close();
}
}
- 字符流
public class BufferedTest {
/**
* 使用BufferedReader和BufferedWriter实现对文本文件的复制
*/
}
@Test
public void testBufferedReaderBufferedWriter2(){
BufferedReader bf = null;
BufferedWriter bw= null;
try {
//1、创建文件和相应的流
bf = new BufferedReader(new FileReader(new File("hello")));
bw = new BufferedWriter(new FileWriter(new File("hello3")));
//2、读写操作
//方式一:
char[] buffer=new char[10];
int len;
while((len=bf.read(buffer))!=-1){
bw.write(buffer,0,len);
}
//方式二:readLine():一次读一行
String data;
while((data=bf.readLine())!=null){
//方法一:
// bw.write(data);//data中不包含换行符
//方法二:
bw.write(data);
bw.newLine();//提供换行操作
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//3、关闭资源
if(bf!=null){
bf.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bw!=null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.2 处理流到转换流
4.2.1 概述
转换流属于字符流,将一个字节的输入流转换为字符的书输入流,将一个字符的输出流转换为字节的输出流。
4.2.2 具体分类
- InputStreamReader:将一个字节的输入流转换为字符的输出流
- OutputStreamWriter:将一个字符的输出流转换为字节的输出流
4.2.3 代码实现
- InputStreamReader的使用
public class InputStreamReaderTest {
@Test
public void test1() {
InputStreamReader isr= null;
try {
FileInputStream fis=new FileInputStream("hello1");
isr = new InputStreamReader(fis,"UTF-8");//默认为文件保存时的字符集
char [] cbuf=new char[5];
int len;
while((len=isr.read(cbuf))!=-1){
String str=new String(cbuf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(isr!=null){
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 综合使用InputStreamReader和OutputStreamWriter
public class InputStreamReaderTest {
@Test
public void teat2(){
//1、造文件、造流
File file1=new File("hello1");
File file2=new File("hello_gbk");
InputStreamReader isr= null;
OutputStreamWriter osw= null;
try {
FileInputStream fis=new FileInputStream(file1);
FileOutputStream fos=new FileOutputStream(file2);
isr = new InputStreamReader(fis,"utf-8");
osw = new OutputStreamWriter(fos,"gbk");
//2、读写过程
char[] cbuf=new char[5];
int len;
while((len=isr.read(cbuf))!=-1){
osw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3、资源关闭
try {
if(isr!=null){
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(osw!=null){
osw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.3 其他流
4.3.1 标椎的输入输出流
- System.in:标准的输入流,默认从键盘输入
- System.out:标准的输出流,默认从控制台输出
- System类的setIn()/setOut()方式重新指定输入和输出流
4.3.2 代码实现
public class OtherStreamTest {
public static void main(String[] args) {
test1();
}
public static void test1() {
BufferedReader br = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
br = new BufferedReader(isr);
while (true) {
System.out.println("请输入字符串:");
String data = br.readLine();
if (data.equalsIgnoreCase("e") || data.equalsIgnoreCase("exit")) {
System.out.println("程序退出!");
break;
}
String upperCase = data.toUpperCase();
System.out.println(upperCase);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}