Java BIO是面向流的IO,所有的操作都是基于流的。对于字节和字符,有对应的字节流和字符流。也有对字节和字符进行转换的转换流,还有提升效率的缓冲流。对于流的方向,还有输入流和输出流。
1. 字节流和字符流
1.1 字节和字符
简单的说,字节是给计算机看的,字符是给人看的。字节(Byte)是表示计算机存储容量的计量单位。而字符是字节经过编码之后,便于人理解的一种符号。比如我们常用的编码规则(编码表)有UTF-8、GB2312、GBK等等。
1.2字节流
- 字节输入流 InputStream 抽象类
- FileInputStream 操作文件的字节输入流
- BufferedInputStream高效的字节输入流
- 字节输出流 OuputStream抽象类
- FileOutputStream 操作文件的字节输出流
- BufferedOutputStream 高效的字节输出流
下面是一些使用案例
public class FileOutputStreamDemo {
public static void main(String[] args) {
File file = new File(path);
//定义FileOutputStream的引用
FileOutputStream fos = null;
try {
//创建FileOutputStream对象,选择续写模式
fos = new FileOutputStream(file, true);
//写出数据,加入换行
fos.write("abcde/r/n".getBytes());
} catch (IOException e) {
System.out.println(e.toString() + "----");
} finally {
//一定要判断fos是否为null,只有不为null时,才可以关闭资源
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException("");
}
}
}
}
}
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File(path);
// 创建一个字节输入流对象,明确数据源。
FileInputStream fis = new FileInputStream(file);
//创建一个字节数组,长度可以定义成1024的整数倍。
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fis.close();
}
}
public class CopyFileByBufferTest {
public static void main(String[] args) throws IOException {
File srcFile = new File(srcpath);
File destFile = new File(destpath);
// 明确字节流和数据源相关联,输出流和目的源关联。
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//缓冲区
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
// 将数组中的指定长度的数据写入到输出流中。
fos.write(buf, 0, len);
}
// 关闭资源。
fos.close();
fis.close();
}
}
1.3 字符流
- 字符输入流 Reader抽象类
- InputStreamReader 输入操作的转换流(把字节流封装成字符流)
- FileReader 用来操作文件的字符输入流(简便的流)
- BufferedReader 高效的字符输入流
- 字符输出流 Writer抽象类
- OutputStreamWriter 输出操作的转换流(把字节流封装成字符流)
- FileWriter 用来操作文件的字符输出流(简便的流)
- BufferedWriter 高效的字符输出流
/*
* 字符流复制文本文件,必须是文本文件
* 字符流查询本机默认的编码表
* FileReader读取数据源
* FileWriter写入到数据目的
*/
public class Copy {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader(srcpath);
fw = new FileWriter(destpath);
char[] cbuf = new char[1024];
int len = 0 ;
while(( len = fr.read(cbuf))!=-1){
fw.write(cbuf, 0, len);
// 注意要调用flush()函数进行刷新
fw.flush();
}
}catch(IOException ex){
System.out.println(ex);
throw new RuntimeException("复制失败");
}finally{
try{
if(fw!=null)
fw.close();
}catch(IOException ex){
throw new RuntimeException("释放资源失败");
}finally{
try{
if(fr!=null)
fr.close();
}catch(IOException ex){
throw new RuntimeException("释放资源失败");
}
}
}
}
}
1.3 转换流
转换流有两个,也就是两个方向,一个是字节流转换为字符流(InputStreamReader),一个是字符流转换为字节流(OutputStreamWriter)。
OutputStreamWriter
public static void OutputStreamWriterDemo() throws Exception {
//创建与文件关联的字节输出流对象
FileOutputStream fos = new FileOutputStream(destpath);
//创建可以把字符转成字节的转换流对象,并指定编码
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//调用转换流,把文字写出去,其实是写到转换流的缓冲区中
osw.write("你好");//写入缓冲区。
osw.close();
}
InputStreamReader
public static void InputStreamReaderDemo() throws IOException{
//创建读取文件的字节流对象
InputStream in = new FileInputStream(srcpath);
//创建转换流对象
//InputStreamReader isr = new InputStreamReader(in);会用本地默认码表读取,将会发生错误解码的错误
InputStreamReader isr = new InputStreamReader(in,"utf-8");
//使用转换流去读字节流中的字节
int ch = 0;
while((ch = isr.read())!=-1){
System.out.println((char)ch);
}
//关闭流
isr.close();
}
1.4 缓冲流
为什么缓冲流是高效的流呢? 举个例子,你去买零食,一共想买10袋,一定是一次性买十袋要比一次买1袋买十次更高效。
字节缓冲流
//字节缓冲输出流BufferedOutputStream
private static void write() throws IOException {
//创建基本的字节输出流
FileOutputStream fileOut = new FileOutputStream("abc.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedOutputStream out = new BufferedOutputStream(fileOut);
//2,写数据
out.write("hello".getBytes());
//3,关闭流
out.close();
}
//字节缓冲输入流BufferedInputStream
private static void read() throws IOException {
//1,创建缓冲流对象
FileInputStream fileIn = new FileInputStream("abc.txt");
//把基本的流包装成高效的流
BufferedInputStream in = new BufferedInputStream(fileIn);
//2,读数据
int ch = -1;
while ( (ch = in.read()) != -1 ) {
//打印
System.out.print((char)ch);
}
//3,关闭
in.close();
}
高效复制文件
private static void method4(String src, String dest) throws IOException {
//1,指定数据源
BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
//2,指定目的地
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
//3,读数据
byte[] buffer = new byte[1024];
int len = -1;
while ( (len = in.read(buffer)) != -1) {
//4,写数据
out.write(buffer, 0, len);
}
//5,关闭流
in.close();
out.close();
}
字符缓冲流
//字节缓冲输出流BufferedOutputStream
private static void write() throws IOException {
//创建基本的字节输出流
FileWriter fileOut = new FileWriter("abc.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedWriter out = new BufferedWriter(fileOut);
//2,写数据
out.write("hello");
out.newLine();
//3,关闭流
out.close();
}
//字节缓冲输入流BufferedInputStream
private static void read() throws IOException {
//1,创建缓冲流对象
FileReader fileIn = new FileReader("abc.txt");
//把基本的流包装成高效的流
BufferedReader in = new BufferedReader(fileIn);
//2,读数据
String line = null;
while ( (line = in.readLine()) != null ) {
//打印
System.out.print(line);
}
//3,关闭
in.close();
}
例子:文本复制
public class CopyTextFile {
public static void main(String[] args) throws IOException {
//1,指定数据源, 是数据源中读数据,采用输入流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,指定目的地,是把数据写入目的地,采用输出流
BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));
//3,读数据
String line = null;
while ( (line = in.readLine()) != null ) {
//4,写数据
out.write(line);
//写入换行符号
out.newLine();
}
//5,关闭流
out.close();
in.close();
}
}