- 字符流Reader Writer
- FileReader & FileWriter
-
读取文件对象必须存在
- 创建一个字节数组来接收读取的数据
- 例如:copy一个文本文件,包含异常处理代码:
import java.io.*; public class FileReaderAndFileWriterDemo { public static void main(String[] args) { // TODO Auto-generated method stub Reader 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 stub BufferedReader 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(); else sb.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 } @Override public String myReadLine() throws IOException { // TODO Auto-generated method stub lineNumber++; return super.myReadLine(); } public int getLineNumber() { return lineNumber; } public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } }
- 继承和装饰的区别:装饰比继承灵活,避免了继承体系的臃肿。装饰类和被装饰类属于同体系,通常都继承同一个父类,比如A1、A2、A3、AA都继承A,AA装饰A1~A3
- FileReader & FileWriter
- 字节流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 stub InputStream 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 stub BufferedInputStream 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
- BufferedInputStream:使用时不用定义缓冲区,直接读取int
- OutputStream:write(byte[])【没用缓冲区时不需要刷新,因为都是一个一个字节写的】
- 转换流InputStreamReader与OutputStreamWriter
- 字节流通向字符流的桥梁:InputStreamReader
- 由键盘录入一行并输出问题想到readLine()方法,但System.in是InputStream,而readLine()是BufferedReader的方法;因此要在字节字符流之间转换
- 例:从键盘读入一行数据并转换成大写输出,如果读到over,程序停止
public static void main(String[] args) throws IOException{ // TODO Auto-generated method stub BufferedReader 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 stub BufferedReader 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));
- 字节流通向字符流的桥梁:InputStreamReader
- 总结:流操作规律
- 明确源和目的
- 操作的数据是否纯文本
- 明确使用哪个具体的对象(内存?硬盘?键盘/控制台?)
- 插曲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:获取系统信息
list方法接收PrintStream参数Properties prop = System.getProperties(); prop.list(System.out);
黑马程序员_总结笔记之IO流(1)_基本流
最新推荐文章于 2023-10-06 11:15:24 发布