一、什么是IO流
IO流用来处理设备之间的数据传输。Java对数据的操作是通过流的方式。Java用于操作流的对象都在IO包中。输入流和输出流相对于内存设备而言。
IO流的分类
根据处理数据类型的不同分为:字符流和字节流。
根据数据流向不同分为:输入流和输出流。
流的分类
1、按功能分
读取流:InputStream Reader
写出流:OutPutStream Writer
2、按流的类型分类
字节流:InputStream OutputStream
字符流:Reader Writer
3、字节流的抽象基类:InputStream,OutputStream。
4、字符流的抽象基类:Reader,Writer。
p.s.
字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字。再对这个文字进行
操作。简单说:字节流+编码表。
二、IO流的运用
重点记忆:
1. close方法只能用一次。
2. 流关闭以后不能,不能再调用write方法,否则会报异常错误。
3.如果构造函数中加入true,可以实现对文件进行续写。
4.IO流的异常处理方式:为防止代码异常导致流无法关闭,因此在finally中对流进行关闭。
5.如果要操作文字数据,建议优先考虑字符流。
读取一个文本文件,有2种方式:
第一种读取方式:使用read()方法读取文本文件数据。
第二种读取方式:使用read(char[])方法读取文本文件数据。
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo{
public static void main(String[] args)throws IOException{
FileReader fr = new FileReader("demo.txt" );
//使用read(char[])读取文本文件数据
//先创建字符数组
char[] buf = new char[3];
int len = 0;
while((len = fr.read(buf)) != -1){
System.out.println( new String(buf,0,len));
}
fr.close();
}
}
案例演示1:
将d盘的一个文本文件复制到d盘。
分析:
读取d盘demo.txt文件中的数据,将这些数据写入到d盘copyText_1.txt文件当中。
既然是操作文本数据,使用字符流。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextTest{
private static final int BUFFER_SIZE = 1024;
public static void main(String[] args){
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("demo.txt" );
fw = new FileWriter("copytest_2.txt" );
//创建一个临时容器,用于缓存读取到的字符
char[] buf = new char[BUFFER_SIZE];
//定义一个变量记录读取到的字符数(其实就是往数组里装的字符个数)
int len = 0;
while((len = fr.read(buf)) != -1){
fw.write(buf,0,len);
}
} catch(Exception e){
throw new RuntimeException("读写失败!");
} finally{
if(fw != null){
try{
fw.close();
} catch(IOException e){
System.out.println(e.toString());
}
}
if(fr != null){
try{
fw.close();
} catch(IOException e){
System.out.println(e.toString());
}
}
}
}
}
三、字符缓冲区
缓冲区的出现提高了对数据的读写效率。
对应类:
BufferedWriter
BufferedReader
缓冲区要结合流才可以使用。
作用:在流的基础上对流的功能进行了增强。
1、字符流缓冲区:
写入换行使用BufferedWriter类中的newLine()方法。
读取一行数据使用BufferedReader类中的readLine()方法。
bufr.read():这个read方法是从缓冲区中读取字符数据,所以覆盖了父类中的read方法。
bufr.readLine():另外开辟了一个缓冲区,存储的是原缓冲区一行的数据,不包含换行符。
原理:使用了读取缓冲区的read方法,将读取到的字符进行缓冲并判断换行标记,将标记前的缓冲数据变成字符串返回。
案例演示2:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class CopyTextBufTest{
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("buf.txt" );
BufferedReader bufr = new BufferedReader(fr);
FileWriter fw = new FileWriter("buf_copy.txt" );
BufferedWriter bufw = new BufferedWriter(fw);
String line = null;
//方式一
while((line = bufr.readLine()) != null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
//方式二
/*
int ch = 0;
while((ch = bufr.read()) != -1){
bufw.write(ch);
}
*/
bufr.close();
bufw.close();
}
}
2、LineNumberReader
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
案例演示2:
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderDemo{
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("LineNumberReaderDemo.java" );
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(100);
while((line = lnr.readLine()) != null){
System.out.println(lnr.getLineNumber() + ":" + line);
}
lnr.close();
}
}
四、 IO流常用基类-字节流
读取一个键盘录入的数据,并打印在控制台上。
键盘本身就是一个标准的输入设备。对于java而言,对于这种输入设备都有对应的对象。
import java.io.IOException;
import java.io.InputStream;
public class ReadKey{
public static void main(String[] args) throws IOException {
readKey();
}
public static void readKey() throws IOException {
InputStream in = System.in;
int ch = in.read();//阻塞式方法
System.out.println(ch);
ch = in.read(); //阻塞式方法
System.out.println(ch);
ch = in.read(); //阻塞式方法
System.out.println(ch);
in.close();
}
}
重点记忆:
1、获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。通过System类的setIn,setOut方法
可以对默认设备进行改变。
System.setIn(new FileInputStream(“1.txt”));//将源改成文件1.txt
System.setOut(new PrintStream(“2.txt”));//将目的改成文件2.txt
因为是字节流处理的是文本数据,可以转换成字符流,操作更方便。
BfferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw =
new BufferedWriter(new OutputStreamWriter(System.out));
2、默认的输入和输出系统不需要关,它会随着系统的结束而消失。
五、流的操作规律
之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。
想要知道对象的开发时用到哪些对象,只要通过四个明确即可。
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确数据是否是纯文本数据
源:是纯文本:Reader
否:InputStream
目的:是纯文本:Writer
否:OutputStream
到这里,就可以明确需求中具体要使用哪个体系。
3、明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4、是否需要其他额外功能
是否需要高效(缓冲区):
是,就加上buffer