Java I/O 系统中最常用的类及其特性和基本用法
Java I/O 体系主要分为三个类:
1.字节流
2.字符流
3.特殊对象流
一 字节流
字节流分为字节输出流(OuputStream)和输入流(InputStream)
常用的接口子类有:OutputStream 和 FileOutputStream
InputStream 和 FileInputStream
OutputStream是字节流中最顶层的类,该输出流对数据逐个字节进行输出。特点:效率较慢,但是通用性强(因为计算机中的数据都是以字节的形式存储的),并且只有一个无参构造函数,也足以说明它的通用性了。
FileOutputStream是文件字节输出流,我们的数据经常是文件的形式存在的,如:图片,文本文件等。FileOutputStream是对OutputStream的进一步封装,使其更具体。该类提供多个构造函数,可以用文件的路径或者一个File对象作为参数对输出流进行初始化
InputStream同OutputStream一样,也是IO系统中比较顶层的类。该类同样值有一个无参构造函数,特点:同OutputStream相同
FileInputStream 与 FileOutputStream特性相同,一个为文件输入流一个为文件输出流,操作对象都针对于文件。
例:用FileInputStream读取txt文件,并打印到控制台
import java.io.*;
public class FileInputStreamDemo1 {
public static void main(String []args)throws IOException{
//定义出入流对象
FileInputStream fis = new FileInputStream("E:\\iofile\\demo.txt");
//读入数据,当数据被读完是,返回值为-1
//第一种读取
/*int ch = 0;
while((ch = fis.read()) != -1){
System.out.print((char)ch);
}*/
//第二种读取
/*byte[] b = new byte[1024];
int n = 0;
while((n = fis.read(b))!= -1){
System.out.print(new String(b,0,n));
}*/
//第三种,能够获取字节数,是字节流特有的方法。
//注:当数据量不是特别大的时候可以使用这种方法,但是当数据量过大而超出内存空间的大小是就会发生内存溢出错误。
int len = fis.available();
byte []b = new byte[len];
fis.read(b);
System.out.println(new String(b));
//关闭字节流
fis.close();
}
}
带缓冲区的字节流:由于以上两种字节流都是以字节为单位进行读写的,这样频繁的读写比较浪费资源而且影响程序的运行效率,Java提供了一对带缓 冲区的字节流,一次性读取某一长度的字节数据,然后先向这些数据存储到内存中对其进行统一写入操作,这样就提搞了效率。
这一对带缓冲区的字节流为:BufferedInputStream和BufferedOutputStream
这两个类的构造器分别接受InputStream和OutputStream
具体用法如下所示:
import java.io.*;
/**
* 复制mp3文件,通过缓冲区
* */
public class IOPractise5 {
public static void main(String []args) throws IOException{
//创建流对象
FileInputStream fis = new FileInputStream("e:\\iomediafile\\yikuaihongbu.mp3");
FileOutputStream fos = new FileOutputStream("e:\\iofile\\yikuaihongbu.mp3");
//创建输入输出缓冲区
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//定义标记
int b = 0;
while((b = bis.read()) != -1){
bos.write((char)b);
bos.flush();
}
bos.close();
bis.close();
}
}
二 字符流
很多情况下流对象都要对文本文件的内容进行读写操作,如果能按字符进行操作那就相当于对字节流加上了一个小的缓冲区,有利于提高效率。
Java提供了两个以字符为基本单位进行操作的字符流抽象类接口 Writer 和 Reader ,分别是写入字符流和读取字符流。这两个抽象类都有很大具体的实现类。
常用的有以下几个
Writer Reader
|--OutputStreamWriter 转换流 |--InputStreamReader 转换流
|--FileWriter 文件字符写入流 |--FileReader 文件字节读取流
|--BufferedWriter 带缓冲区的写入流 |--BufferedReader 但缓冲区的读取流
下面对这几个常用类一一做简单介绍。
FileWriter 和 FileReader 是对文本文件进行操作时最常用到的两个类,这两个类中提供了对文本文件操作的强大支持,既可以按字节读取,又可以按字符读取,同时还可以以行为单位来进行数据的读写操作。
用法如下所示
import java.io.*;
/**
* 用 read(char[] rbuf)读取多个字符
* */
public class FileReaderDemo2 {
public static void main(String []args){
// 创建FileReader对象
FileReader fd = null;
try {
//建立与目标文件的链接
fd = new FileReader("E:\\iofile\\demo.txt");
//定义缓冲区,缓冲区一般定义1024的N倍的长度
char [] c = new char[1024];
//定义标记
int num = 0;
//判断是否读取到文件中字符的末尾
while((num = fd.read(c)) != -1){
//打印被都出了的字符串
System.out.print(new String(c,0,num));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fd != null) {
fd.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 文件内容的续写
* **/
public class FileWriterDemo3 {
public static void main(String []args){
// 创建FileWriter对象
FileWriter fw = null;
try {
//传递一个true参数,表示不覆盖已有的文件,并在已有文件的末尾床续写
fw = new FileWriter("E:\\iofile\\demo1.txt", true);
// \r\n 在txt文件下换行
fw.write("\r\nhaha");
fw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader 和 BufferedWriter 是带缓冲区的字符流,与BufferedOutputStream和BufferedInputStream有相同的效果,就是提供程序的运行效率,他们都是用装饰设计模式的思想对基础操作进行封装增强。具体用法如下:
/**
* 缓冲区是提高流的工作效率,在创建缓冲区之前要先创建流对象
* */
public class IOBufferDemo1 {
public static void main(String []args) throws IOException{
//创建流对象
FileWriter fw = new FileWriter("E:\\iofile\\bufferDemo1.txt");
//为了提高写入效率,加入缓冲技术。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
BufferedWriter bw = new BufferedWriter(fw);
//写入操作
bw.write("fdasfdadsf");
//用缓冲区写入一定要用flush刷新才能写入成功。
bw.flush();
//其实关闭缓冲区就是关闭缓冲区中的流对象,不用再次关闭流对象
bw.close();
}
}
/**
* 读取-缓冲区
* 该缓冲区提供了一个一次都一行的方法readLine(),方便了对文本数据的读取,当返回null时表示读到末尾
* */
public class IOBufferDemo2 {
public static void main(String []args)throws IOException{
//创建字符读取对象
FileReader fr = new FileReader("E:\\iofile\\BubbleSort.java");
//为了提高效率 加入缓冲技术创建字符读取缓冲区
BufferedReader br = new BufferedReader(fr);
String s = null;
//一次读一行
while((s = br.readLine()) != null){
System.out.println(s);
}
}
}
转换流:InputStreamReader 和 OutputStreamWriter 。这两个类的IO中非常重要的两个类,他们能在字节流和字符流之间对流进行转换,这两个类的构造器分别介绍字节输入流 和 字节输出流 ,将其封装成字符输入流 和 字符输出流。具体用法如下:
import java.io.*;
/**
* 将中文的文本文件内容打印到控制台上
* */
public class IOPractise6 {
public static void main(String[] args) {
//源文件为文本文件,因此首选Reader,但是要设置编码因此选择FileInputStream
FileInputStream fis = null;
//又因为要进行编码设置因此选择InputStreamReader
InputStreamReader isr = null;
//目的地为控制台,并且要打印中文,因此应该指定编码表,因此用 OutputStreamWriter
OutputStreamWriter osw = null;
try{
//初始化对象
fis = new FileInputStream("d:\\个人资料\\新建文本文档.txt");
isr = new InputStreamReader(fis,"GBK");
BufferedReader br = new BufferedReader(isr);
osw = new OutputStreamWriter(System.out,"GBK");
BufferedWriter bw = new BufferedWriter(osw);
String s = null;
while((s = br.readLine()) != null){
bw.write(s);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}catch(Exception e){
}finally{
try{
}catch(Exception e){
}
}
}
}
两种常见的写法:
//将字节输入流封装为带缓冲区的字符流
BufferedReader br = new BufferedReader(new InputStreamReader(new InputStream()));
//将字节输出流封装为带缓冲区的字符流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new OutputStream()));