------<a href="http://www.itheima.com" target="_blank" rel="external nofollow" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
IO流——字节流
一.IO流:
1、IO流的类的层次结构
A:字节流:
OutputStream:
|--FileOutputStream:
|--FilterOutputStream:(没学)
|--BufferedOutputStream:(带缓冲区字节流)
InputStream:
|--FileInputStream:
|--FilterInputStream:(没学)
|--BufferedInputStream(带缓冲区字节流)
B:字符流:
Writer:
|--OutputStreamWriter(转换流)
|--FileWriter:
|--BufferedWriter(带缓冲区字符流)
Reader:
|--InputStreamReader(转换流)
|--FileReader:
|--BufferedReader:(带缓冲区的字符流)
2.IO流概念:
1).IO流:InputStream和OutputStream
2).流:是有方向的,线性的;针对某个文件的输入输出流
站在程序的角度:
InputStream :从外部向程序中读入数据的
OutputStream:从程序向外部输出数据
3).分类:
A.按流向:
输出流
输入流
B.按读写方式:
字节流:
字符流:
二、FileOutputStream(类,继承自OutputStream抽象类)(文件可以不存在)
1.构造方法:
覆盖写:
FileOutputStream(String name):使用一个文件名构造一个输出流
例子:FileOutputStream file=new FileOutputStream("D:\\aaa\\output.txt");
FileOutputStream(File file);使用一个文件类型的引用构造一个输出流
例子:FileOutputStream file=new FileOutputStream(new File("output.txt"));
对于上述的例子中的文件既可以是绝对路径也可以是相对路径,相对路径就会在当前工作目录创建文件。
这里会有一场出现,会在不能创建文件(磁盘问题,权限问题等)时出现异常,使用try...catch语句抛出异常即可
追加写:
FileOutputStream(String name,boolean append):
FileOutputStream(File file,boolean append);追加写入,当判断为真时,在文件的末位。
2.写入方法:
A:public void write(int byte):向文件中写入一个字节。因此byte必须在字节的范围之内,即-128~127.但是负值有可能没有对应值。
B:public viod write(byte[] byteArray):写入一个字节数组。
★★★如何把一个字符串转化为一个字节数组呢?使用String类的getBytes()方法获取字节数组byte[]
C:public void write(byte[] byteArray,int off,int len):只写数组的一部分
3.关闭流:
close();关闭通道,结余资源,不然一直占用其他文件无法访问。
4.输出换行符
out.write("\r\n".getBytes());
★★5.加入异常处理
1).直接在方法声明上抛出异常(不推荐)
2).try..catch单组捕获异常
3).try..catch 多组组合捕获异常
public class Demo {
public static void main(String[] args) {
FileOutputStream out = null;
try {
out = new FileOutputStream("output2.txt",true);//可能产生异常
//写入数据
out.write("你好Java".getBytes());//可能产生异常
out.write("\r\n".getBytes());//可能产生异常
} catch (FileNotFoundException e) {
System.out.println("无法创建系统文件,请查看您是否有权限访问磁盘,或查看磁盘空间是否够用!");
} catch (IOException e) {
System.out.println("无法写入系统文件,请联系系统管理员!");
}finally{
//释放资源
try {
if(out != null){
out.close();
}
} catch (IOException e) {
System.out.println("无法关闭系统文件,请联系系统管理员!");
}
}
}
}
三、FileInputStream(类,继承自InputStream)(文件必须存在,抛出异常:java.io.FileNotFoundException)
1.构造方法:
FileInputStream(String name):使用文件名创建一个输入流
FileInputStream(File file):使用一个文件类型的引用创建一个输入流
2.读取的方法:
public int read();一次读取一个字节,返回一个Int值,可以打印,可以用char强转,但是可能没有意义。
当读取到文件的末位时,会返回-1。可以读取换行符。在eclipse里面会显示是\r\n,是两个换行符。
两种常用的循环遍历的方法:
方法一:
int m=in.read();
while(m!=-1){
System.out.println(m+""+char(m));}
m=in.read();
方法二:
int m=0;
while((m=in.read())!=-1){
System.out.println(m+""+char(m));}
3.复制一个文本文件案例(用来做加密文字比较好啊)
思路分析:
1).从源文件读取数据,使用输入流
2).一次读取一个字节
3).向目标文件写入输出一个字节
代码实现:
public class Demo {
public static void main(String[] args) {
try {
//创建一个输入流对象
FileInputStream in=new FileInputStream("D:\\day20-copy.text");
//创建一个输出流对象
FileOutputStream out=new FileOutputStream("D:\\day20-copy1.java");
//读取一个字节
int n=0;
while((n=in.read())!=-1){
System.out.println(n+""+(char)n);
out.write(n);
}
in.close();
out.close();
} catch (FileNotFoundException e) {
System.out.println("捕获输入输出异常");
e.printStackTrace();
} catch (IOException e) {
System.out.println("捕获读取写入异常");
e.printStackTrace();
}
System.out.println("程序执行完毕!!!");
}
}
4.第二种读取方法:public int read(byte[] byteArray):
★★★如何打印字节数组的内容呢?
很简单的,Array.toString(byteArray),其打印结果是,用[]括起来的,用逗号分隔的数组元素的字符串。
★★★使用String的构造方法,可以将一个byte数组转换为一个字符串。
String(byte[] bytes)
String(byte[] bytes, int offset, int length)
读取到文本底部时,返回值也是-1.
基本使用方法:
//创建一个字符数组
byte[] byteArray=new byte[20];一般根据需要定义数组的长度
int n=0;
while((n=in.read(byteArray))!=-1){
String s=new String(byteArray,0,n);//此种的构造方法,可以恰到好处的取出全部的内容★★
★★//实际上n代表的就是数组中被再次填入的元素个数,最后一次填入,可能填不满,但是原来的元素不会被全部覆盖。
System.out.println(s);
}
一次读取一个字节数组,复制文本文件。视频同样方法。代码实现:
public class Demo {
public static void main(String[] args) throws IOException {
//1.文件的输入流:文件必须存在,否则抛出异常
FileInputStream in = new FileInputStream("D:\\aaa\\StringDemo.java");
//2.文件的输出流:文件可以不存在。如果不存在,则创建
FileOutputStream out = new FileOutputStream("StringDemo_demo02_copy.java");
//开始复制:
//一次读取一个字节数组
byte[] byteArray = new byte[1024];
int n = 0;
while((n = in.read(byteArray)) != -1){
//写入,一次写入一个byte数组
out.write(byteArray, 0, n);
}
//释放资源
in.close();
out.close();
System.out.println("复制完毕!下课");
}
}
四、带缓冲的字节流
1.缓冲的字节流概述
可以看到使用字节数组可以大大加快复制速度,由于数组具有缓冲区功能。一次读取的数据填充到数组中,然后再一次写入,提高了效率。
2.带缓冲的字节流
BufferedInputStream;带缓冲的输入流
BufferedOutputStream;带缓冲的输出流
3.带缓冲的输出流:BufferedOutputStream
BufferedOutputStream:带缓冲的输出流:只要是OutputStream的子类都可以,我们学过:FileOutputStream;
BufferedOutputStream只提供了"缓冲区",只是写进了内存去,内部写入,仍然使用参数传递的FileOutputStream对象实现。
BufferedOutputStream(OutputStream out) :创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
输出流的写入的方法:它没有特有的写入方法,使用父类的即可
注意:如果要实现追加写的话,就要在构建OutputStream时准备好。
flush(),刷新缓冲区,实现写入功能。
close(),内部集成了刷新功能,可以不用再刷新了。
4.带缓冲的输入流:BufferedInputStream
BufferedInputStream(InputStream in) : 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferedInputStream(InputStream in, int size) : 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
没有特有方法,使用父类的方法
int read():读取一个字节
int read(byte[] byteArray):读取一个字节数组
5.五种方式复制文件速度对比
1.一次读、写一个字节:使用基本流:FileInputStream 和 FileOutputStream -- > method1(): 57626毫秒
2.一次读、写一个字节数组:使用基本流:FileInputStream 和 FileOutputStream --> method2(); 149 毫秒
3.一次读、写一个字节:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method3(); 958 毫秒
4.一次读、写一个字节数组:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method4(); 66 毫秒
结论:读写"二进制"文件,首选带缓冲的字节流。
//1.一次读、写一个字节:使用基本流:FileInputStream 和 FileOutputStream -- > method1()
private static void method1() throws IOException{
FileInputStream in = new FileInputStream("D:\\aaa\\哥有老婆.mp4");
FileOutputStream out = new FileOutputStream("哥有老婆_copy1.mp4");
//开始复制,一次读写一个字节
int n = 0;
while((n = in.read()) != -1){
out.write(n);//写入一个字节
}
//释放资源
in.close();
out.close();
}
//2.一次读、写一个字节数组:使用基本流:FileInputStream 和 FileOutputStream --> method2();
private static void method2() throws IOException{
FileInputStream in = new FileInputStream("D:\\aaa\\哥有老婆.mp4");
FileOutputStream out = new FileOutputStream("哥有老婆_copy2.mp4");
//开始复制,一次读写一个字节数组
byte[] byteArray = new byte[1024];
int n = 0;
while((n = in.read(byteArray)) != -1){
out.write(byteArray,0,n);//一次写入一个字节数组
// out.flush();
}
//释放资源
in.close();
out.close();
}
//3.一次读、写一个字节:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method3()
private static void method3() throws IOException{
BufferedInputStream in = new BufferedInputStream(new FileInputStream("D:\\aaa\\哥有老婆.mp4"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("哥有老婆_copy3.mp4"));
//一次读、写一个字节
int n = 0;
while((n = in.read()) != -1){
out.write(n);
}
//释放资源
in.close();
out.close();
}
//4.一次读、写一个字节数组:缓冲流:BufferdInputStream 和 BufferedOutputStream --> method4();
private static void method4() throws IOException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream("D:\\aaa\\哥有老婆.mp4"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("哥有老婆_copy3.mp4"));
//一次读、写一个字节数组
byte[] byteArray = new byte[1024];
int n = 0;
while((n = in.read(byteArray)) != -1){
out.write(byteArray,0,n);
}
//释放资源
in.close();
out.close();
}