JAVA中IO流详解
IO流:数据传输是需要通道的,而IO流就是数据传输的通道。
IO流可以形象的比喻为运送货物的传输带。
IO流的分类:
①根据操作的数据类型的不同可以分为 :字节流与字符流。
②根据数据的流向分为:输入流与输出流,程序(内存)作为参照物,程序从外部读取称为输入(Input),程序向外部写数据成为输出(Output)。
字节输入流:
父类:InputStream
常用的字节输入流:FileInputStream
1.FileInputStream
①构造方法:
FileInputStream(File)
FileInputStream(String filename)
2.常用方法
①read :读取一个字节,返回该字节的值,如果到达文件的末尾,则返回-1。需要注意:read()方法和迭代器一样,会自动下移的
②read(byte[ ])从输入流中读取至多一个数组长度的内容,到达文件末尾,则返回-1。
- 数组称为缓冲区数组,大小一般取值为1024的整数倍。
- 转换为字符时,使用String(byte [ ] bytes,int offset,int length)
- available()没有读取的剩余字节数,如果该文件还从未被读取,就返回该文件的长度。
- close() 关闭流并释放资源
字节输入流代码演示:
其中1.txt位于本项目的根目录下:内容为"abcdefg"
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Demo6 { 6 7 public static void main(String[] args) throws IOException{ 8 File file=new File("1.txt"); //新建一个文件的抽象路径 9 FileInputStream fis=new FileInputStream(file); 10 int result=fis.read(); 11 System.out.println(result); 12 13 } 14 15 }
程序执行的结果为97,因为读取的a的ASCII码值
字节输入流的循环读取:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Demo7 { 6 7 public static void main(String[] args) throws IOException{ 8 File file =new File("1.txt"); 9 FileInputStream fis=new FileInputStream(file); 10 int result; 11 while((result=fis.read())!=-1) { 12 System.out.print(result+"\t"); 13 } 14 15 16 } 17 18 }
打印了a到g的ASCII码值
字符流的读取方法:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Demo8 { 6 7 public static void main(String[] args) throws IOException{ 8 File file =new File("1.txt"); 9 FileInputStream fis=new FileInputStream(file); 10 byte[] bt=new byte[1024]; 11 int count; 12 while((count=fis.read(bt))!=-1) { 13 String string =new String(bt,0,count); 14 System.out.println(string); 15 } 16 } 17 }
输出结果
下面可以用同样的文件来比较字节输入流和字符输入流的读取速度:
文件是一张格式为png图片
先是字节输入流的读取速度
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Demo9 { 6 7 public static void main(String[] args) throws IOException{ 8 File file =new File("D:\\Java代码\\123.png"); 9 FileInputStream fis=new FileInputStream(file); 10 int count; 11 long start=System.currentTimeMillis(); 12 while((count=fis.read())!=-1) { 13 System.out.println(count); 14 } 15 long end=System.currentTimeMillis(); 16 System.out.println("======下面是所用的时间======"); 17 System.out.println(end-start); 18 } 19 20 }
结果如下:
下面是字符输入流:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 5 public class Demo10 { 6 7 public static void main(String[] args) throws IOException { 8 File file=new File("D:\\Java代码\\123.png"); 9 FileInputStream fis=new FileInputStream(file); 10 byte[] bt=new byte[1024]; 11 int count; 12 long start=System.currentTimeMillis(); 13 while((count=fis.read(bt))!=-1) { 14 System.out.println(count); 15 } 16 long end=System.currentTimeMillis(); 17 System.out.println("======下面是所用的时间======"); 18 System.out.println(end-start); 19 } 20 }
结果如下:
字节输入流读取文件花费了760毫秒,而字符输入流读取文件花费了3毫秒,由此可见,字符输入流的速度要比字节输入流更快。
文件字节输出流:
字节输出流:OutputStream 是所有输出流的超类
常用子类:FileOutputStream 文件字节输出流
构造方法:
FileOutputStream(File file) /FileOutputStream(String name)
注意:如果父目录不存在,会报FileNotFoundException异常,如果父目录存在,会创建一个新的文件,如果此时已经有文件存在,会覆盖原文件
FileOutputStream(File file,boolean flag)/FileOutputStream(String name,boolean flag)
注意:如果当前文件需要从文件末尾进行插入(接着文件里的内容继续写),必须将第二个参数设置为true,默认不写为false,会覆盖原文件
常用方法:
write(int)向文件中写入一个字节的值
write(byte[]) 向文件中写入一个数组的数据。
***③ write(byte[] offset len) 将 偏移量为 offset 的索引位置的长度为 len 的数据,写入到输出流中。
代码示例:
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 5 public class Demo11 { 6 7 public static void main(String[] args) throws IOException { 8 File file=new File("3.txt"); 9 FileOutputStream fos=new FileOutputStream(file); 10 11 fos.write("没有绝对的绝缘体,只有不努力的电压。".getBytes()); 12 } 13 }
执行结果,会在本项目的根目录下生成一个3.txt 文件,并且将内容写入进去。
文件复制:将一个文件通过IO流复制到另一个文件中去
代码示例:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class Demo12 { 7 8 public static void main(String[] args) throws IOException { 9 File file=new File("1.txt"); 10 FileInputStream fis=new FileInputStream(file); 11 FileOutputStream fos=new FileOutputStream(new File("4.txt")); 12 byte[] bt=new byte[1024]; 13 int count; 14 while((count=fis.read(bt))!=-1) { 15 fos.write(bt,0,count); 16 } 17 fis.close(); 18 fos.close(); 19 } 20 }
结果会将1.txt的内容复制到4.txt中
带缓冲区的字节流
1. 通过比较 read() 与 read(byte[]) 的方法复制文件的时间的长短,可以看出,带缓冲区的读写文件的速度快,
java 上提供了专门带缓冲区的字节流,用以提高读写速度。
2.BufferedInputStream /BufferedOutputStream 带缓冲区的字节输入 / 输出流
3. 结论: 带缓冲区的字节流 读取速度高于字节流
代码演示:
1 public class 带缓冲区的字节流 { 2 public static void main(String[] args) throws IOException { 3 /*FileInputStream fis=new FileInputStream(new File("src\\com\\ 文件复制 .java")); 4 // 复制操作 : 5 BufferedInputStream bis=new BufferedInputStream(fis);*/ 6 // // 读取 7 // BufferedInputStream bis=new BufferedInputStream(new FileInputStream(new File("src\\com\\ 文 8 件复制 .java"))); 9 // // 写入 10 // BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(new File("1.java")) 11 ); 12 // 读取 13 BufferedInputStream bis=new BufferedInputStream(new FileInputStream(new File("D:\\0318java 班 14 \\day08\\ 录屏 \\1_day08IO 流概述 .mp4"))); 15 // 写入 16 BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(new File("C:\\Users\\ 17 Administrator\\Desktop\\2.mp4"))); 18 byte[] bt=new byte[1024]; 19 int count=0; 20 long start=System.currentTimeMillis(); 21 while((count=bis.read(bt))!=-1) { 22 bos.write(bt, 0, count); 23 } 24 long end=System.currentTimeMillis(); 25 System.out.println(end-start); 26 bis.close(); 27 bos.close(); 28 } 29 }
jdk1.6 流的异常处理
1. 异常处理方式:
① try-catch-finally 异常的捕获
② throws 异常的声明
2. 以文件复制的形式来写流的异常处理 :
在 1.7jdk 之前包括 1.6 不包含 1.7 的流的异常处理形式。
代码演示:
1 public class 字节流的异常处理方式 { 2 public static void main(String[] args) { 3 // 为了在 finally 里面能够使用关闭资源,提升作用域 4 FileInputStream fis=null; 5 FileOutputStream fos=null; 6 try { 7 // 输入流 8 fis=new FileInputStream(new File("src\\com\\ 带缓冲区的字节流 .java")); 9 // 输出流 10 fos=new FileOutputStream(new File("2.java")); 11 // 文件复制 12 byte[] bt=new byte[1024]; 13 int count=0; 14 while((count=fis.read(bt))!=-1) { 15 fos.write(bt,0,count); 16 } 17 }catch(Exception e) { 18 e.printStackTrace(); 19 }finally { 20 close(fis, fos); 21 } 22 } 23 public static void close(InputStream fis,OutputStream fos) { 24 // 关闭资源 25 try { 26 // 为了防止空指针,需要判断不为 null 再关闭 27 if (fis!=null) { 28 fis.close(); 29 } 30 } catch (IOException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 try { 35 // 为了防止空指针,需要判断不为 null 再关闭 36 if (fos!=null) { 37 fos.close(); 38 } 39 } catch (IOException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 } 43 } 44 }
Jdk1_7 流的异常处理形式
1 public class Jdk1_7 流的异常处理形式 { 2 public static void main(String[] args) { 3 try( 4 FileInputStream fis=new FileInputStream(new File("src\\com\\ 带缓冲区的字节流 .java")); 5 FileOutputStream fos=new FileOutputStream(new File("3.java")); 6 ){ 7 /*Scanner sc=new Scanner(System.in); 8 sc.close();*/ 9 byte[] bt=new byte[1024]; 10 int count=0; 11 while((count=fis.read(bt))!=-1) { 12 fos.write(bt,0,count); 13 } 14 }catch (Exception e) { 15 e.printStackTrace(); 16 } 17 Scanner sc1=new Scanner(System.in); 18 String name = sc1.nextLine(); 19 } 20 }