Java IO流(字符流)

来源:互联网 发布:金蝶数据库可以恢复吗 编辑:程序博客网 时间:2024/06/14 00:33

------- android培训、java培训、期待与您交流! ----------

一、字符输出流的缓冲区 (BufferedWriter).

 缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符----newLine();
【API文档】
newLine
public void newLine()
             throws IOException
写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。 
抛出:
IOException- 如果发生 I/O 错误
 
示例:
import java.io.*;
 
class  BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("buf.txt");
 
 //为了提高字符写入流效率。加入了缓冲技术。
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw);
 
for(int x=1; x<5; x++)
{
bufw.write("abcd"+x);
bufw.newLine();
bufw.flush();
}
 
//记住,只要用到缓冲区,就要记得刷新。
//bufw.flush();
 
//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();
 
}

}

 

 

 二、字符输入流缓冲区【BufferedReader】

该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾
【API文档】
readLine
public String readLine()
                throws IOException
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 
返回:
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
抛出:
IOException- 如果发生 I/O 错误
示例:
 
import java.io.*;
 
class  BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("buf.txt");
 
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
 
String line = null;
 
while((line=bufr.readLine())!=null)
{
System.out.print(line);
}
bufr.close();
}

}

三、Readline方法的原理

明白了BufferedReader类中特有方法readLine的原理后,可以自定义一个类中包含一个功能和readLine一致的方法来模拟一下BufferedReader。
StringBuilder
容器
示例:
import java.io.*;
class MyBufferedReader extends Reader
{
private Reader r;
MyBufferedReader(Reader r)
{
this.r = r;
}
 
//可以一次读一行数据的方法。
public String myReadLine()throws IOException   //这里抛异常就是了,不需要处理,谁调用谁处理
{
//定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
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)        //以防字符后边没有\n时就不返回字符,所以加一个判断
return sb.toString();
return null;
}
 
/*
覆盖Reader类中的抽象方法。
 
*/
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf,off,len) ;
}
 
public void close()throws IOException
{
r.close();
}
public void myClose()throws IOException
{
r.close();
}
}
 
 
class  MyBufferedReaderDemo
{
public static void main(String[] args) throws IOException  //其实在这里应该处理try catch
{
FileReader fr = new FileReader("buf.txt");
 
MyBufferedReader myBuf = new MyBufferedReader(fr);
 
String line = null;
 
while((line=myBuf.myReadLine())!=null)
{
System.out.println(line);
}
 
myBuf.myClose();
}

}

 

 

四、通过缓冲区复制一个.java文件

 

示例:
import java.io.*;
 
class  CopyTextByBuf
{
public static void main(String[] args) 
{
BufferedReader bufr = null;
BufferedWriter bufw = null;
 
try
{
                                                           Bufr  = new BufferedReader(new FileReader("BufferedWriterDemo.java"));
Bufw = new BufferedWriter(new FileWriter("bufWriter_Copy.txt"));
 
String line = null;
 
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
 
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}

 

五、装饰设计模式:

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
 
装饰类通常会通过构造方法接收被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。
 
示例:
class Person
{
public void chifan()
{
System.out.println("吃饭");
}
}
//增强
class SuperPerson 
{
private Person p ;
SuperPerson(Person p)
{
this.p = p;
}
public void superChifan()
{
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根");
}
}
class  PersonDemo
{
public static void main(String[] args) 
{
Person p = new Person();
 
//p.chifan();
 
SuperPerson sp = new SuperPerson(p);
sp.superChifan();
 
}

}

六、装饰和继承的区别

MyReader//专门用于读取数据的类
|--MyTextReader
|--MyBufferTextReader
|--MyMediaReader
|--MyBufferMediaReader
|--MyDataReader
|--MyBufferDataReader
 
class MyBufferReader
{
MyBufferReader(MyTextReader text)
{}
MyBufferReader(MyMediaReader media)
{}
}
上面这个类扩展性很差。
找到其参数的共同类型。通过多态的形式。可以提高扩展性。
 
class MyBufferReader extends MyReader
{
private MyReader r;
MyBufferReader(MyReader r)
{}
}
 
 
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferReader
 
 
以前是通过继承将每一个子类都具备缓冲功能。
那么继承体系会复杂,并不利于扩展。
 
现在优化思想。单独描述一下缓冲内容。
将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
这样继承体系就变得很简单。优化了体系结构。
 
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
 
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常是都属于一个体系中的。

七、跟踪行号的缓冲字符输入流

public class LineNumberReader
extends BufferedReader
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber()
,它们可分别用于设置和获取当前行号。
示例:
import java.io.*;
class LineNumberReaderDemo 
{
public static void main(String[] args)throws IOException 
{
FileReader fr = new FileReader("PersonDemo.java");
 
LineNumberReader lnr = new LineNumberReader(fr);
 
String line = null;
lnr.setLineNumber(100);
while((line=lnr.readLine())!=null)
{
System.out.println(lnr.getLineNumber()+":"+line);
}
 
lnr.close();
}
}
 
 
自定义函数模拟LineNumberReader的功能
import java.io.*;
 
class MyLineNumberReader extends MyBufferedReader
{
private int lineNumber;
MyLineNumberReader(Reader r)
{
super(r);
}
public String myReadLine()throws IOException
{
lineNumber++;
return  super.myReadLine();
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
}
class  MyLineNumberReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("copyTextByBuf.java");
 
MyLineNumberReader mylnr = new MyLineNumberReader(fr);
 
String line = null;
mylnr.setLineNumber(100);
while((line=mylnr.myReadLine())!=null)
{
System.out.println(mylnr.getLineNumber()+"::"+line);
}
 
mylnr.myClose();
}
}

 


0 0