Java基础---认识IO流---字节流、字符流---缓冲流---转换流

一、认识IO流

I/O就是用于设备之间进行数据交互的对象所属的类型
IO流的体系结构:根据分类,有四种流对象类型
字节流:可以直接操作字节信息的流对象
字节输入流:InputStream
字节输出流:OutputStream
字符流:
字符输入流:Reader
字符输出流:Writer

二、字节流

InputeStream

1、字节输入流的顶层父类
2、常用方法:
int read() :
从当前的字节输入流中,读取并返回一个字节,返回-1表示未读取到。
int read(byte[] arr):
将最多arr.length个字节,读取到arr数组中返回读取的字节个数,-1表示未读取到
int available()
返回流中剩余可以读取的字节个数
void close() 关闭流对象
3、InputStream是一个抽象类,不能直接创建对象,只能由子类创建对象

FileInputStream

1、InputSteam的一个具体子类,用于和磁盘上的文件进行交互
2、FileInputStream,不仅一次可以读取一个字节,也可以一次读取多个字节,也可以读取图片,音乐,视频,等一些非纯文本文件。
3、构造方法:
FileInputStream(String Path):将字符串(文件路径)封装成字节输入流,不能是一个目录
FileInputStream(File f):将file对象封装成字节输入流
注意:无论是哪个构造方法,都只能封装的是文件的路径,封装文件夹路径是没有任何意义的,文件夹本身没有任何数据 的,如果指定文件不存在,或者它是一个目录,而不是一个常规文件,否则抛出 FileNotFoundException

OutputStream

1、字节输出流的顶层抽象父类
2、常用方法:
void write(int b);将一个字节信息写出到指定的设备中
void write(byte[] arr):将一个字节数组所有信息,写出到指定的设备中
void write(byte[] arr,int offset,int len);将一个字节数组的部分信息,写出到指定的设备中
将数组arr中从索引offset开始,总字节数为len个字节信息写出到指定设备中
void close();
3、抽象类

FileOutputStream

1、可以将字节数据写出到指定设备中
2、构造方法
FileOutputStream(File f):将f描述的文件路径封装成一个字节输出流对象
FileOutputStream(String name):将抽象路径字符串name封装成一个字节输出流对象
使用字节输出流的时候,写出数据,写入到指定的设备中
3、注意:
使用流写出到磁盘上,存储的数字,既没有编码,也没有解码,如果使用编辑器打开这些文件的时候,编辑器,读取数据,根据编码表,进行解码,看到就是解码后的内容

package com.DaYu;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

public class Demo01 {
	public static void main(String[] args) throws IOException {
//		构造方法
		FileInputStream fis = new FileInputStream("a.txt");
		
//		File f = new File("a.txt");
//		FileInputStream fis1 = new FileInputStream(f);
		
		FileOutputStream fos = new FileOutputStream("b.txt");
//		
//		File f = new File("c.txt");
//		FileOutputStream fos1 = new FileOutputStream(f);
		
//		read(byte[] arr)方法
			byte[] bytes = new byte[3];
			int len = fis.read(bytes);
			System.out.println(Arrays.toString(bytes));
			System.out.println(len);
			System.out.println(fis.available());
		int i = 0;
//		read()方法
		while((i = fis.read())!=-1) {
			System.out.println(i);
		}
		
//		write()方法		
			fos.write(98);// 写一个字节
			byte[] bytes1 = { 99, 100, 101, 102, 103 };
			fos.write(bytes);
			fos.write(bytes1, 1, 4);
//		关闭资源
			fis.close();
			fos.close();	
	}
}

文件拷贝(复制)

1、含义:
将一个文件中的数据,拷贝到指定的文件中
2、本质上就是将原文件中的信息,读取到内存中,将内存中的数据,写出到指定的位置(文件)

public static void main(String[] args) throws IOException {
//		创建字节输入流对象
		FileInputStream fis = new FileInputStream("a.txt");
//		创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("b.txt");

//		使用字节输入流,读取磁盘中文件的数据
		int i;
//		使用while循环读取文件中的每一个字节
		while ((i = fis.read()) != -1) {
//			将读到的字节信息,通过字节输出流,写出到指定的文件中
			fos.write(i);
		}
//		关闭流
		fis.close();
		fos.close();
}

文件拷贝效率的提升

利用read(byte[] arr)和write(byte[] bytes)创建数组进行读写,数组的大小是可以进行任意的选择,数组越大,拷贝的次数少,效率高,一般情况,数组的大小使用1024的整数倍。

	public static void many2many_2() throws IOException {
//		创建字节输入流对象
		FileInputStream fis = new FileInputStream("a.txt");
//		创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("b.txt");

//		创建一个数组
		byte[] arr = new byte[100];
		int len;
		while ((len = fis.read(arr)) != -1) {
//			将读到的数据写出到指定文件中
			fos.write(arr,0,len);
		}
//		关闭流
		fis.close();
		fos.close();
	}

高效缓冲流

1、BufferedInputStream和BufferedOutputStream
2、高效缓冲流对FileInputStream,FileOutputStream进行加强,底层创建一个数组(容量为8192个字节)进行缓冲,不需要频繁访问磁盘,提高了效率。
3、构造方法
BufferedInputStream(InputStream in) :将指定的具体的输入流对象传入到构造方法中,形成了一个带有缓冲区的高效流
BufferedOutputStream(OutputStream os):将指定的具体的字节输出流对象传入到构造方法中,形成了一个带有缓冲区的高效输出流

public class Demo02 {
//高效缓冲流使用的注意事项
	public static void main(String[] args) throws Exception {
		FileInputStream fis = new FileInputStream("a.txt");
//		高效输入流对象
		BufferedInputStream bis = new BufferedInputStream(fis);
		
		FileOutputStream fos = new FileOutputStream("aaBuff.txt");
//		高效的输出流对象
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		int i ;
		while((i = bis.read()) != -1) {
			bos.write(i);
		}
//		 使用缓冲流要注意关流
		bis.close();
		bos.close();
	}
}

输出流中的close方法和flush方法

1、close方法会先调用flush()
2、close方法用于流对象的关闭,一旦调用了close方法,那么这个流对象就不能再使用了
3、flush只是将缓冲区中的数据刷新到指定文件中,而不会将流对象关闭,可以继续使用流对象
如果flush这个方法使用的过于频繁,就丧失了缓冲区的作用

三、字符流

1、抽象父类Reader Writer
2、Reader:
read():读取一个字符,返回值如果是-1,表示到文件的末尾
read(char[] chs):将一堆字符读入到指定的chs字符数组中
Writer:
writer(int c): 写出一个字符
writer(char[] chs):写出一个字符数组
writer(char[] chs,int offset,int len):将字符数组的一部分写出到指定的文件中
writer(String str):将一个字符串写出到指定文件中
3、对于抽象类而言,也是不能直接创建对象的,需要使用具体的类型来进行创建
FileReader,FileWriter

public class Demo03 {
	public static void main(String[] args) throws Exception {
		FileReader fr = new FileReader("F:/test/b.txt");
		char[] chs = new char[3];
		int len = fr.read(chs);
		System.out.println(chs);

		FileWriter fw = new FileWriter("F:/test/c.txt");
		char[] chs1 = { 's', 'o', 's' };
		fw.write(30000);
		fw.write(chs1);
		fw.write(chs1, 0, 2);
		fw.write("中文");
		fr.close();
		fw.close();
	}
}

字符流的小数组拷贝

1、使用FileReader read(byte[] arr)方法将多个字符读入到数组中,返回的值表示的是有效字符的个数,如果返回-1 表示读取到了文件的末尾
2、使用FileWriter中的write(byte[] arr)(使用该方法进行拷贝,会出现最后一次的数组中会遗留上一次的字符)和write(byte[] arr,int offset,int len),将读到的字符写出到指定的位置
3、说明:
FileWriter中也是带有一个缓冲区的,大小8192
要记得关流

public static void main(String[] args) throws IOException {
//		字符小数组进行拷贝
		FileReader fr = new FileReader("a.txt");
		FileWriter fw = new FileWriter("acopy.txt");
//		创建一个字符数组
		char[] chs = new char[4];
		int len;
		while ((len = fr.read(chs)) != -1) {
//			 将读到的字符写出到指定文件中
			fw.write(chs,0,len);
		}
//		不要忘记关流
		fr.close();
		fw.close();
	}

使用字符流进行拷贝的注意点

1、没有必要使用字符流来进行拷贝,因为字符流会先将字节信息转成字符,读取到内存中,最后还要将这些字符信息转成字节信息,写出到另一个文件中去,中间做了两次没有意义的操作,浪费时间。
2、如果在读到字符之后,需要人为的阅读和修改这个字符,那么就需要使用字符流。
3、字符流只能拷贝纯文本文件,不能操作非纯文本文件。

高效的缓冲字符流

1、riteBufferedReader:
readLine();可以从输入流中,一次读取一行数据,返回一个字符串,如果到达文件末尾,则返回null
2、BufferedWriter:
newLine();换行,在不同的操作系统中,换行符各不相同,newLine()方法就是可以给我们根据操作系统的不同,提供不同的换行符

public static void main(String[] args) throws IOException {
//		创建字符输入流
		FileReader fr = new FileReader("a.txt");
//		创建字符输出流
		FileWriter fw = new FileWriter("aac.txt");

//		进行包装
		BufferedReader br = new BufferedReader(fr);
		BufferedWriter bw = new BufferedWriter(fw);

		String str;
		while ((str = br.readLine()) != null) {
			bw.write(str);
			bw.newLine();
		}
		br.close();
		bw.close();
	}

四、转换流

1、OutputStreamWriter:是字符流通向字节流的桥梁,可以指定编码形式
构造方法:OutputStreamWriter(OutputStream out, String charsetName)
创建一个转换流的对象,可以把将来方法中接收到的字符串,通过指定的编码charsetName,编码成字节信息,再通过字节流,进行写出
使用:直接使用writer中的方法即可
2、InputStreamReader:字节流到字符流的桥梁,可以指定编码格式
构造方法:InputStreamReader(InputStream in, String charsetName)
创建一个转换流对象,可以使用in这个字节输入流从磁盘中读取字节信息,通过指定的编码格式,将字节信息转成相对 应的字符,返回给调用者
使用:直接使用Reader中的方法即可
3、说明;
无论是读取的时候还是写出的时候,都要参考读取文件和写出文件的编码形式
读取源文件时,解码的形式必须和源文件的编码形式一致
写出到目标源文件时,编码形式必须和目标文件的编码形式一致

public static void main(String[] args) throws IOException {
//		子节流到字符流的桥梁
		InputStream fis = new FileInputStream("b.txt");
//		能够按照指定的编码  格式去读取相应的字节数
		InputStreamReader isr = new InputStreamReader(fis, "utf-8");

		FileWriter fw = new FileWriter("isr.txt");
		int i;
		while ((i = isr.read()) != -1) {
			fw.write(i);
		}
		fis.close();
		fw.close();
	}

	private static void OutputStreamWriters() throws FileNotFoundException, UnsupportedEncodingException, IOException {
		// 从一个文件中获取字符信息使用字符流
		FileReader fr = new FileReader("a.txt");
		// 创建一个字符流到字节流的对象(转换流)
		OutputStream os = new FileOutputStream("b.txt");
		OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
        
		int i;
		while ((i = fr.read()) != -1) {
			osw.write(i);
		}
		fr.close();
		osw.close();
}

猜你喜欢

转载自blog.csdn.net/qq_41401295/article/details/106556107