黑马程序员_总结笔记之IO流(1)_基本流

来源:互联网 发布:网络银行系统架构 编辑:程序博客网 时间:2024/04/30 05:31
  • 字符流Reader Writer
    • FileReader & FileWriter
      • 读取文件对象必须存在

      • 创建一个字节数组来接收读取的数据
      • 例如:copy一个文本文件,包含异常处理代码:
        import java.io.*;public class FileReaderAndFileWriterDemo {public static void main(String[] args) {// TODO Auto-generated method stubReader reader = null;Writer writer = null;try{reader = new FileReader("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File1\\aaa.txt");writer = new FileWriter("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File2\\aaa.txt");char[] ch = new char[1024];int len = 0;while((len=reader.read(ch))!=-1)writer.write(ch,0,len);
      •  System.out.println("OK");}catch(IOException e){e.printStackTrace();}finally{if(reader != null){try{reader.close();}catch(IOException e){e.printStackTrace();}}if(writer != null){try{writer.close();}catch(IOException e){e.printStackTrace();}}}}}

    • BufferedReader&BufferedWriter
      • 创建缓冲区之前必须要有流对象,所以缓冲区没有无参构造方法,必须传入一个流对象
      • 提高流的操作效率
      • 关闭缓冲区,就是关闭缓冲区中的流对象
      • BufferedWriter:
        • 用缓冲区记得刷新
        • newLine();
      • BufferedReader:
        • 行的高效读取:String readLine();【不包含行终止符】
        • 有个子类 LineNumberReader,有get和set LineNumber的方法

      • 用缓冲区复制文本文件:
        import java.io.*;public class BufferedReaderAndBufferedWriterDemo {public static void main(String[] args) throws IOException {// TODO Auto-generated method stubBufferedReader bufr = new BufferedReader(new FileReader("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File1\\PicServer.java"));BufferedWriter bufw = new BufferedWriter(new FileWriter("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File2\\PicServer.java"));String line = null;while((line=bufr.readLine())!=null){bufw.write(line);bufw.newLine();  //换行bufw.flush();  //刷新}bufr.close();bufw.close();}}

      • FileReader与BufferedReader引出装饰设计模式:
        • 基于已有类进行功能增强
        • 通过构造方法接收被装饰的类
        • 例如自己写的MyBufferedReader装饰了Reader,以及自己写的LineNumberReader:
          import java.io.*;public class MyBufferedReader {private Reader r;public MyBufferedReader(Reader r) {super();this.r = r;}public String myReadLine() throws IOException{StringBuilder sb = new StringBuilder();int ch = 0;while((ch=r.read())!=-1){if(ch == '\r')continue;if(ch == '\n')return sb.toString();elsesb.append((char)ch);}if(sb.length()>0)return sb.toString();return null;}public void myClose() throws IOException{r.close();}}

          import java.io.*;public class MyLineNumberReader extends MyBufferedReader {private int lineNumber;public MyLineNumberReader(Reader r) {super(r);this.lineNumber = 0;// TODO Auto-generated constructor stub}@Overridepublic String myReadLine() throws IOException {// TODO Auto-generated method stublineNumber++;return super.myReadLine();}public int getLineNumber() {return lineNumber;}public void setLineNumber(int lineNumber) {this.lineNumber = lineNumber;}}

        • 继承和装饰的区别:装饰比继承灵活,避免了继承体系的臃肿。装饰类和被装饰类属于同体系,通常都继承同一个父类,比如A1、A2、A3、AA都继承A,AA装饰A1~A3
  • 字节流InputStream和OutputStream
    • OutputStream:write(byte[])【没用缓冲区时不需要刷新,因为都是一个一个字节写的】
    • FileInputStream和FileOutputStream
      • 三种读文件的方式:1.一个一个字节读 2.字节数组缓冲区读 3.用available()方法获取缓冲区长度,但小心内存溢出
      • 例:复制图片
        import java.io.*;public class FileInputStreamAndFileOutputStreamDemo {public static void main(String[] args) throws IOException{// TODO Auto-generated method stubInputStream in = new FileInputStream("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File1\\pizza.jpg");OutputStream out = new FileOutputStream("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File2\\pizza.jpg");byte[] b = new byte[1024];int len = 0;while((len=in.read(b))!=-1)out.write(b, 0, len);in.close();out.close();}}

        问:用字符流可以复制吗 答:复制完的图片可能打不开 如果字节查编码表查不到,那就会用相似的编码代替,最后文件的内容改变
    • 字节流缓冲流BufferedInputStream和BufferedOutputStream:
      • BufferedInputStream:使用时不用定义缓冲区,直接读取int
        public static void main(String[] args) throws IOException{// TODO Auto-generated method stubBufferedInputStream in = new BufferedInputStream(new FileInputStream("C:\\Users\\Desdemona\\Documents\\JavaWork\\IO\\File1\\aaa.txt"));int b = 0;while((b=in.read())!=-1)System.out.print((char)b);}

      • MyBufferedInputStream解释了缓冲区的读取方法:先读到字节数组里,然后一个一个取出
        import java.io.*;public class MyBufferedInputStream {private InputStream in;private byte[] buf=new byte[1024];private int count, off;public MyBufferedInputStream(InputStream in) {super();this.in = in;}public int myRead() throws IOException{if(count==0){count = in.read(buf);if(count<0)return -1;count--;return buf[off]&255;}else if(count>0){count--;off++;return buf[off]&255;}return -1;}public void myClose() throws IOException{in.close();}}

        注意int read() 方法将读出的字节补位为32位,write(int)方法将参数取最低八位写入,这是为了避免出现11111111,即-1,所以自己定义的myRead()方法要防止出现-1,所以&255
  • 转换流InputStreamReader与OutputStreamWriter
    • 字节流通向字符流的桥梁:InputStreamReader
      • 由键盘录入一行并输出问题想到readLine()方法,但System.in是InputStream,而readLine()是BufferedReader的方法;因此要在字节字符流之间转换
      • 例:从键盘读入一行数据并转换成大写输出,如果读到over,程序停止
        public static void main(String[] args) throws IOException{// TODO Auto-generated method stubBufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));String s = null;while((s=bfr.readLine())!=null){if("over".equals(s))break;System.out.println(s.toUpperCase());}bfr.close();}
    • 字符流通向字节流的桥梁:OutputStreamWriter
      • 例:修改以上程序,用字节流输出:
        public static void main(String[] args) throws IOException{// TODO Auto-generated method stubBufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));String s = null;while((s=bfr.readLine())!=null){if("over".equals(s))break;bfw.write(s.toUpperCase());bfw.newLine();bfw.flush();}bfr.close();bfw.close();}

        别忘记刷新~~~
    • 标准输入输出转换流写法:BfferedReader bufr =
      new BufferedReader(new InputStreamReader(System.in));

      new BufferedWriter bufw =
      new BufferedWriter(new OutputStreamWriter(System.out));
  • 总结:流操作规律
    1. 明确源和目的
    2. 操作的数据是否纯文本
    3. 明确使用哪个具体的对象(内存?硬盘?键盘/控制台?)
  • 插曲1:修改标准输入输出设备
    • System.setIn(InputStream)
    • System.setOut(PrintStream)
  • 插曲2:异常的日志信息
                    SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String s = date.format(new Date());PrintStream ps = new PrintStream("log.txt");ps.println(s);System.setOut(ps);new Exception().printStackTrace(ps);
  • 插曲3:获取系统信息
    Properties prop = System.getProperties();prop.list(System.out);
    list方法接收PrintStream参数


0 0