2016.08.22-2016.08.24
上课类容:IO流
请别和我说话,小心我一言不和就放图。好吧,如果作为一名初学者,我相信你看到下面这幅图,整个人就不好了。
一看到这幅图,宝宝吓坏了,瞬间整个人就不好了。
请自行看3遍,谢谢!
下面我们再分别叙述一下字节流和字符流。
一:字节流
1.IO流体系:对数据进行读写操作,所以说IO流不是读就是写咯。
2.IO流相关的类:都在java.io包下。
有关的io操作都会产生IOException异常。
3.IO:参照物是程序
i:input.进来,读取数据到程序中。
o:output:出去,将数据从程序中写出去。
再放一图
4:io流的分类,相关的类都会有相应的单词。
4.1:从数据的流向分。个人理解为就是内存和硬盘之间的数据交换,内存上的数据是暂时性的,而硬盘上的数据是永久性的。
Input(输入):读取数据,数据往程序中流。或者说:将硬盘上的数据放到内存上
Output(输出):写出数据,将数据从程序中写出去。或者说:将内存上的数据放到硬盘上
4.2:字节流和字符流
Stream:字节流,所有的数据都可以用字节流操作。计算机真正能识别的就是010101这些东西,8个0或者1组合成位,8位就是一个字节了。
Reader或者Writer:字符流。字符流是在字节流的基础上加了编码机制。只能对文字进行操作,虽说是文字,更贴切的说是文本文件,并不包括.doc等富文本文件,因为这些文件里面可以放图片或者其他的非文字内容。不能够对图片或者音频文件进行操作。
InputSteam:读取字节流。OutputStream:输出字节流。
Reader:读取字符流, Writer:写出字符流。
5:文件字节流
OutputStream,:抽象类
文件输出字节流:FileOutputStream:节点流,跟目标设备相关联。
实例一:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo1 {
public static void main(String[] args) throws IOException {
//1.创建文件输出流对象,参数为全路径名
FileOutputStream fos = new FileOutputStream("e:\\aa.txt");
//2.写出数据
//2.1准备数据
String str = "要写出的数据";
//2.2将数据转为字节数组的形式
byte[] b = str.getBytes();
//3.0将数据按照一个个字节地写出目标文件中
/*for(int i=0; i<b.length; i++){
fos.write(b[i]);
}*/
//3.1以下是将整个数组输出去,和3.0可到达相同的效果
fos.write(b);
//4.释放资源
fos.close();
}
}
BufferedInputStream:处理流,必须先有节点流。为了增加效率。处理的方式是将节点流包装起来
public static void testBufferedOutputStream() throws IOException{
//在使用带缓冲区的字节流的时候先要有一个节点流作为参数,或者说先指定一个目标文件
FileOutputStream fos = new FileOutputStream("d:\\test.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//将以下文字写到目标文件中去
String str = "这几个文字即将通过带缓冲区的字节流写到一个文本文件中";
bos.write(str.getBytes());
//写完之后记得要刷新才能真正写入到文件中,不然还会保存在缓冲区里,直到释放资源
bos.flush();
//释放资源(关闭流)
bos.close();
}
InputStream:抽象类。
文件输入字节流:FileInputStream:节点流,和要读取那个文件关联起来
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo1 {
public static void main(String[] args) throws IOException {
//1.创建字节输入流对象
FileInputStream fis = new FileInputStream("e:\\bb.txt");
//2.开始读取数据
// System.out.println((char)fis.read());
int b;
while((b=fis.read())!=-1){
System.out.print((char)b);
}
fis.close();
}
}
BufferedOutputStream:带缓冲区的。也是为了增加效率,处理的方式是将节点流包装起来
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 将一个文件的文字输出到控制台
*/
public class BufferedInputStreamDemo1 {
public static void main(String[] args) {
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream("d:\\aa.txt");
bis = new BufferedInputStream(fis);
//byte数组用来装读取到的数据
byte[] b = new byte[1024];
int len = -1;
while((len = bis.read(b))!=-1){
System.out.println(new String(b, 0, len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6:字节流:在文件系统中,任何文件都是以二进制形式存储的,二进制用位体现(8位为一个二进制单元),8位=1字节,所以字节流可以处理任何文件。
6.1字节流常用的一些类:
6.1.1输入流read(), 读到末尾返回-1
常用read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
FileInputStream:文件输入流
BufferedInputStream:带缓冲区的输入流,先要传入一个节点流(输入流)作为参数
6.1.2输出流write()
常用write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off
开始的 len
个字节写入此文件输出流。
FileOutputStream:文件输入流
BufferedOutputStream:带缓冲区的输入流,先要传入一个节点流(输入流)作为参数
结合输入输出流写一个文件复制的工具
public static boolean copyFile( String filePath,String target){
boolean flag = false;
//输出流,将数据写入到目标文件中
FileOutputStream fos = null;
//输入流,将要用的文本拿到程序中
FileInputStream fis = null;
//读取文本
byte[] b = new byte[1024];
//每次读取字符数据的有效长度
int length = -1;
try {
fis = new FileInputStream(filePath);
fos = new FileOutputStream(target);
/*
* fis.read(b):从fis关联的文件中每次读取 1024 个字节,
* 并把读取到的字节数据保存这个数组里面,
* 但是这个文件并不是只有1024 这个么大,有可能要读多次,所以要用循环
* 寻到的条件是读到文件没有得读了,就是读到最后了就不读了,
* 读到末尾的返回值是-1,如果返回值是-1则停止循环
*
*/
while((length=fis.read(b)) != -1){//读到文件末尾就返回-1,不在往下读取
//将读到的数据写入目标文件中
fos.write(b, 0, length);
fos.flush();//将数据刷到目标文件
}
System.out.println("文件复制成功!");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//关闭释放资源
try {
fos.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
flag = true;
return flag;
}
二.字符流
1.字符流:在字节流的基础上添加了编码机制。很大程度上和字节流操作一样的,字符流只能操作文本类文件,准确的说应该是纯文本类文件。例如.txt,.java,.cpp,.html等
编码:每一个国家都有自己的编码,编码不一致往往导致的结果就是!!乱码!!。中国编码的编码:gbk
gbk:英文字母:1个字节,中文:2个字节,系统的默认编码。
unicode:统一编码。中文还是英文字母都是占2个字节。
utf-8: 国际编码。英文占1个字节,中文占3个字节。
文件是用什么编码来写的,那么就用什么编码来读取。最常用的编码是gbk和utf-8.一般的情况下,都设置为utf-8.(还有其他的很多编码:例如GB2312,big5等等)。如果想测试是否像上面所说那么多个字节的话,建议使用Notepad2文本软件,体积小功能强!(似乎再买广告了。。。)
Reader:读取数据
FileReader:文件读取字符流
BufferedReader://带缓冲区的字符输入流
readLine() ;读取一行数据
LineNumberReader;带行号.通过getLineNumber()方法获取行号
带行号功能的字符输入流
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
/*LineNumberReader是BufferedReader的子类,
* 比BufferedReader多了设置行号和获取行号的功能。
* 使用LineNumberReader流读取文本文件,并打印在控制台上。
* 在每行的前面添加行号。
*/
public class LineNumberReaderDemo1 {
public static void main(String[] args) throws IOException {
String str = null;
while((str = lnr.readLine()) != null){
// lnr.setLineNumber(90);//设置行号
System.out.print(lnr.getLineNumber()+" : ");
System.out.println(str);
}
lnr.clo
Writer:写入数据
FileWrite:写入数据,记得刷新。
BufferedWriter://带缓冲区的字符输出流
newLine():写入换行字符。
write(String str):写入字符串。
/*
* 2:用字符流复制文本文件。
*/
public static boolean copyText(String textPath, String targetPath){
boolean flag = false;
if(textPath==null || textPath.trim().equals("")){
return flag;
}
if(targetPath == null || targetPath.trim().equals("")){
int end = textPath.lastIndexOf(".");
String endStr = textPath.substring(end);//后缀名
int index = textPath.lastIndexOf("\\");
if(index == 0){
index = textPath.lastIndexOf("/");
}
targetPath = textPath.substring(0,end)+"2"+endStr;//新文件名
}
BufferedReader br = null;
BufferedWriter bw = null;
try {
//字符输入流
FileReader fr = new FileReader(textPath);
br = new BufferedReader(fr);
//字符输出流
FileWriter fw = new FileWriter(targetPath);
bw = new BufferedWriter(fw);
String str = "";
while((str=br.readLine()) != null){
bw.write(str);
bw.newLine();
bw.flush();
}
flag = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
bw.close();
br.close();
}catch (IOException e){
e.printStackTrace();
}
}
return flag;
}
转换流:可带编码格式的流
InputStreamReader;字节转换为字符流
转换流示例
public class SystemReadDemo1 {
public static void main(String[] args) throws IOException {
//获取键盘输入
InputStream is = System.in;
//将字节流转换为字符流,用到InputStreamReader(InputStream in)---转换流
InputStreamReader isr = new InputStreamReader(is,"utf-8");
//将字符流再转为带缓冲区的字符流
BufferedReader br = new BufferedReader(isr);
String str = null;
while(true){
str = br.readLine();
if("886".equals(str)){
break;
}
System.out.println(str);
}
br.close();
}
}
OutputStreamWriter ;字符流转换为字节流。
转换流示例二
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
/*
* 1:获取键盘录入的数据,将数据写到文件中,但是以utf-8编码的形式写到文件中去。
*/
public class HomeWork1 {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("e:\\aa.txt"), "utf-8"));
String str = "";
while(true){
str = br.readLine();
if("exit".equals(str)){
//可以尝试不同的编码
OutputStreamWriter osw = new OutputStreamWriter(System.out, "GBK");
BufferedWriter bw2 = new BufferedWriter(osw);
bw2.write("输入结束!");
bw2.flush();
break;
}
bw.write(str);
bw.newLine();
bw.flush();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
这一段代码的作用是:因为BufferedInputStream为别的输入流添加缓冲功能,在创建BufferedInputStream时会创建一个内部缓冲数组, 用于缓冲数据,提高性能。默认的缓冲大小是8192KB,如果你要读取的文件大于这个默认的大小时,缓冲区没有读满是不会被写入文件的。 所以要关闭输入流,释放这个流的资源。或者用flush()这个命令强制写入。
try {
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三.练习
1.使用字节流读取500MB~1G的文件,然后再使用缓冲流读取500MB~1G的文件,测试两者的区别