新博客地址:
第一讲,IO流(BufferedWriter)
一,字符流的缓冲区概述:
- 缓冲区的出现提高了对数据的读写效率。
- 对应类:BufferedWriter,BuuferedReader。(存在于java.io包中)
- 缓冲区要结合流才可以使用。 ====缓冲区是为了提高流的操作效率出现的,所以在创建缓冲区之前必须要现有流对象====
- 在流的基础上对流的功能进行了增强。
========缓冲技术原理:BufferedWriter,BufferedReader对象里面封装了数组==========
二,缓冲区操作类的简单了解:
BufferedWriter 类:
-
-
-
-
- 类的定义: public class BufferedWriter extends Writer 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
- 构造方法:public BufferedWriter (Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。===注:此处必须指明Writer对象作为参数,原因见概述第三条==========
- 构造方法:public BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
- 方法:public void newLine() throws IOException 写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。
- public void write(int c) throws IOException 写入单个字符。===注:此方法被重载多次,可写入char数组和字符串====
-
-
-
BufferedReader 类:
-
-
-
-
- 类的定义:public class BufferedReader extends Reader 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
- 构造方法:public BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。==注:指明Reader对象==
- 构造方法:public BufferedReader(Reader in,int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
- 方法: public int read() throws IOException 读取单个字符。返回值:作为一个整数(其范围从 0 到 65535 (0x00-0xffff))读入的字符,如果已到达流末尾,则返回 -1
- 方法: public int read(char[] cbuf, int off, int len) throws IOException 将字符读入数组的某一部分。==注: 包括off下标==
- 方法: public String readLine() throws IOException 读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
- 方法: public long skip(long n) throws IOException 跳过字符。返回值:实际跳过的字符数量。
-
-
-
三,缓冲区写入操作步骤:
- 创建一个字符写入流对象: FileWriter fw=new FileWriter("buf.txt");
- 创建缓冲区对象: BufferedWriter bw=new BufferedWriter(fw);
- 调用缓冲区对象方法写入数据: bw.write("abcd"); ===注:此步骤执行后,文件若不存在会被创建,但是,数据并没有写入文件。=====
- 刷新缓冲区: bw.flush(); ===注:用到缓冲区后一定要刷新===
- 关闭缓冲区: bw.close(); ===注:缓冲区只是提高操作效率,真正实现写操作的是FileWriter对象,所以缓冲区的关闭其实是关闭的是他所提高效率的流对象,即FileWriter 对象。===
四,代码练习:
1 /* 2 * 缓冲区对象使用联系。重点观察写入过程 3 *什么时候创建文件,以及将数据写入文件的时机 4 */ 5 import java.io.*; 6 import java.util.Scanner; 7 8 9 public class BufferedWriterDemo {10 public static void main(String args[]){11 12 //声明实际写文件对象引用13 FileWriter fw=null;14 15 //声明缓冲区对象引用16 BufferedWriter bw=null;17 18 //表示文件字符串19 String fileName="E:/buf.txt";20 21 //异常处理22 try{23 24 //实例化对象引用25 fw=new FileWriter(fileName);26 27 bw=new BufferedWriter(fw);28 29 30 //调用缓冲对象方法写入数据此时并没有写进文件中,但是文件已经创建。若文件存在由于不是追加写方式,源文件内容清空31 bw.write("abcd");32 33 //写入文件换行符,此方法跨平台34 bw.newLine();35 36 //写入第二行37 bw.write("第二行");38 39 //此处停顿,按任意键继续,此时可观察文件变化40 System.out.println("刷新流之前:");41 System.out.println("按任意键继续:");42 43 44 //用户输入任意字符后继续;45 new Scanner(System.in).next();46 47 //刷新缓冲流,将字符写入文件。48 bw.flush();49 50 //此后观察文件发现数据已经写入51 System.out.println("刷新流之后:");52 53 54 }catch(IOException e){55 System.out.println("写入操作发生错误!");56 }finally{57 try{58 if(bw!=null)59 bw.close();60 }catch(IOException e){61 System.out.println("关闭文件发生错误!");62 }63 64 65 }66 }67 }
第二讲:IO流(BufferedReader)
一,BufferedReader类的了解:见第一讲
二,缓冲区读入步骤:
- 创建一个读取流对象和文件相关联。 FileReader fr=new FileReader("buf.txt");
- 创建缓冲读取对象,提高读取操作效率。BufferedReader br=new BufferedReader(fr);
- 使用缓冲区对象方法读取数据: br.readLine(); ==注:readLine() 方法对于读取文本文件特别方便。特别注意:如果已到达流末尾,则返回 null 而不是 -1 ,此方法返回的字符串中不包括换行符==
- 关闭缓冲区。
三,代码练习:
1 import java.io.*; 2 3 4 public class BufferedReaderDemo { 5 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 9 //创建对象引用10 FileReader fr=null;11 BufferedReader br=null;12 13 //文件字符串14 String fileName="E:/buf.txt";15 16 17 //异常处理18 try{19 fr=new FileReader(fileName);20 21 br=new BufferedReader(fr);22 23 //创建字符串,保存读取内容24 String readLine=null;25 26 //循环读取文件内容,注意此处的判断条件是 null 而不是 -127 while((readLine=br.readLine())!=null){28 System.out.println(readLine);29 }30 31 32 //处理异常,给出提示33 }catch(FileNotFoundException e){34 System.out.println("文件没有找到!"+e.toString());35 }catch(IOException e){36 System.out.println("文件读取发生错误"+e.toString());37 }finally{38 try{39 if(br!=null)40 br.close();41 }catch(IOException e){42 System.out.println("文件关闭失败:"+e.toString());43 }44 }45 }46 47 }
第三讲:IO流(通过缓冲区复制文本文件)
一,练习:通过缓冲区复制一个 .java文件
注意事项:
-
-
- readLine() 方法返回的字符串中不包括换行符,所以再写入新的文件时应该加上,使用BudderedWriter.newLine()方法。
- 每次循环写入都必须刷新。
-
二,代码练习:
1 import java.io.*; 2 3 4 public class CopyFile { 5 public static void main(String args[]){ 6 7 //创建对象引用 8 BufferedReader br=null; 9 10 BufferedWriter bw=null;11 12 13 //源文件字符串表示14 String srcFileName="E:/test.java";15 16 17 //目标文件字符串表示18 String destFileName="E:/dest.java";19 20 //判断是否是.java文件21 if(!srcFileName.endsWith(".java")){22 System.out.println("文件后缀名不是 .java");23 24 //如果不是.java文件返回25 return;26 }27 28 29 30 //异常处理31 try{32 33 34 //使用匿名对象实例化缓冲区对象br 35 br=new BufferedReader(new FileReader(srcFileName));36 37 bw=new BufferedWriter(new FileWriter(destFileName));38 39 //接受读入的字符串40 String readLine=null;41 42 43 //循环读取44 while((readLine=br.readLine())!=null){45 46 //读取一行,写入一行47 bw.write(readLine);48 49 //由于readLine() 方法没有返回换行符,此处应当换行50 bw.newLine();51 52 //刷新缓冲区,将数据写入文件53 bw.flush();54 }55 56 //成功提示57 System.out.println("文件拷贝完毕!");58 59 //异常处理以及提示60 }catch(FileNotFoundException e){61 System.out.println("源文件没有找到,或者目标文件不存在"+e.toString());62 }catch(IOException e){63 System.out.println("文件拷贝失败"+e.toString());64 }65 }66 }
第四讲:IO流(readLine的原理图例)
原理概括,readLine 方法最终操作其实也是一个一个的读取数据,只不过它把读取到的数据存进了自己的缓冲区中,当遇到换行符时,结束读取,并一次性返回所有数据。如图:
第五讲:IO流(MyBufferedReader)
自定义readLine方法代码:
1 import java.io.*; 2 3 class MyBufferedReader { 4 5 //定义对象引用,并进行封装,使用构造函数实例化 6 private FileReader reader; 7 8 9 //定义缓冲区,缓冲读入的字符 10 private char[] str; 11 12 13 //构造方法,传入一个FileReader对象进行文件读操作,使用默认缓冲区 14 public MyBufferedReader(FileReader reader){ 15 this.reader=reader; 16 this.str=new char[1024]; 17 } 18 19 20 //使用自定义的缓冲区大小 21 public MyBufferedReader(Reader Filereader,int size){ 22 this.reader=reader; 23 this.str=new char[size]; 24 } 25 26 27 28 //自定义函数进行缓冲的高效读写。此处异常交由调用者处理。 29 public String myReadLine() throws IOException{ 30 31 //保存读取的单个字符; 32 int ch=0; 33 34 //记录读取的总字符数量 35 int num=0; 36 37 //循环读取内容 38 while((ch=this.reader.read()) != -1){ 39 40 41 //如果字符为 '\r' 则跳过继续下一轮循环 42 if(ch == '\r') 43 continue; 44 45 //如果字符为 '\n' 则结束循环,返回读取的内容 46 else if(ch == '\n') 47 return new String(str,0,num); 48 49 //如果超出缓冲区大小,则结束循环,返回读取内容 50 else if(num>=size) 51 return new String(str,0,num); 52 else{ 53 54 //将读取的字符保存在字符数组中,下标加一 55 str[num]=(char)ch; 56 num++; 57 } 58 } 59 60 //判断最后一行数据是否存在 61 if(num!=0) 62 return new String(str,0,num); 63 else return null; 64 } 65 66 67 //关闭流,实为关闭内部流对象。此处异常抛出。 68 public void myClose() throws IOException{ 69 this.reader.close(); 70 } 71 } 72 73 74 75 public class MyBufferedReaderDemo { 76 77 public static void main(String[] args) { 78 // TODO Auto-generated method stub 79 MyBufferedReader mbr=null; 80 81 String fileName="E:/testmybuf.txt"; 82 83 try{ 84 mbr=new MyBufferedReader(new FileReader(fileName)); 85 86 String readLine; 87 88 //循环读取 89 while((readLine=mbr.myReadLine())!=null){ 90 System.out.println(readLine); 91 } 92 System.out.println("读取完毕!"); 93 94 }catch(IOException e){ 95 System.out.println("读取文件错误"+e.toString()); 96 }finally{ 97 try{ 98 if(mbr!=null){ 99 mbr.myClose();100 }101 }catch(IOException e){102 System.out.println("文件关闭时发生错误!"+e.toString());103 }104 }105 }106 107 }
第六讲、第七讲、第八讲:装饰设计模式、装饰和继承的区别、自定义装饰类
一,装饰设计模式简介:
-
- 装饰模式(Decorator)的定义:当想对已有对象进行功能增强时,可定义一个类,这个类将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。又名包装(Wrapper)模式,装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
- 装饰模式的特点:
-
-
-
- 装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
- 装饰对象包含一个真实对象的引用(reference).
- 通常装饰类,与被装饰类实现同一个接口。即属于同一个接口或者类。
-
- 装饰设计模式和继承的区别:
-
- 装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。装饰模式扩展的是对象的功能,不需要增加类的数量,而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加两个方法。
- 装饰模式是一种动态行为,可以对已经存在类进行随意组合,而类的继承是一种静态的行为,一个类定义成什么样的,该类的对象便具有什么样的功能,无法动态的改变。
-
-
二,代码练习(第五讲代码增强):
1 import java.io.*; 2 3 class MyBufferedReader { 4 5 //定义对象引用,并进行封装,使用构造函数实例化 6 private FileReader reader; 7 8 9 //定义缓冲区,缓冲读入的字符 10 private char[] str; 11 12 13 //构造方法,传入一个FileReader对象进行文件读操作,使用默认缓冲区 14 public MyBufferedReader(FileReader reader){ 15 this.reader=reader; 16 this.str=new char[1024]; 17 } 18 19 20 //使用自定义的缓冲区大小 21 public MyBufferedReader(Reader Filereader,int size){ 22 this.reader=reader; 23 this.str=new char[size]; 24 } 25 26 27 28 //自定义函数进行缓冲的高效读写。此处异常交由调用者处理。 29 public String myReadLine() throws IOException{ 30 31 //保存读取的单个字符; 32 int ch=0; 33 34 //记录读取的总字符数量 35 int num=0; 36 37 //循环读取内容 38 while((ch=this.reader.read()) != -1){ 39 40 41 //如果字符为 '\r' 则跳过继续下一轮循环 42 if(ch == '\r') 43 continue; 44 45 //如果字符为 '\n' 则结束循环,返回读取的内容 46 else if(ch == '\n') 47 return new String(str,0,num); 48 49 //如果超出缓冲区大小,则结束循环,返回读取内容 50 else if(num>=size) 51 return new String(str,0,num); 52 else{ 53 54 //将读取的字符保存在字符数组中,下标加一 55 str[num]=(char)ch; 56 num++; 57 } 58 } 59 60 //判断最后一行数据是否存在 61 if(num!=0) 62 return new String(str,0,num); 63 else return null; 64 } 65 66 67 //关闭流,实为关闭内部流对象。此处异常抛出。 68 public void myClose() throws IOException{ 69 this.reader.close(); 70 } 71 72 73 74 //覆写父类中的抽象方法 75 @Override 76 public int read(char[] cbuf, int off, int len) throws IOException { 77 78 //调用真是实现类实现具体操作 79 return this.reader.read(cbuf, off, len); 80 } 81 82 83 //覆写父类中的抽象方法 84 @Override 85 public void close() throws IOException { 86 this.reader.close(); 87 88 } 89 } 90 91 92 93 public class MyBufferedReaderDemo { 94 95 public static void main(String[] args) { 96 // TODO Auto-generated method stub 97 MyBufferedReader mbr=null; 98 99 String fileName="E:/testmybuf.txt";100 101 try{102 mbr=new MyBufferedReader(new FileReader(fileName));103 104 String readLine;105 106 //循环读取107 while((readLine=mbr.myReadLine())!=null){108 System.out.println(readLine);109 }110 System.out.println("读取完毕!");111 112 }catch(IOException e){113 System.out.println("读取文件错误"+e.toString());114 }finally{115 try{116 if(mbr!=null){117 mbr.myClose();118 }119 }catch(IOException e){120 System.out.println("文件关闭时发生错误!"+e.toString());121 }122 }123 }124 125 }
第九讲、第十讲:IO流(LineNumberReader)、IO流(MyineNumberReader)
一,LineNumberReader类的了解:
-
-
- 类的定义:public class LineNumberReader extends BufferedReader 跟踪行号的缓冲字符输入流。此类定义了方法
setLineNumber(int)
和getLineNumber()
,它们可分别用于设置和获取当前行号。==注:默认情况下,行编号从 0 开始。该行号随数据读取在每个行结束符处递增,可以通过调用setLineNumber(int)
更改行号。setLineNumber(int)
不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。=== - 方法:public int getLineNumber() 获得当前行号。
- 方法:public void setLineNumber(int lineNumber) 设置当前行号。
- 类的定义:public class LineNumberReader extends BufferedReader 跟踪行号的缓冲字符输入流。此类定义了方法
-
二,LineNumberReader类的原理:
在类的内部增加了一个行号计数器。
三,代码练习:
1 import java.io.*; 2 class LineNumberReaderDemo 3 { 4 public static void main(String[] args) 5 { 6 LineNumberReader lnr=null; 7 try 8 { 9 10 lnr=new LineNumberReader(new FileReader("LineNumberReaderDemo.java"));11 12 //设置行号:此设置仅对 getLineNumber() 有效并不会影响源文件13 lnr.setLineNumber(100); 14 15 //接受读取的字符串16 String line=null;17 18 //循环读取19 while ((line=lnr.readLine())!=null ){20 21 //输出行号与内容22 System.out.println(lnr.getLineNumber()+":"+line); 23 }24 }25 26 //异常处理27 catch (IOException e)28 {29 throw new RuntimeException("读取数据失败");30 }31 finally32 {33 try34 {35 if(lnr!=null)36 lnr.close();37 }38 catch (IOException e)39 {40 throw new RuntimeException("读取流关闭失败");41 }42 } 43 }44 }
第十一讲,十二讲:IO流(字节流File读写操作)、IO流(拷贝图片)
一,字节流概述:
-
- 字节流除了可以操作文本文件外还可以操作其他文件,例如媒体文件。
- 字节流的顶层类: InputStream,OutputStream。
- 字节流的写入是直接写入文件的,所以不用进行刷新。==注:因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。==
二,InputStream类的了解:
-
-
- 构造方法:public abstract class InputStream extends Object implements Closeable 此抽象类是表示字节输入流的所有类的超类。
- 独特的方法:public int available() throws IOException 返回可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回
0
。===注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用。=== - 直接已知子类:AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
-
三,拷贝图片步骤:
-
-
- 用字节读取流对象和图片关联。
- 用字节流对象创建一个图片文件,存储获取到的图片数据。
- 通过循环读写,完成数据的存储。===注:此处不存在流的刷新====
- 关闭资源。
-
四,代码练习,拷贝图片:
1 import java.io.*; 2 public class CopyImage{ 3 public static void main(String[] args){ 4 5 //创建对象引用 6 FileInputStream fis=null; 7 FileOutputStream fos=null; 8 9 10 try{11 //实例化对象,与文件相关联12 fis=new FileInputStream("E:/image/pub.jpg");13 14 fos=new FileOutputStream("E:/image/pub2.jpg");15 16 17 //创建数组用于保存读取到的数据 byte[] b=new byte[1024];18 19 //记录读取到的字节数20 int len=0;21 22 23 //循环读取24 while ((len=fis.read(b))!=-1){25 26 //边读边写实现复制27 fos.write(b,0,len);28 }29 }30 31 32 catch (IOException e)33 {34 throw new RuntimeException("图片复制失败");35 }36 finally37 {38 try39 {40 if(fis!=null)41 fis.close();//关闭输入字节流42 }43 catch (IOException e)44 {45 throw new RuntimeException("读取字节流关闭失败");46 }47 try48 {49 if(fos!=null)50 fos.close();//关闭输出字节流51 }52 catch (IOException e)53 {54 throw new RuntimeException("写入字节流关闭失败");55 }56 }57 } 58 }
第一十三讲、一十四讲:IO流(字节流的缓冲区)、IO流(自定义字节流的缓冲区-read和write的特点)
一,缓冲输出流的了解:
-
-
- 用到的类BufferedOutputStream,BufferedInputStream.
- BufferedInputStream类的定义:public class BufferedInputStreamextends FilterInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持
mark
和reset
方法的能力。 - 方法与InputStream类相同。
-
二,缓冲区的原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。如图:
三,字节流操作注意事项:
-
-
- 读取方法应当返回 int 类型,而不是 byte 类型。==原理:数据在内存中以二进制形式存在,当读到八个一时,转换为 byte类型是 -1 ,则此时使用 -1作为文件结束的判断逻辑将会出错。解决办法:将byte 类型转换为 int 类型,并将转后的的数据的前24位二进制用零填充。代码实现: return byte&0xff; 0xff即 255 二进制形式为 00000000 000000000 00000000 11111111 所以将byte的前24位变为零==
-
四,代码练习:
1 import java.io.*; 2 3 4 public class MyBufferedInputStream { 5 6 7 //定义被包装的类成员 8 private InputStream in; 9 10 //定义缓冲区的大小 11 private int size=1024; 12 13 14 //定义变量分别表示读取数量,以及当前数组下标 15 private int pos=0,count=0; 16 17 //声明已知长度的缓冲区 18 byte[] buf=new byte[size]; 19 20 21 //定义构造方法 22 public MyBufferedInputStream(InputStream in){ 23 this.in=in; 24 } 25 26 27 //定义构造方法 28 public MyBufferedInputStream(InputStream in,int size){ 29 this.in=in; 30 this.size=size; 31 } 32 33 34 //声明对外提供的方法 35 //功能:一次从缓冲区中读取一个字节数据。 36 public int myRead() throws IOException{ 37 38 //缓冲区中没有数据 39 if(count==0){ 40 41 //将数据读入缓冲区 42 count=in.read(buf); 43 44 //到达文件末尾返回 -1 45 if(count<=0){ 46 return -1; 47 } 48 49 //返回缓冲区中的第一个字节 50 byte read=buf[pos]; 51 52 //缓冲区数据量 减一 53 count--; 54 55 //缓冲区下标加一 56 pos++; 57 58 //返回整形数据,原数据与上255,将钱24位设定为零,避免读取的字节为八个一时,错误判断为文件结束 59 return read&0xff; 60 61 } 62 else { 63 64 //缓冲区中有数据,直接返回 65 byte read=buf[pos]; 66 67 //改变下标 68 count--; 69 pos++; 70 71 //返回修改之后的值 72 return read&0xff; 73 } 74 } 75 76 77 //定义主方法拷贝mp3 78 public static void main(String args[]){ 79 80 81 //声明引用句柄 82 FileInputStream src=null; 83 FileOutputStream dest=null; 84 MyBufferedInputStream mbi=null; 85 86 //异常处理 87 try{ 88 89 //实例化源文件,目标文件 90 src=new FileInputStream("E:/my.mp3"); 91 dest=new FileOutputStream("E:/my2.mp3"); 92 93 //实例化缓冲区读取对象 94 mbi=new MyBufferedInputStream(src); 95 96 97 //接受读取的数据 98 int read=0; 99 100 //循环读取数据并写入文件101 while((read=mbi.myRead())!=-1){102 dest.write(read);103 }104 105 106 //异常处理107 }catch(IOException e){108 System.out.println("文件复制错误"+e.toString());109 }finally{110 try{111 if(src!=null){112 src.close();113 }114 if(dest!=null){115 dest.close();116 }117 }catch(IOException e){118 System.out.println("文件关闭发生错误"+e.toString());119 }120 }121 }122 }
第一十五讲:IO流(读取键盘录入)
一,使用到的对象:System.in
-
-
- 该对象的定义:public static final InputStream in “标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。======注:次对象使用完毕后可以不进行显示的关闭==========
- System的另一个静态对象: public static final PrintStream out “标准”输出流。此流已打开并准备接受输出数据。
-
二,需求分析:
通过键盘录入数据,当录入一行数据后,就将改行打印,如果录入的数据是 end ,那么停止录入。
三,代码实现:
1 import java.io.*; 2 3 4 public class ReadIn { 5 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 9 //创建输入对象,指向System.in ======次对象可以不用显示关闭==========10 InputStream in=System.in;11 12 //缓冲读入的字符13 StringBuilder sb=new StringBuilder();14 15 16 //一直读取键盘输入,直到用户输入end字符串17 while(true){18 19 //接受输入字符20 int ch=0;21 22 23 //读取输入内容24 try {25 ch=in.read();26 } catch (IOException e) {27 System.out.println("读取发生错误"+e.toString());28 }29 30 //进行判断,如果是 '\r' 则进行下一次读取31 if(ch==13)32 continue;33 34 //如果是 '\n' 字符结束读取,打印用户的输入35 else if(ch==10){36 37 //如果用户输入的是 "end" 字符串,则结束读取38 if("end".equals(sb.toString()))39 break;40 41 //否则打印用户输入,进行下一次读取42 System.out.println(sb);43 44 //打印完毕必须清空缓冲区45 sb.delete(0, sb.length());46 }else 47 48 //普通字符存入缓冲区中49 sb.append((char)ch);50 51 }52 }53 54 }
===========键盘录入也可以使用 crtl + c 快捷键结束===============
第一十六讲,一十七讲:IO流(读取转换流),IO流(写入转换流)
一,需求分析:
使用readLine()方法读取键盘的一行数据。
使用newLine() 方法进行换行。
二,思路分析:
-
- readLine() 方法是字符流BufferedReader类中的方法。
- 负责接收键盘录入的read() 方法是字节流InputStream 类中的方法。
- newLine() 方法是字符流BufferedWriter 类中的方法。
三,解决办法:
-
- 使用转换流。InputStreamReader(字节转换字符流),OutputStreamReader(字符流转换字节流)。
- InputStreamReader 类的定义:public class InputStreamReaderextends Reader
- InputStreamReader 类的构造方法:
- public InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。
- public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException 创建使用指定字符集的 InputStreamReader。
- public InputStreamReader(InputStream in, Charset cs) 创建使用给定字符集的 InputStreamReader。
- OutputStreamWriter 类的定义:public class OutputStreamWriterextends Writer OutputStreamWriter 是字符流通向字节流的桥梁
- OutputStreamWriter 类的构造方法:
- public OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。
- public OutputStreamWriter(OutputStream out, Charset cs) 创建使用给定字符集的 OutputStreamWriter。
- public OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用给定字符集编码器的 OutputStreamWriter。
- 将字节流转换成字符流,之后再使用字符流的 readLine() ,newLine()方法进行数据的按行读取,以及进行换行操作。
- 使用转换流。InputStreamReader(字节转换字符流),OutputStreamReader(字符流转换字节流)。
四,练习代码:
1 import java.io.*; 2 3 4 public class TransStreamDemo { 5 public static void main(String args[]){ 6 7 //创建字符流对象,此对象包装了字节流对象 8 InputStreamReader isr=new InputStreamReader(System.in); 9 10 11 //创建缓冲字符流对象,使用readLine() 方法12 BufferedReader br=new BufferedReader(isr);13 14 //接受输入的字符串15 String line=null;16 17 //循环读取用户输入内容18 while(true){19 try {20 21 //如果用户输入 "end" 则结束读取22 if("end".equals(line=br.readLine()))23 break;24 } catch (IOException e) {25 // TODO Auto-generated catch block26 System.out.println("读取发生错误"+e.toString());27 }28 29 //输出用户的输入30 System.out.println(line);31 }32 33 }34 }
===============键盘录入最常见写法:BufferedReaderin=new BufferedReader(new InputStreamReader(System.in));====================
第一十八讲:IO流(流操作规律-1)
一,操作流程:
-
- 明确目的和源:
- 源:键盘录入。
- 目的:控制台(屏幕设备)。
- 需求分析:
- 把键盘录入的数据存储到一个文件中。======源:键盘,目的地:文件(硬盘)==========
- 把一个文件数据打印到控制台上。 ======源:文件,目的地:控制台==========
- 通过两个明确来选择众多流对象中具体应该用那中体系。--------1,明确目的和源。2,操作的文件或者是源,是否是文本形式的。-----------------
- 当体系明确后再明确具体使用那个对象。 ====源设备:内存,硬盘,键盘,目的:内存,硬盘,控制台=====
- 明确目的和源:
二,练习分析:
-
- 将一个文本文件数据,存储到另一个文本文件中,即复制文件。
- 源:应为是源所以使用读取流(InputStream, Reader)。
- 是不是文本文件 (Reader)。 ===明确体系===
- 确定源对象:因为设备是硬盘文件,选择FileReader。 FileReader fr=new FileReader("源.txt");
- 目的:因为是目的所以使用写入流(OutpurStream, Writer)。
- 是不是文本文件 (Writer)。
- 确定目的对象:FileWriter。 FileWriter fw=new FileWriter("目的.txt");
- 输入流提高效率: 加入BufferedReader BufferedReader br=new BufferedReader(fr);
- 输出流提高效率: 加入BufferedWriter BufferedWriter bw=new BufferedWriter(fw);
- 将一个文本文件数据,存储到另一个文本文件中,即复制文件。
三,复制图片代码练习:
1 import java.io.*; 2 3 4 public class MyImage { 5 public static void main(String args[]){ 6 7 //确定使用的对象===源:硬盘,图片文件,目的:硬盘,图片文件 8 FileInputStream fis=null; 9 FileOutputStream fos=null;10 11 12 //使用缓冲流提高效率13 BufferedInputStream bis=null;14 BufferedOutputStream bos=null;15 16 17 String src="F:/Image/psb.jpg";18 String dest="F:/Image/psb2.jpg";19 20 try{21 22 //实例化对象23 fis=new FileInputStream(src);24 bis=new BufferedInputStream(fis);25 26 bos=new BufferedOutputStream(fos=new FileOutputStream(dest));27 28 //转存读入的内容29 byte[] b=new byte[1024];30 31 //循环读取写入实现文件复制32 while(bis.read(b)!=-1)33 bos.write(b);34 35 //给出成功提示36 System.out.println("文件复制成功");37 }catch(IOException e){38 System.out.println("文件复制错误!"+e.toString());39 }finally{40 try{41 if(bis!=null)42 bis.close();43 if(bos!=null)44 bos.close();45 }catch(IOException e){46 System.out.println("文件关闭过程发生错误!"+e.toString());47 }48 }49 }50 }
第一十九讲:IO流(流操作规律-2)
一,扩展:把录入的数据按照指定的编码表(UTF-8)(默认编码表是GBK),将数据存到文件中。
-
- 想要实现使用指定的编码表将数据存入文件中,只能使用转换流。OutputStreamWriter osw=new OutputStreamWriter(new FileInputStream("d.txt"),"UTF-8");
- 提高效率:BufferedWriter bw=new BufferedWriter(osw);
====转换流的使用时机:1,字符和字节之间的桥梁。2,涉及到字符编码转换。===
二,代码练习:使用指定的编码表(UTF-8)将键盘输入的数据存入文件中
1 import java.io.*; 2 3 public class TransStreamDemo2 { 4 public static void main(String args[]){ 5 6 7 //确定输入源为键盘,创建相对应的输入流对象,并使用装饰流提高效率 8 InputStream in=System.in; 9 10 //输入流输入的为文本文件,使用转换流进行转换11 InputStreamReader isr=new InputStreamReader(in);12 BufferedReader br=new BufferedReader(isr);13 14 //读取键盘输入的常用格式:15 //以上三句话可以省略写为:BufferedReader br=new BufferedReader(new InputStreamReader(System.in));16 //确定输出源为文件,创建相对应输出流对象,并使用装饰流提高效率17 FileOutputStream fos=null;18 19 //输出流输出的为文本文件,使用输出流进行转换20 OutputStreamWriter isw=null;21 BufferedWriter bw=null;22 try{23 24 //创建输出缓冲流,其中转换里流明确使用UTF-8编码格式25 bw=new BufferedWriter(isw=new OutputStreamWriter(fos=new FileOutputStream("E:/test.txt"),"UTF-8"));26 27 //接受读入的一行数据28 String line=null;29 30 //循环读取写入31 while(!"end".equals(line=br.readLine())){32 33 //写入文件34 bw.write(line);35 36 //写入换行符37 bw.newLine();38 39 //缓冲流需要刷新40 bw.flush();41 }42 43 //成功提示44 System.out.println("存入完毕");45 46 //异常处理47 }catch(IOException e){48 System.out.println("发生错误!"+e.toString());49 }finally{50 try{51 if(bw!=null)52 bw.close();53 }catch(IOException e){54 System.out.println("文件关闭发生错误!"+e.toString());55 }56 }57 }58 }
第二十讲:IO流(改变标准输入输出设备)
一,改变标准输入、输出设备用到的System类中的方法:
-
-
- public static void setIn (InputStream in) 重新分配“标准”输入流。
- public static void setOut(PrintStream out) 重新分配“标准”输出流。
-
二,代码练习:通过改变标准输入、输出实现文件的复制
1 import java.io.*; 2 3 4 public class TransStreamDemo3 { 5 public static void main(String args[]){ 6 7 //目的和源都是 文件,创建相对应的流对象引用 8 FileInputStream in=null; 9 PrintStream out=null;10 11 //确定操作的是文本文件,使用相对应的缓冲刘提高效率12 BufferedWriter bw=null;13 BufferedReader br=null;14 15 //异常处理16 try{17 18 //实例化输入输出流对象19 in=new FileInputStream("E:/test.txt");20 out=new PrintStream("E:/test_copy.txt");21 22 //分别调用 setIn() setOut() 方法重定向标准输入、输出。23 System.setIn(in);24 System.setOut(out);25 26 27 //实例化缓冲流。使用转换流进行转换28 br=new BufferedReader(new InputStreamReader(System.in));29 bw=new BufferedWriter(new OutputStreamWriter(System.out));30 31 //接受读入的一行数据32 String line=null;33 34 //循环读入写入操作35 while((line=br.readLine())!=null){36 37 //写入数据38 bw.write(line);39 40 //换行操作41 bw.newLine();42 43 //清空缓冲区44 bw.flush();45 }46 47 //操作成功给出提示48 System.out.println("文件复制成功!");49 }catch(FileNotFoundException e){50 System.out.println("文件没有找到"+e.toString());51 }catch(IOException e){52 System.out.println("文件复制发生作物"+e.toString());53 }finally{54 try{55 if(br!=null)56 br.close();57 if(bw!=null)58 bw.close();59 }catch(IOException e){60 System.out.println("文件关闭发生错误"+e.toString());61 }62 }63 }64 }
第二十一讲,二十二讲:IO流(异常的日志信息),IO流(系统信息)
一,需求分析:
-
- 将程序运行时异常记录在文件中。
- 加入异常产生的时间。
二,思路:
-
- 获取文件输出流,输出异常信息。
- 记录异常产生时间,并输入文件。
- 获取异常信息,并将之输入文件。
三,代码实现:
1 import java.io.*; 2 import java.util.Date; 3 import java.text.SimpleDateFormat; 4 5 6 public class ExceptionInfo { 7 public static void main(String arga[]){ 8 9 //测试记录函数,此处会发生ArrayIndexOutOfBoundsException10 try{11 String s[]=new String[2];12 s[3]="li";13 }catch(Exception e){14 log(new Date(),e);15 }16 }17 18 //声明将异常记录在文件方法19 public static void log(Date date,Exception e){20 //记录异常文件名21 String filename="E:/Exception.log";22 23 //声明缓冲输出流,提高操作效率24 BufferedWriter bw=null;25 try{26 27 //实例化输出对象28 bw=new BufferedWriter(new FileWriter(filename));29 30 //声明格式化日期操作类,格式化日期格式31 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");32 33 //写入异常发生时间34 bw.write(sdf.format(date)+"===");35 36 //写入异常信息37 bw.write(e.toString());38 }catch(IOException ex){39 System.out.println("记录异常发生错误"+ex.toString());40 }finally{41 try{42 if(bw!=null)43 bw.close();44 }catch(Exception ex){45 System.out.println("关闭文件发生错误"+ex.toString());46 }47 }48 }49 }
四,输出系统信息。
-
- 获取系统信息: Propertes prop=System.getProperties();
- 列出系统信息: prop.list(new PrintStream("E:/sysinfo.txt");
五,代码练习:
1 import java.io.*; 2 import java.util.Properties; 3 4 5 public class SysInfo { 6 public static void main(String args[]){ 7 8 //获取系统信息 9 Properties prop=System.getProperties();10 11 //声明输出流句柄12 PrintStream ps=null;13 try{14 15 //实例化对象16 ps=new PrintStream("E:/sysinfo.txt");17 18 //将系统信息输出到指定流中19 prop.list(ps);20 }catch(IOException e){21 System.out.println("写入错误"+e.toString());22 }finally{23 try{24 if(ps!=null)25 ps.close();26 }catch(Exception e){27 System.out.println("关闭文件错误!"+e.toString());28 }29 }30 }31 }
六,常用到的系统信息:
-
- user.language=zh 用户的语言
- file.encoding=GBK 系统编码
- user.name=Thinkpad 用户名
- line.separator= 换行符
- os.name=Windows 8 操作系统
- path.separator=; 路径分割符