javase_14(字节流)

字节流的抽象基类:
InputStream(输入) OutPutStream(输出)
字符流的抽象基类:
Reader(读) Writer(写)
这四个类派生出来的子类都是由父类的名作为子类名的后缀.
IO需要了解的问题:
1.有了垃圾回收站为什么还要调用close方法去进行关闭
解答: 虽然java已经垃圾回收了这个流,但是系统根本就不知道什么时候关闭这个流,所以我们要手动的去关闭
2.为什么IO异常一定要处理嗯?
解答:如果io异常不处理的, 当读到一个文件的时候出现错误,那么后面的也就会执行不到了.所以我们一定要异常处理/..
字符流创建一个文件
1 FileWriter fw = new FileWriter(“src/a.txt”); //建立数据存放的文件 2 3 fw.writer(“test”); //把text写入到流中
关闭流资源,并将流中的数据进行清空到文件中.
如果想要在原文件中加入新的数据呢?
FileWriter fw = new FileWriter(“src/a.txt”,true);//代表从一个文件的末尾处追加 fw.writer(“happy”);
1.jpgCopy.class(对一个图片进行拷贝)
1 package com.javami.kudy.Code14; 2 import java.io.FileInputStream; 3 import java.io.IOException; 4 import java.io.FileOutputStream; 5 public class JpgCopy { 6 public static void main(String[]args) 7 { 8 FileInputStream fis = null; 9 FileOutputStream fos = null; 10 try 11 { 12 fis = new FileInputStream("src/a.jpg"); //输入一个图(输出(读) 输出(写)) 13 fos = new FileOutputStream("src/b.jpg"); 14 int len; 15 while((len=fis.read())!=-1) 16 { 17 fos.write(len); //输出(写入) 18 } 19 20 }catch(IOException e) 21 { 22 e.printStackTrace(); 23 } 24 finally 25 { 26 27 } 28 } 29 }
CloseUtil.class(自己写的一个工具关闭流)
1 package com.javami.kudy.Code14; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.OutputStream; 5 import java.io.Reader; 6 import java.io.Writer; 7 public class CloseUtil { 8 private CloseUtil(){} 9 public static void close(InputStream is,OutputStream os,Reader r,Writer w) throws IOException 10 { 11 try 12 { 13 is.close(); 14 } 15 finally 16 { 17 os.close(); 18 try 19 { 20 r.close(); 21 } 22 finally 23 { 24 w.close(); 25 } 26 } 27 } 28 }
System.currentTimeillis();//获取毫米数
自定义输入流:(读)
1 package com.javami.kudy.CodeBuffer; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 public class MyBufferedInputStream extends InputStream { 7 private InputStream is; 8 private byte[] buf = new byte[1024]; //假设我这边有1024个缓冲区 9 private int len; //默认为零 10 private int pos; //标记一下角标的个数 11 public MyBufferedInputStream(InputStream is) 12 { 13 this.is = is; 14 } 15 /* 16 * 1.需要考虑的问题? 17 * 思路: 18 * 加速 19 * FileInputStream is = new FileInputStream("src/a.jpg"); 20 */ 21 @Override 22 public int read() throws IOException 23 { 24 if(len==0) 25 { 26 len = is.read(buf); //一次性填充缓冲区(从这个文件中截取1024个放到buf里面去,返回的是最长的个数) 27 //角标pos置零 28 pos=0; 29 } 30 if(len==-1) 31 return -1; 32 len--; 33 //但是返回的这个byte有可能是-1 ,如果-1程序就错了 34 return buf[pos++]&0xff; //0xff代表:11111111 &00000000 00000000 00000000 11111111 35 //返回的结果是前面+24个08个1.这样就不会被当成-1处理啦 36 } 37 public void close()throws IOException 38 { 39 //关闭底层的流 40 is.close(); 41 } 42 43 }
自定义输出(写入)
1 package com.javami.kudy.CodeBuffer; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 6 public class MyBufferedOutputStream extends OutputStream { 7 private OutputStream op; 8 private byte[] buf = new byte[1024]; 9 int pos; 10 int len; 11 public MyBufferedOutputStream(OutputStream op) 12 { 13 this.op = op; 14 } 15 @Override 16 public void write(int b) throws IOException { 17 if(pos == 1024) 18 { 19 flush(); 20 pos = 0; 21 } 22 /* 23 * 外部执行的情况: 24 * while 不断往里面放入字节 25 * 内部实现: 判断是否满了.如果满了.我这边就刷新一下. 26 */ 27 buf[pos++] = (byte)b; 28 } 29 public void flush()throws IOException 30 { 31 op.write(buf,0,pos);//写入 : 输出(到一个指定的文件里面去) 32 } 33 public void close()throws IOException 34 { 35 op.close(); 36 } 37 38 }
测试几种用法的时间差:
1 package com.javami.kudy.CodeBuffer; 2 import java.io.BufferedOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.BufferedInputStream; 7 import com.javami.kudy.Code14.CloseUtil; 8 public class Mp3Copy { 9 public static void main(String[]agrs) 10 { 11 /* 12 //时间差 13 14 long Timedifference =end - start; 15 System.out.println(Timedifference);*/ 16 17 String source = "src/a.mp3"; //来源 18 String target = "src/d.mp3"; //目标 19 20 long start = System.currentTimeMillis(); 21 try 22 { 23 myTest(source,target); 24 } 25 catch(IOException e) 26 { 27 e.printStackTrace(); 28 } 29 long end = System.currentTimeMillis(); 30 System.out.println(end-start); //获取到时间差 31 System.out.println("hello"); 32 } 33 /* 34 * 单个拷贝字节: 毫秒大概是: 50000~60000之间 35 */ 36 private static void FileInputStreamTest(String source,String target)throws IOException 37 { 38 FileInputStream fls = null; 39 FileOutputStream fos = null; 40 try 41 { 42 fls = new FileInputStream(source); 43 fos = new FileOutputStream(target); 44 int ch; 45 while((ch=fls.read())!=-1) 46 { 47 fos.write(ch); 48 } 49 } 50 finally 51 { 52 CloseUtil.close(fls, fos, null, null); 53 } 54 } 55 /* 56 * 通过包装类来拷贝 缓存---> 593 57 */ 58 private static void BufferedTest(String source,String target)throws IOException 59 { 60 BufferedInputStream bis= null; //读(输入) 61 BufferedOutputStream bos = null; //写(输出) 62 try 63 { 64 bis = new BufferedInputStream(new FileInputStream(source)); 65 bos = new BufferedOutputStream(new FileOutputStream(target)); 66 int len; 67 while((len=bis.read())!=-1) //把左边的内容读到底层的一个bis[pos++]之后再从缓冲区里面返回 68 { 69 bos.write(len); 70 } 71 } 72 finally 73 { 74 CloseUtil.close(bis, bos, null, null); 75 } 76 } 77 /* 78 * 用户自定义的缓存数组: 94 79 */ 80 private static void copyMp3ByBuf(String source,String target)throws IOException 81 { 82 FileInputStream fis = null; 83 FileOutputStream fos = null; 84 try 85 { 86 fis = new FileInputStream(source); 87 fos = new FileOutputStream(target); 88 byte[] buf = new byte[1024]; 89 int ch; 90 while((ch=fis.read(buf))!=-1) 91 { 92 fos.write(buf); 93 } 94 } 95 finally 96 { 97 CloseUtil.close(fis, fos, null, null); 98 } 99 } 100 /* 101 * 用自己写的包装输入输出字节流 102 * 203 103 * 通过比较得出的结论: 104 * 105 */ 106 private static void myTest(String source,String target )throws IOException 107 { 108 MyBufferedInputStream mis = null; 109 MyBufferedOutputStream mos = null; 110 try 111 { 112 mis = new MyBufferedInputStream(new FileInputStream(source)); 113 mos = new MyBufferedOutputStream(new FileOutputStream(target)); 114 int b; 115 while((b=mis.read())!=-1) 116 { 117 mos.write(b); 118 } 119 } 120 finally 121 { 122 CloseUtil.close(mis, mos, null, null); 123 } 124 } 125 }
关闭流的工具类:
1 package com.javami.kudy.Code14; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.OutputStream; 5 import java.io.Reader; 6 import java.io.Writer; 7 public class CloseUtil { 8 private CloseUtil(){} 9 public static void close(InputStream is,OutputStream os,Reader r,Writer w) throws IOException 10 { 11 try 12 { 13 if(is!=null) 14 is.close(); 15 } 16 finally 17 { 18 if(os!=null) 19 os.close(); 20 try 21 { 22 if(r!=null) 23 r.close(); 24 } 25 finally 26 { 27 if(w!=null) 28 w.close(); 29 } 30 } 31 } 32 }
其实字符流的底层实现是需要字节流的
1 package com.javami.kudy.CodeBuffer; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.OutputStream; 6 import java.io.OutputStreamWriter; 7 8 public class MyFileWriter extends OutputStreamWriter { 9 10 /* 11 * 如果你放进去一个字符流! 12 * 我们通过底层调用父类的字节流.帮你处理这个数据 13 */ 14 public MyFileWriter(String name)throws IOException 15 { 16 //底层实现原理: 其实调用字符流底层是字节流实现的?为何呢? 17 super(new FileOutputStream(name)); 18 } 19 20 public MyFileWriter(String name,boolean is)throws IOException 21 { 22 super(new FileOutputStream(name,true)); 23 } 24 25 }
关于字节流转字符流
1 package com.javami.kudy.PM; 2 import java.io.BufferedReader; 3 import java.io.BufferedWriter; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.OutputStream; 8 import java.io.PrintStream; 9 import java.io.OutputStreamWriter; 10 import java.io.Reader; 11 import java.io.Writer; 12 13 import com.javami.kudy.Code14.CloseUtil; 14 public class TreasStreamTest { 15 /* 16 * 字节流转换成字符流 17 * 思路: 18 * 1.首先要获取到输入流与输出流 19 * 2.(字符流) == <-- InputStreamReader--> (输入流) 20 3.(字符流) == <--OutputStream-->(输出流) 21 */ 22 public static void main(String[]args) 23 { 24 /*//1.获取输入流 25 InputStream ism = System.in; 26 //2.获取输出流 27 PrintStream pts = System.out; 28 //3.字符流(读)-->输入流 转换 29 InputStreamReader isr = new InputStreamReader(ism); 30 //4.字符流(写)-->输出留 31 OutputStreamWriter osr = new OutputStreamWriter(pts); 32 //5.转换成父类型的引用可以指向子类型的对象(转换成字符流的读) 33 Reader r = isr; 34 //6.转换成父类型的引用可以指向子类型的对象(转换成字符流的写) 35 Writer w = osr; 36 //包装字符流 37 BufferedReader br = new BufferedReader(r);//包装 38 BufferedWriter bw = new BufferedWriter(w); 39 关于执行速度--> 40 */ 41 //从字节流转换成字符流的步骤 42 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 43 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 44 try 45 { 46 String line; 47 while(true) 48 { 49 line = br.readLine(); //读一行 50 bw.write(line); //写一行 51 bw.newLine(); 52 bw.flush(); //刷新-->从流里面刷新一下.因为它是属于打一行打一行的概率 53 if("bye".equals(br)) 54 break; 55 } 56 } 57 catch(IOException e) 58 { 59 e.printStackTrace(); 60 } 61 finally 62 { 63 try 64 { 65 CloseUtil.close(null, null, br, bw); 66 } 67 catch(IOException e) 68 { 69 e.printStackTrace(); 70 } 71 } 72 } 73 }
流程图:
System.in(读)
System.out(写)
BufferedReader br = new BufferedReader(new InputStream(System.in)); //把输入流转换成包装的读
BufferedWriter bw = new BufferedWriter(new OutputStream(System.out)); //把输出流转换成包装的写
BuffferedReader对标准输入System.in进行包装,实现读取键盘上输入的一行
注意:
如果想要实现读一行,打一行↓
String line br.readLine(); //第一行
bw.writer(line);
bw.newLine(); //换行
bw.flush()刷新一下流
1 /** 2 * 测试题5 3 * 输入学生新,按break终止,每个学生有3门课的成绩,定义一种比较直观的文本文件格式, 4 输入学生姓名和成绩,从键盘输入以上数据(包括姓名,三门课成绩), 5 按总分数从高到低的顺序将学生信息存放在磁盘文件"stu.txt"中。 6 思路: 7 1.读取键盘,一行输入一个学生的信息,封装成学生对象 8 2.将学生对象存入一个TreeSet按总分排序 9 3.遍历TreeSet集合,取出所有的学生信息,输出到stu.txt中 10 */ 11 12 package com.javami.kudy.PM; 13 import java.io.BufferedReader; 14 import java.io.BufferedWriter; 15 import java.io.FileWriter; 16 import java.io.IOException; 17 import java.io.InputStreamReader; 18 import java.util.Comparator; 19 import java.util.TreeSet; 20 public class Test { 21 public static void main(String[]args) 22 { 23 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){ 24 25 //比较器 26 @Override 27 public int compare(Student s1, Student s2) { 28 int num = s1.getSum()-s2.getSum(); 29 if(num!=0) 30 return -num; 31 return s1.getName().compareTo(s2.getName()); 32 } 33 34 }); 35 try 36 { 37 saveStuInfo(ts); 38 listStuInfo(ts); 39 } 40 catch(IOException e) 41 { 42 e.printStackTrace(); 43 } 44 } 45 /* 46 * 遍历集合里面的内容,把它写入到一个文件名里面 47 */ 48 private static void listStuInfo(TreeSet<Student> ts)throws IOException 49 { 50 BufferedWriter bw = null; 51 try 52 { 53 bw = new BufferedWriter(new FileWriter("src/a.txt")); 54 for(Student str : ts) 55 { 56 //一定要标记为toString 为啥呢? 因为它是不会自动的打印toString的 57 bw.write(str.toString()); 58 bw.newLine(); 59 } 60 } 61 finally 62 { 63 bw.close(); 64 } 65 } 66 /* 67 * 读取键盘 68 * 获取学习的对象 69 * 把学习的对象存入ts里面去 70 */ 71 public static void saveStuInfo(TreeSet<Student> ts)throws IOException 72 { 73 //当你读的时候,我们要求它用逗号分隔 74 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//输入-?读 75 try 76 { 77 String line; 78 while(true) 79 { 80 line = br.readLine(); //读一行 81 if("break".equals(line)) 82 break; 83 //将line分隔成4部分 84 String[]bufs = line.split(","); 85 Student s = new Student(bufs[0],Integer.parseInt(bufs[1]) 86 ,Integer.parseInt(bufs[2]) 87 ,Integer.parseInt(bufs[3])); 88 ts.add(s); 89 } 90 } 91 finally 92 { 93 br.close(); 94 } 95 } 96 } 97 98 class Student 99 { 100 private String name; 101 private int chinese; //语文成绩 102 private int math; //数学成绩 103 private int english; //英语成绩 104 private int sum; //总分 105 public Student(String name,int chinese,int math,int english) 106 { 107 this.name = name; 108 this.chinese = chinese; 109 this.math = math; 110 this.english = english; 111 this.sum = chinese+math+english; 112 } 113 public int getSum() 114 { 115 return sum; 116 } 117 public String getName() 118 { 119 return name; 120 } 121 @Override 122 public String toString() 123 { 124 return "姓名:"+name+"语文成绩:"+chinese+"数学成绩:"+math+"英语成绩:"+english; 125 } 126 127 }
浙公网安备 33010602011771号