1、IO流
处理设备之间的数据传输
字符流为了处理文字而存在,基于字节流,其中融合了编码表
(1)字节流的抽象基类
InputString OutputStream
(2)字符流的抽象基类
Reader Writer
1.1、字符流Writer--------write,flush,close
java.util.FileWriter
FileWriter(String fileName)根据给定的文件名构造一个FileWriter对象
java.io.OutputStreamWriter
void write(String str, int off, int len)将数据写入流中
void flush()刷新流中的缓冲
void close()关闭此流,但要先刷新它
1 import java.io.FileWriter; 2 import java.io.IOException; 3 4 /* 5 * 字符流和字节流 6 * 7 * 字节流两个基类 8 * InputStream OutputStream 9 * 10 * 字符流两个基类 11 * Reader Writer 12 * 13 * 先学习一下字符流的特点 14 * 既然IO流是用于操作数据的 15 * 那么数据的最常见体现形式是文件 16 * 17 * 那么先以操作文件为主来演示 18 * 需求: 在硬盘上,创建一个文件并写入一些文字数据 19 * 20 * 找到一个专门用于操作文件的Writer子类对象,FileWriter。后缀名是父类名,前缀名是该流对象的功能 21 * */ 22 public class FileWriterDemo { 23 public static void main(String[] args) throws IOException{ 24 //创建一个FileWriter对象,该对象以被初始化就必须要明确被操作的文件 25 //而且该文件会被创建到制定目录下,如果该目录下已有同名文件,会被覆盖 26 //其实就是明确数据要存放的目的地 27 FileWriter fw = new FileWriter("demo.txt"); 28 29 //调用write方法,将字符串写入到流中 30 fw.write("abcde"); 31 32 //刷新流对象中的缓冲中的数据 33 // fw.flush(); 34 35 36 //关闭流资源,但是关闭之前会刷新一次内部缓冲数据 37 //将数据刷到目的地中,和flush的区别在于 38 //和flush区别,flush刷新后,流可以继续使用,close刷新后会将流关闭 39 fw.close(); 40 } 41 42 }
运行结果
1.2、异常处理机制
注意close放入finally,但是也需要排除流创建失败带来的空指针异常,因此需要一个判断
1 package learn; 2 3 import java.io.FileWriter; 4 import java.io.IOException; 5 6 /*IO异常的处理方式 7 * 8 * */ 9 public class FileWriterDemo2 { 10 public static void main(String[] args) { 11 FileWriter fw =null;//对象的建立和引用的挂钩分开写 12 try 13 { 14 //fw创建失败则不可能添加数据,故放在一个try中 15 fw = new FileWriter("demo.txt"); 16 fw.write("abcdefg"); 17 18 } 19 catch(IOException e) 20 { 21 System.out.println(e.toString()); 22 } 23 //必须要关闭流,所以必须写finally, 24 //但是因可能出现没流建立成功,没流能关闭,所以也将关闭写作异常 25 //finally的执行也需要 fw不为空时才可以 26 finally 27 { 28 try 29 { 30 if(fw!=null) 31 fw.close(); 32 } 33 catch(IOException e) 34 { 35 System.out.println(e.toString()); 36 } 37 38 } 39 40 } 41 }
运行结果
1.3、文件的续写
java.io.FileWriter
FileWriter(String fileName, boolean append)根据指定的文件名以及指示是否附加写入数据的boolean值得来构造FileWriter对象。true则在末尾处添加
windows中的换行符为/r/n,因而只写/n得到的是黑块
1 package learn; 2 3 import java.io.FileWriter; 4 import java.io.IOException; 5 6 /* 7 * 演示对已有文件的数据续写 8 * */ 9 public class FileWriterDemo3 { 10 public static void main(String[] args) throws IOException{ 11 //传递一个true参数,代表不覆盖已有的文件,并在已有文件末尾处进行数据续写 12 FileWriter fw= new FileWriter("demo.txt",true); 13 fw.write("ha ha"); 14 fw.close(); 15 } 16 }
运行结果
2.1、字符流Reader
文本读取方式一
java.io.Reader
int read() 读取单个字符,一直读下去的话,末尾返回值为-1
1 package learn; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 public class FileReadDemo { 7 public static void main(String[] args) throws IOException{ 8 //创建一个文件读取流对象,和指定名称的文件相关联 9 //要保证文件是已经存在的,如果不存在,会发生异常FileNotFoundException 10 FileReader fr = new FileReader("demo.txt"); 11 //调用读取流对象的read方法 12 //read方法一次读一个字符,且会自动往下读 13 int ch = 0; 14 while((ch=fr.read())!=-1) 15 { 16 System.out.println((char)ch); 17 } 18 fr.close(); 19 } 20 }
运行结果
2.2、文本读取方式二
先创建一个数组,读一个存一个,读完了,输出。
java.lang.String
String(int[] codePoints, int offset, int count)分配一个新的String, 它包含Unicode代码点数组参数一个子数组的字符
offset初始偏移量, count长度,(长度即为下例中的num)
1 package learn; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 public class FileReadDemo2 { 7 public static void main(String[] args) throws IOException{ 8 FileReader fr = new FileReader("demo.txt"); 9 //定义一个字符数组,用于存储读到字符 10 //该read(char[])返回的是读到字符个数 11 //通常定义new char[1024]; 12 //创建字符数组,大小为3 13 char[] buf = new char[3]; 14 int num = 0; 15 //读一个存一下 16 while((num = fr.read(buf))!=-1) 17 { 18 System.out.println(new String(buf,0,num)); 19 } 20 // int num = fr.read(buf); 21 // System.out.println("num="+num+"..."+new String(buf)); 22 fr.close(); 23 } 24 }
运行结果
2.2.1、练习
当文件内容超过了1024,才会出现println的换行
1 package Test; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 /*读取一个.java文件,并打印在控制台上*/ 7 public class FileReaderTest { 8 public static void main(String[] args) throws IOException{ 9 FileReader fr = new FileReader("FileReadDemo.java"); 10 char[] buf = new char[1024]; 11 int num = 0; 12 while((num = fr.read(buf))!=-1) 13 { 14 System.out.println(new String(buf,0,num)); 15 } 16 fr.close(); 17 } 18 }
运行结果
2.3、copy
copy2更好
思路:有了存放的地方,先读,临时存放下,再一起写入
1 package Test; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 /* 8 * 将C盘一个文本文件复制到D盘 9 * 复制的原理: 10 * 其实就是将C盘下的文件数据存储到D盘的一个文件中 11 * 12 * 步骤: 13 * 1、在D盘创建文件。用于存储C盘文件中的数据 14 * 2、定义读取流和C盘文件关联 15 * 3、通过不断你的读写完成数据存储 16 * 4、关闭资源 17 * */ 18 public class CopyText { 19 public static void main(String[] args) throws IOException { 20 copy2(); 21 } 22 //从c盘读一个字符写一个字符 23 public static void copy1 ()throws IOException 24 { 25 //创建目的地 26 FileWriter fw = new FileWriter("RuntimeDemo_copy.txt"); 27 //与已有文件关联 28 FileReader fr = new FileReader("FileReadDemo.java"); 29 int ch = 0; 30 //有一个字符写一次 31 while((ch=fr.read())!=-1) 32 { 33 fw.write(ch); 34 } 35 fw.close(); 36 fr.close(); 37 38 } 39 public static void copy2() 40 { 41 FileWriter fw = null; 42 FileReader fr = null; 43 try 44 { 45 fw = new FileWriter("SystemDe_copy2.txt"); 46 fr = new FileReader("FileReadDemo.java"); 47 char[] buf= new char[1024]; 48 int len = 0; 49 while((len=fr.read(buf))!=-1) 50 { 51 fw.write(buf,0,len); 52 } 53 } 54 catch(IOException e) 55 { 56 throw new RuntimeException("读写失败"); 57 } 58 finally 59 { 60 if(fr!=null) 61 try 62 { 63 fr.close(); 64 } 65 catch(IOException e) 66 { 67 } 68 if(fw!=null) 69 try 70 { 71 fw.close(); 72 } 73 catch(IOException e) 74 { 75 } 76 } 77 } 78 }
运行结果
3、字符流的缓冲区
3.1、BufferedWriter
java.io.BufferedWriter
void newLine();写入一个换行符,通用于各操作系统,在win中换成 ,在linux中换成
因为有流才会有缓冲区,故其构造函数都带有参数
1 package learn; 2 3 import java.io.BufferedWriter; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 /* 8 * 缓冲区的出现时为了提高流的操作效率而出现的 9 * 所以在创建缓冲区之前,必须要先有流对象 10 * 该缓冲区中提供了跨平台的换行符newLine(); 11 * */ 12 public class BufferedWriterDemo { 13 public static void main(String[] args)throws IOException { 14 //创建字符写入流对象 15 FileWriter fw = new FileWriter("buf.txt"); 16 //为了提高字符写入流效率,加入了缓冲技术 17 //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可 18 BufferedWriter bufw = new BufferedWriter(fw); 19 for(int x=1;x<5;x++) 20 { 21 bufw.write("abcd"+x); 22 bufw.newLine(); 23 bufw.flush(); 24 } 25 26 //记住,只要用到缓冲区就要记得刷新 27 //其实关闭缓冲区就是在关闭缓冲区中的流对象 28 bufw.flush(); 29 bufw.close(); 30 31 } 32 }
运行结果
3.2、BufferedReader
java.io.BufferedReader
String readLine()读取文本下一行
1 package learn; 2 /* 3 * 字符流取流缓冲区: 4 * 该缓冲区提供了一个一次读一行的方法readLine, 方便于对文本数据的获取。 5 * 当返回null时,表示读到文件末尾。 6 * */ 7 import java.io.BufferedReader; 8 import java.io.FileReader; 9 import java.io.IOException; 10 11 public class BufferedReaderDemo { 12 public static void main(String[] args) throws IOException{ 13 //创建一个读取流对象和文件相关联 14 FileReader fr = new FileReader("buf.txt"); 15 //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数 16 BufferedReader bufr = new BufferedReader(fr); 17 String line = null; 18 while((line=bufr.readLine())!=null) 19 { 20 System.out.println(line); 21 } 22 // String s1 = bufr.readLine(); 23 // System.out.println("s1:"+s1); 24 bufr.close(); 25 26 } 27 }
运行结果
3.2.2练习 通过缓冲区复制文件
readLine不返回回车符,即会卡在一行所以在write时须加newLine();
1 package learn; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 9 /* 10 * 通过缓冲区复制一个java文件 11 * readLine不返回车符 12 * */ 13 public class CopyTextByBuf { 14 public static void main(String[] args) { 15 BufferedReader bufr = null; 16 BufferedWriter bufw = null; 17 try 18 { 19 bufr = new BufferedReader(new FileReader("FileReadDemo.java")); 20 bufw = new BufferedWriter(new FileWriter("bufWriter_Copy.txt")); 21 String line =null; 22 while((line=bufr.readLine())!=null) 23 { 24 bufw.write(line); 25 //不加就在一行 26 bufw.newLine(); 27 bufw.flush(); 28 } 29 } 30 catch(IOException e) 31 { 32 throw new RuntimeException("读写失败"); 33 } 34 finally 35 { 36 try 37 { 38 if(bufr!=null) 39 bufr.close(); 40 } 41 catch(Exception e) 42 { 43 throw new RuntimeException("读取关闭失败"); 44 } 45 try 46 { 47 if(bufw!=null) 48 bufr.close(); 49 } 50 catch(Exception e) 51 { 52 throw new RuntimeException("写入关闭失败"); 53 } 54 } 55 } 56 }
运行结果
3.3、自写ReadLine
注意,如果原文件结尾没有换行符,则会导致最后一行进入了缓冲区却没被刷入流中,
通过判断缓冲区是否为空来返回至流中
1 package learn; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 6 /* 7 * 明白了BufferedReader类中特有方法readLine的原理后, 8 * 可以自定义一个类包含一个功能和readLine一致的方法 9 * 来模拟一下BufferedReader 10 * */ 11 class MyBufferedReader 12 { 13 private FileReader r; 14 MyBufferedReader(FileReader r) 15 { 16 this.r=r; 17 } 18 //可以一次读一行的方法 19 public String myReadLine() throws IOException 20 { 21 //定义一个临时容器,源BufferReader封装的是字符数组 22 //为了掩饰方便,定义一个StringBuilder容器。因为最终还是要将数据变成字符串 23 StringBuilder sb = new StringBuilder(); 24 int ch = 0; 25 while((ch=r.read())!=-1) 26 { 27 //是 则继续往ch里添加下一个字符,而不添加 28 //是 则返回toString, 29 //不然就是其他字段,则继续往缓冲区sb里添加 30 if(ch==' ') 31 continue; 32 if(ch==' ') 33 return sb.toString(); 34 else 35 sb.append((char)ch); 36 } 37 //如果没有换行符,则数据被读取,放入了缓冲区,没刷到流中 38 if(sb.length()!=0) 39 return sb.toString(); 40 return null; 41 } 42 public void myclose()throws IOException 43 { 44 r.close(); 45 } 46 } 47 public class MyBufferedReaderDemo { 48 public static void main(String[] args) throws IOException{ 49 FileReader fr = new FileReader("buf.txt"); 50 MyBufferedReader myBuf = new MyBufferedReader(fr); 51 String line = null; 52 while((line = myBuf.myReadLine())!=null) 53 { 54 System.out.println(line); 55 } 56 myBuf.myclose(); 57 } 58 }
运行结果
3.4、装饰设计模式
比继承灵活,避免了体系臃肿,降低了类与类之间的关系
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能
所以装饰类和被装饰类通常是都属于一个体系中的
1 package learn; 2 /* 3 * 装饰设计模式 4 * 当想要对已有的对象进行功能增强时, 5 * 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能 6 * 那么自定义的该类称为装饰类 7 * Person和SuperPerson同属于一个接口/类 8 * 装饰类通常会通过构造函数接受被装饰的对象 9 * 并基于被装饰的对象的功能,提供更强的功能 10 * */ 11 12 class Person{ 13 public void chifan(){ 14 System.out.println("吃饭"); 15 } 16 } 17 18 class SuperPerson{ 19 private Person p; 20 SuperPerson(Person p) 21 { 22 this.p=p; 23 } 24 public void superChifan() 25 { 26 System.out.println("开胃酒"); 27 p.chifan(); 28 System.out.println("甜点"); 29 System.out.println("来一根"); 30 } 31 } 32 public class PersonDemo { 33 public static void main(String[] args) { 34 Person p =new Person(); 35 //p.chifan(); 36 SuperPerson sp = new SuperPerson(p); 37 sp.superChifan(); 38 } 39 }
3.5、LineNumberReaderDemo
切记,注意类名。。。。
(因类名和包名冲突导致包调入失败等等引发的一系列明明没错却显示错误BUG。。。。)
1 package learn; 2 3 import java.io.FileReader; 4 import java.io.IOException; 5 import java.io.LineNumberReader; 6 7 8 9 10 public class LineNumberReaderDemo { 11 public static void main(String[] args)throws IOException { 12 FileReader fr = new FileReader("FileReadDemo.java"); 13 LineNumberReader lnr = new LineNumberReader(fr); 14 String line = null; 15 lnr.setLineNumber(100); 16 while((line=lnr.readLine())!=null) 17 { 18 //添加行号 19 System.out.println(lnr.getLineNumber()+":"+line); 20 } 21 lnr.close(); 22 } 23 }
运行结果
3.5.2、自己写LineNumberReader
package learn; import java.io.FileReader; import java.io.IOException; import java.io.Reader; class MyLineNumberReader { private Reader r; private int lineNumber; MyLineNumberReader(Reader r) { this.r=r; } public String myReadLine()throws IOException { lineNumber++; StringBuilder sb = new StringBuilder(); int ch = 0; while((ch=r.read())!=-1) { if(ch==' ') continue; if(ch==' ') return sb.toString(); else sb.append((char)ch); } if(sb.length()!=0) return sb.toString(); return null; } public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } public int getLineNumber() { return lineNumber; } public void myClose() throws IOException { r.close(); } } public class MyLineNumberReaderDemo { public static void main(String[] args) throws IOException{ FileReader fr = new FileReader("FileReadDemo.java"); MyLineNumberReader mylnr = new MyLineNumberReader(fr); String line = null; while((line=mylnr.myReadLine())!=null) { System.out.println(mylnr.getLineNumber()+"::"+line); } mylnr.myClose(); } }
运行结果
4、字节流
4.1、FileInputStream
FileInputStream(File file)
int available()返回流中的字节数,包括
准确的流中内容大小,因此可以替代1024
1 package learn; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 /* 字符流 8 * FileReader 9 * FileWriter 10 * 字节流 11 * InputStream 12 * OutputStream 13 * 需求:想操作图片数据,这是要用到字节流 14 * */ 15 public class FileStreamDemo { 16 public static void main(String[] args) throws IOException{ 17 // writeFile(); 18 readFile_3(); 19 } 20 public static void readFile_3()throws IOException 21 { 22 FileInputStream fis = new FileInputStream("fos.txt"); 23 // int num = fis.available(); 24 //定义一个刚刚好的缓冲区 25 26 byte[]buf = new byte[fis.available()]; 27 // System.out.println(num); 28 fis.read(buf); 29 System.out.println(new String(buf)); 30 31 fis.close(); 32 } 33 public static void readFile_2()throws IOException 34 { 35 FileInputStream fis = new FileInputStream("fos.txt"); 36 byte[] buf = new byte[1024]; 37 int len = 0; 38 while((len=fis.read(buf))!=-1) 39 { 40 System.out.println(new String(buf,0,len)); 41 } 42 fis.close(); 43 } 44 public static void readFile_1()throws IOException 45 { 46 FileInputStream fis = new FileInputStream("fos.txt"); 47 int ch = 0; 48 while((ch=fis.read())!=-1) 49 { 50 System.out.println((char)ch); 51 } 52 fis.close(); 53 } 54 public static void writeFile() throws IOException 55 { 56 FileOutputStream fos = new FileOutputStream("fos.txt"); 57 fos.write("abcde".getBytes()); 58 fos.close(); 59 } 60 }
运行结果
4.2、复制图片
思路:
java.io.FileInputStream
int read (byte[] b) 返回长度,存入b
图片文件→
fis→len获得fis的read返回的长度,()中的buf暂时存放数据,不是-1就一直存→
fos的write写出长度0-len的数组buf中的数据
1 package learn; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 /* 8 * 复制一个图片 9 * 思路: 10 * 1、用字节读取流对象和图片关联 11 * 2、用字节写入流对象创建一个图片文件,用于存储获取到的图片数据 12 * 3、通过循环读写,完成数据的存储 13 * 4、关闭资源 14 * */ 15 public class CopyPic { 16 public static void main(String[] args) { 17 FileOutputStream fos = null; 18 FileInputStream fis = null; 19 try 20 { 21 fos = new FileOutputStream("c:\2.bmp"); 22 fis = new FileInputStream("c:\1.bmp"); 23 24 byte[] buf = new byte[1024]; 25 int len = 0; 26 while((len=fis.read(buf))!=-1) 27 { 28 fos.write(buf,0,len); 29 } 30 } 31 catch(IOException e) 32 { 33 throw new RuntimeException("复制文件失败"); 34 } 35 finally 36 { 37 try 38 { 39 if(fis!=null) 40 fis.close(); 41 } 42 catch(IOException e) 43 { 44 throw new RuntimeException("读取关闭失败"); 45 } 46 47 try 48 { 49 if(fos!=null) 50 fos.close(); 51 } 52 catch(IOException e) 53 { 54 throw new RuntimeException("写入关闭失败"); 55 } 56 57 } 58 } 59 }
运行结果
4.3、复制MP3
1 package learn; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.FileInputStream; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 9 /*演示mp3的复制,通过缓冲区 10 * BufferedOutputStream 11 * BufferedInputStream 12 * 13 * */ 14 public class CopyMp3 { 15 public static void main(String[] args)throws IOException { 16 long start = System.currentTimeMillis(); 17 copy_1(); 18 long end = System.currentTimeMillis(); 19 System.out.println((end-start)+"毫秒"); 20 } 21 //通过字节流的缓冲区完成复制 22 public static void copy_1()throws IOException{ 23 BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\3.mp3")); 24 BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\4.mp3")); 25 int by = 0; 26 while((by=bufis.read())!=-1) 27 { 28 bufos.write(by); 29 } 30 bufis.close(); 31 bufos.close(); 32 33 34 } 35 }
运行结果
4.3.2、自写
read方法在做提升,一个字节读成4个字节,前面添加0,防止第一个数为-1
write在做强转,把最低8位写出去。
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
--------------------------------------------
00000000 00000000 00000000 11111111
1 package learn; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 public class MyBufferedInputStream { 7 private InputStream in; 8 private byte[] buf = new byte[1024*4]; 9 private int pos = 0,count = 0; 10 MyBufferedInputStream(InputStream in) 11 { 12 this.in = in; 13 } 14 //一次读一个字节,从缓冲区(字节数组)获取 15 public int myRead()throws IOException 16 { 17 //通过in对象读取硬盘上数据,并存储到Buffer 18 if(count ==0) 19 { 20 count = in.read(buf); 21 if(count<0) 22 return -1; 23 pos=0; 24 byte b =buf[pos]; 25 count--; 26 pos++; 27 return b&255; 28 } 29 else if(count>0) 30 { 31 byte b =buf[pos]; 32 count--; 33 pos++; 34 return b&0xff; 35 } 36 return -1; 37 } 38 public void myClose() throws IOException 39 { 40 in.close(); 41 } 42 43 }
运行结果
配合Copymp3后得
4.4、键盘录入
关键语句:
InputStream in = System.in;
1 package learn; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 6 /*读取键盘录入 7 * System.out对应的是标准输出设备,控制台 8 * System.in对应的是标准输入设备,键盘 9 * 需求:通过键盘录入数据, 10 * 当录入一行后,就将数据打印, 11 * 若录入over,那么停止录入 12 * */ 13 public class ReadIn { 14 public static void main(String[] args) throws IOException{ 15 InputStream in = System.in; 16 StringBuilder sb = new StringBuilder(); 17 18 while(true) 19 { 20 int ch = in.read(); 21 if(ch==' ') 22 continue; 23 if(ch==' ') 24 { 25 String s = sb.toString(); 26 if("over".equals(s)) 27 break; 28 System.out.println(s.toUpperCase()); 29 sb.delete(0, sb.length()); 30 } 31 else 32 sb.append((char)ch); 33 } 34 35 // System.out.println(' '+0); 36 // System.out.println('n'+0); 37 // int by = in.read(); 38 // System.out.println(by); 39 } 40 }
运行结果
4.4.2、转换流--键盘录入
InputStreamReader 字节流通向字符流的桥梁
InputStreamReader(InputStream in);传入参数字节流,创建一个字符集
1 package learn; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 8 public class TransStreamDemo { 9 public static void main(String[] args) throws IOException{ 10 //获取键盘录入对象 11 InputStream in = System.in; 12 //将字节流对象转成字符流对象,使用转换流InputStreamReader 13 InputStreamReader isr = new InputStreamReader(in); 14 //为了提高效率,将字符流进行缓冲区技术 15 BufferedReader bufr = new BufferedReader(isr); 16 String line = null; 17 while((line=bufr.readLine())!=null) 18 { 19 if("over".equals(line)) 20 break; 21 System.out.println(line.toUpperCase()); 22 } 23 bufr.close(); 24 } 25 }
运行结果
4.4.3、键盘录入最常见写法
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
1 package learn; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.InputStreamReader; 8 import java.io.OutputStream; 9 import java.io.OutputStreamWriter; 10 11 public class TransStreamDemo { 12 public static void main(String[] args) throws IOException{ 13 // //获取键盘录入对象 14 // InputStream in = System.in; 15 // //将字节流对象转成字符流对象,使用转换流InputStreamReader 16 // InputStreamReader isr = new InputStreamReader(in); 17 // //为了提高效率,将字符流进行缓冲区技术 18 // BufferedReader bufr = new BufferedReader(isr); 19 20 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); 21 22 // OutputStream out = System.out; 23 // OutputStreamWriter osw = new OutputStreamWriter(out); 24 // BufferedWriter bufw = new BufferedWriter(osw); 25 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); 26 27 String line = null; 28 while((line=bufr.readLine())!=null) 29 { 30 if("over".equals(line)) 31 break; 32 bufw.write(line.toUpperCase()); 33 bufw.newLine(); 34 bufw.flush(); 35 } 36 bufr.close(); 37 } 38 }
4.5、IO流使用思路
与setIn,setOut方法
1 /*1、 2 * 源:键盘录入 3 * 目的:控制台 4 * 2、 5 * 需求:想把键盘录入的数据存储到一个文件中 6 * 源:键盘 7 * 目的:文件 8 * system.out换成"out.txt" 9 * 10 * 3、 11 * 需求:想将一个文件的数据打印在控制台上 12 * 源:文件 13 * 目的:控制台 14 * system.in换成"文件名.类型" 15 * 16 * 流操作规律 17 * 通过三个明确来完成 18 * 19 * 1、明确源和目的 20 * 源:输入流 InputStream Reader 21 * 目的:输出流 OutputStream Writer 22 * 2、操作的数据是否是纯文本 23 * 是:字符流 24 * 不是:字节流 25 * 26 * 3、当体系明确后,再明确要使用哪个具体的对象 27 * 源设备:内存,硬盘,键盘 28 * 目的设备:内存,硬盘,控制台 29 * 30 * 需求1.将一个文件中的数据存储到另一个文件中。复制文件 31 * 源:因为是源,所以使用读取流,InputStream Reader、 32 * 是不是操作文本文件 33 * 是!这时就可以选择Reader 34 * 这样体系就明确了 35 * 36 * 接下来明确要使用该体系中的哪个对象 37 * 明确设备:硬盘。上一个文件 38 * Reader体系中可以操作文件的对象FileReader 39 * 40 * 是否需要提高效率:是!加入Reader体系中的缓冲区BufferedReader 41 * FileReader fr = new FileReader("a.txt"); 42 * BufferedReader bufr = new BufferedReader(fr); 43 * 44 * 目的:OutputStream Writer 45 * 是否是纯文本 46 * 是!Writer 47 * 设备:硬盘 48 * Writer可以操作文件的对象FileWriter 49 * 是否需要提高效率:是!加入Writer体系中的缓冲区BufferedWriter 50 * 51 * FileWriter fw = new FileWriter("b.txt"); 52 * BufferedWriter bufw = new BufferedWriter(fw); 53 * 54 *需求2:将键盘录入的数据保存到一个文件中 55 * 源:InputStream Reader 56 * 是否纯文本?是Reader 57 * 设备:键盘。对应的对象是system.in 58 * 为了操作键盘的文本数据方便,转成字符流按照字符串操作是最方便的 59 * 所以,既然明确了Reader,那么就将System.in转换成Reader 60 * 用了Reader体系中的转换流InputStreamReader 61 * 62 * InputStreamReader isr= new InputStreamReader(system.in) 63 * 64 * 需要提高效率吗?需要BufferedReader 65 * BufferedReader bufr = new BufferedReader(isr); 66 * 67 * 目的:OutputStream Writer 68 * 是否是纯文本?是Writer 69 * 设备:键盘。一个文件,使用FileWriter 70 * FileWriter fw= new FileWriter("c.txt"); 71 * 需要提高效率吗?需要BufferedWriter 72 * BufferedWriter bufw = new BufferedWriter(fw); 73 * 74 * 扩展:想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中 75 * 目的:OutputStream Writer 76 * 是否是纯文本?是Writer 77 * 设备:键盘。一个文件,使用FileWriter 78 * 但是FileWriter使用的是默认编码表 79 * 但是存储时,需要加入指定编码表,而指定的编码表只有转换流可以指定 80 * 所以要使用的对象是OutputStreamWriter 81 * 而该转换流对象要接受一个字节输出流,而且还可以操作的文件的字节输出流,FileOutputStream 82 * OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8"); 83 * 需要高效吗,需要 84 * BufferedWriter bufw = new BufferedWriter(osw); 85 * 所以,记住,转换流在涉及到字符编码转换时 86 * 需要用到转换流 87 * 88 * 89 * */ 90 public class TransStreamDemo { 91 public static void main(String[] args) throws IOException{ 92 System.setIn(new FileInputStream("buf.txt")); 93 System.setOut(new PrintStream("zzz.txt")); 94 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); 95 96 97 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); 98 99 String line = null; 100 while((line=bufr.readLine())!=null) 101 { 102 if("over".equals(line)) 103 break; 104 bufw.write(line.toUpperCase()); 105 bufw.newLine(); 106 bufw.flush(); 107 } 108 bufr.close(); 109 } 110 }
运行结果
4.6、异常的日志信息
1 package learn; 2 3 import java.io.IOException; 4 import java.io.PrintStream; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 8 public class ExceptionInfo { 9 public static void main(String[] args) { 10 try 11 { 12 int [] arr = new int[2]; 13 System.out.println(arr[3]); 14 } 15 catch(Exception e) 16 { 17 try{ 18 //创建日期 19 Date d = new Date(); 20 //格式化日期 21 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 22 //转换成字符串 23 String s= sdf.format(d); 24 //创建输出文件 25 PrintStream ps = new PrintStream("exeception.log"); 26 //字符串写入输出流 27 ps.println(s); 28 //输出流写入文件 29 System.setOut(ps); 30 31 } 32 catch(IOException ex) 33 { 34 throw new RuntimeException("日志文件创建失败"); 35 } 36 e.printStackTrace(System.out); 37 } 38 } 39 }
运行结果