1、字节流的两个基类
字节流的两个基类分别为:写入OutputStream和读取InputStream
2、字节输出流
字节输出流使用的是OutputStream
public abstract class OutputStreamextends Objectimplements Closeable, Flushable |
本类是一个抽象类,根据面向对象的概念,要通过子类进行对象的实例化操作
在此类中常用的方法
Public void write(byte[]b)throws IOException:写入一组数据 Public void write(byte b)throws IOException:写入一个数据 Public void close()throws IOException:关闭流 |
例:把数据写到一个文件中去
package com.itheima.io1; import java.io.File; import java.io.FileOutputStream; public class OutputStreamDemo1 { public static void main(String[] args) { //定义一个字节输出流 FileOutputStream fos=null; try{ //实例化字节流对象 File file=new File("d:"+File.separator+"a.txt"); if(!file.exists()){//判断文件是否存在,不存在则创建 file.createNewFile(); } fos=new FileOutputStream(file); //定义一个字符串数据 String str="黑马程序员"; //因为字节流只能以字节或字节数组的形式读取 fos.write(str.getBytes()); }catch(Exception e){ e.printStackTrace(); }finally{//一定要执行的关闭流,释放资源 try{ //判断fos是否为null if(fos!=null) fos.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
从上面的程序可以看出与字符流的写入基本相同,只是字符流可以直接写入字符串,而字节流不需要刷新。
如果想在已有的文件中追加数据,怎样呢?
package com.itheima.io1; import java.io.File; import java.io.FileOutputStream; public class OutputStreamDemo1 { public static void main(String[] args) { //定义一个字节输出流 FileOutputStream fos=null; try{ //实例化字节流对象 File file=new File("d:"+File.separator+"a.txt"); if(!file.exists()){//判断文件是否存在,不存在则创建 file.createNewFile(); } fos=new FileOutputStream(file,true); //定义一个字符串数据 String str="黑马程序员_1"; //因为字节流只能以字节或字节数组的形式读取 fos.write(str.getBytes()); }catch(Exception e){ e.printStackTrace(); }finally{//一定要执行的关闭流,释放资源 try{ //判断fos是否为null if(fos!=null) fos.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
3、字节输入流
字节输入流可以使用InputStream,
public abstract class InputStream extends Object implements Closeable |
此类是一个抽象类,如果是文件输入,使用FileInputStream
Public abstract int read()throws IOException:读取一个字节 Public int read(byte[] b)throws IOException:读取一组内容 Public void close()throws IOException:关闭流 |
例:从文件中读出输入到控制台上
方法一:按字节读取
package com.itheima.io1; import java.io.File; import java.io.FileInputStream; public class InputStreamDemo1 { public static void main(String[] args) { //定义一个字节输入流 FileInputStream fis=null; try{ //实例化字节流对象 File file=new File("d:"+File.separator+"a.txt"); fis=new FileInputStream(file); //定义一个整型数据 int ch=0; while((ch=fis.read())!=-1){ System.out.print((char)ch); } }catch(Exception e){ e.printStackTrace(); }finally{//一定要执行的关闭流,释放资源 try{ //判断fis是否为null if(fis!=null) fis.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
方法二:按字节数据读取
package com.itheima.io1; import java.io.File; import java.io.FileInputStream; public class InputStreamDemo1 { public static void main(String[] args) { //定义一个字节输入流 FileInputStream fis=null; try{ //实例化字节流对象 File file=new File("d:"+File.separator+"a.txt"); fis=new FileInputStream(file); //定义一个字节数组 byte[]buf=new byte[1024*1024]; int len=0; while((len=fis.read(buf))!=-1){ System.out.print(new String(buf,0,len)); } }catch(Exception e){ e.printStackTrace(); }finally{//一定要执行的关闭流,释放资源 try{ //判断fis是否为null if(fis!=null) fis.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
上面的两种方法与字符流基本相同,还有一种字节流独有的方法,FileInputStream中有一个方法返回文件的长度available(0,但是如果文件过大如视频,建议不要使用这种方法。
例如:
package com.itheima.io1; import java.io.File; import java.io.FileInputStream; public class InputStreamDemo2 { public static void main(String[] args) { //定义一个字节输入流 FileInputStream fis=null; try{ //实例化字节流对象 File file=new File("d:"+File.separator+"a.txt"); fis=new FileInputStream(file); //创建一个字节数组 byte[]buf=new byte[fis.available()]; System.out.print(new String(buf)); }catch(Exception e){ e.printStackTrace(); }finally{//一定要执行的关闭流,释放资源 try{ //判断fis是否为null if(fis!=null) fis.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
4、字节流的缓冲区
BufferedInputStream和BufferedOutputStream与字符流一样,不过字节流读取时没有读一行的方法,只能用字节或字节数组读取
5、读取键盘的录入
System.out:对应的是标准输出设备,控制台 System.in:对应的是标准输入设备,键盘 |
例:录入一行数时,将该行数打印,如果录入的是over那么停止。
package com.itheima.io1; import java.io.InputStream; public class Demo1 { public static void main(String[] args)throws Exception { //创建一个输入流 InputStream in=System.in; //把存入的数据放在缓冲区中 StringBuffer buf=new StringBuffer(); while(true){ int ch=in.read();//读取数据 if(ch=='\r') continue; if(ch=='\n'){ //把字符转化成字符串输出 String str=buf.toString(); //如果遇到over,就停止 if("over".equals(str)){ break; } //编程大写输出 System.out.println(str.toUpperCase()); //取出后清空缓冲区 buf.delete(0, buf.length()); }else{//如果没有遇到回车符,就继续往缓冲中添加 buf.append((char)ch); } } } } |
上述代码其实就是读一行的原理,能不能直接使用readLine方法完成键盘录入数据呢?
readLine方法是字符流BufferedReader类中的方法,而键盘录入时read方法是字节流InputStream中的方法,那么能不能将字节流转换成字符流呢
package com.itheima.io1; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class Demo2 { public static void main(String[] args)throws Exception { //创建一个输入流 InputStream in=System.in; //将字节流转换成字符流 InputStreamReader ir=new InputStreamReader(in); //利用BufferedReader BufferedReader bufr=new BufferedReader(ir); String line=null; while((line=bufr.readLine())!=null){ //读取的内容编程大写输出 System.out.println(line.toUpperCase()); if("over".equals(line)){ break; } } bufr.close(); } } |
6、字节流的应用
例一:用键盘录入然后再控制台输出
这个就是上面的代码的实现
例二:从键盘录入的数据存到文件中
分析:源:键盘录入
目的:文件
package com.itheima.io1; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class Demo3 { public static void main(String[] args) { //定义一个输入流 BufferedReader bufr=null; //定义一个输出流 BufferedWriter bufw=null; try{ //实例化输入流 bufr=new BufferedReader(new InputStreamReader(System.in)); //实例化输出流 bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"))); String line=null; while((line=bufr.readLine())!=null){ //向文件中写入读取的内容 bufw.write(line); //换行 bufw.newLine(); bufw.flush(); } }catch(Exception e){ e.printStackTrace(); }finally{//关闭流 try{ if(bufw!=null) bufw.close(); if(bufr!=null) bufr.close(); }catch(Exception e){ e.printStackTrace(); } } } } |
例三:想要将一个文件的数据打印到控制台
分析:源:文件
目的:控制台
只需把上面的代码作如下修改即可:
//实例化输入流 bufr=new BufferedReader( new InputStreamReader(new FileInputStream("a.txt"))); //实例化输出流 bufw=new BufferedWriter(new OutputStreamWriter(System.out)); |
7、流操作的基本规律
(1)明确源和目的
源:输入流Inputstream Reader 目的:输出流Outputstream Writer |
(2)操作的数据是否是纯文本
是:用字符流 不是:用字节流 |
(3)当体系明确后,在明确使用哪个具体的对象,通过设备来进行区分
源设备:内存 硬盘 键盘 目标设备:内存 硬盘 控制台 |
问题:什么时候用到转换流
转换流是字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流,系统默认的编码为GBK,转换为UTF-8
OutputStreamWriter(new OutputStream(“a.txt”),”UTF-8”); |