IO流之字符流

概述:IO就是java中的输入和输出,主要是对数据的操作。Java中把这些输入和输出的内容看作流来处理,根据处理的对象的不同,分为字符流和字节流。,根据流向不同可分为输入流和输出流。

字符流:由连续的char组成的流,适用于多个自己表示一个字符的内容,例如文本数据。

字符流就是字节流读取字节数据后,先查相应的码表,获取对应的文字然后再进行输出。

字节流:连续的byte组成的流。适用于字节表示的内容,例如:多媒体文件,图片等。

字节流和字符流的区别:

1,字节流读取的时候,读到一个字节就返回一个字节。

字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。

2,字节流可以处理所有类型数据,如图片,mp3,avi。

而字符流只能处理字符数据。

字符流的抽象基类:

Reader(读)、Writer(写)

字节流的抽象基类:

InputStream(读入)、OutputStream(输出)

这里所谓的读写,输入和输出都是相对的概念,都是相对于程序本身而言的,把硬盘上的数据读入到内存,就叫输入或读入,把程序中的数据输出到硬盘或者网络,就叫输出。

字符输入流:

Reader :抽象基类,没有构造方法。有以下几个常用的方法:

1、Int read()返回以一个用int表示的char,-1表示到文件末尾。

2、Int read(char[] a)把从流中得到的多个字符放入char[]中,并返回实际得到的字符数,-1表示到流的末尾。

3、void close()关闭字符流,关闭之前会调用flush()方法,刷新缓冲区。

要从一个

FileReader:文件输入流。用于读取文本文件或者关联文本文件。

构造函数:FileReader(String)和FileReader()两个构造方法。在读取流对象初始化的时候,必须要指定一个被读取的文件。如果该文件不存在会发生FileNotFoundException.

 

从一个流得到单个字符进行输入时,大致步骤如下:

1、 创建字符流对象r,指明从哪里输入。

2、  int c = 0;

while(true){

            c = r.read();//得到流中的内容

            if(c==-1)//判断是否结束

                     break;

  对c中的得到的内容进行处理

}

3、  关闭流

以上的while循环通畅简化为:

         While((c==in.read())!=-1)

{

处理c;
}

从一个流得到多个字符进行输入时,大致步骤如下:

1、 创建字符流对象r,指明从哪里输入

2、  char [] c= new char[1024];//指定缓冲区大小

int len = 0;//接受读取的字符数

while(true){

                     len=r.read(c);//得到流中的内容

                     if(len==-1)//判断是否结束

                              break;

                     对c中的得到的内容进行处理

}

3、  关闭流

以上的while循环通畅简化为:

         While((len==in.read(c))!=-1)

{

处理c;
}

注意:1、一次读取多个字节比一次读取一个字节效率高。

2、对于读取或者写入流对象的构造函数,以及读写方法,还有刷新关闭功能都会抛出IOException或者其子类。所以都要进行处理。或者throws抛出,或者try catch处理。

package IOTest;
import java.io.*;
public class FileReaderDemo {
	public static void main(String[] args) throws IOException{
		FileReaderDemo demo = new FileReaderDemo();
		demo.readFile("miss.txt");

	}
	public static void readFile(String fileName)throws IOException
	{
		Reader r = null;
		try{
			r = new FileReader(fileName);//指定从哪里输入
			char[]c = new char[1024];
			int len = 0;
			while((len = r.read(c))!=-1)//得到流的内容并判断是都到流的末尾
			{
				System.out.println(new String(c,0,len));//对得到的内容进行处理
			}
		}finally
		{
			if(r!=null)
				r.close();
		}
	}
}

BufferedReader:缓冲字符流

缓冲区的出现提高了对流的操作效率。原理:其实就是将数组进行封装,将每次读入数据先从封装的缓冲区读,如果没有则从被套接的流中读入多个字符放入到缓冲数组中。

两个构造方法:

BufferedReader(Reader r) 指定套接的输入流。

BufferedReader(Reader r,int n)指定套接的输入流,用int 指定缓冲区的大小。

特殊方法:

String readLine()一次可以得到文件中的一行,不过得到的是去掉换行符之后的内容。当返回null时表示到流的末尾。

 

实例代码如下:

package IOTest;
import java.io.*;
public class BufferedReaderDemo {
	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		BufferedReaderDemo demo = new BufferedReaderDemo();
		demo.readFile("miss.txt");
	}
	public static void readFile(String fileName) throws IOException
	{
		BufferedReader br = null;
		try{
			br = new BufferedReader(new FileReader(fileName),1024);//指明从哪里输入
			String line= null;
			while((line = br.readLine())!=null)//得到流并判断是否到流的末尾
			{
				System.out.println(line);//对得到的内容进行处理
			}
		}finally
		{
			if(br!=null)
				br.close();//关闭流
		}
	}

}

字符输出流:

Writer:抽象基类,没有构造方法。有以下几个常用的方法:

1write(ch):将一个字符写入到流中。

2write(char[]):将一个字符数组写入到流中。

3write(String):将一个字符串写入到流中。

4flush():刷新流,将流中的数据刷新到目的地中,流还存在。

5close():关闭资源:在关闭前会先调用flush(),刷新流中的数据去目的地。然流关闭。

FileWriter:

该类没有特有的方法。只有自己的构造函数。

该类特点在于,

1,用于处理文本文件。

2,该类中有默认的编码表,

3,该类中有临时缓冲。

构造函数:在写入流对象初始化时,必须要有一个存储数据的目的地。

FileWriter(Stringfilename):

该构造函数做了什么事情呢?

1,调用系统资源。

2,在指定位置,创建一个文件。

注意:如果该文件已存在,将会被覆盖。

FileWriter(Stringfilename,boolean append): 该构造函数:当传入的boolean类型值为true时,会在指定文件末尾处进行数据的续写。

 

BufferedWriter:该类套接在其他输出流上,提供缓冲功能。

两个构造方法:

BufferedWriter(Writerw):指定需要套接的流。

BufferedWriter(Writerw,int n):n用于之指定缓冲区的大小。

特有方法:

newLine():跨平台的换行符。

练习:通过缓冲区的形式,对文本文件进行拷贝。

public static void main(String[] args)
{
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
String line = null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}

readLine():方法的原理:

其实缓冲区中的该方法,用的还是与缓冲区关联的流对象的read方法。

只不过,每一次读到一个字符,先不进行具体操作,先进行临时存储。

当读取到回车标记时,将临时容器中存储的数据一次性返回。

实现自己的BufferedReader:

class MyBufferedReader
{
private Reader r;
MyBufferedReader(Reader r)
{
this.r = r;
}
public String myReadLine()throws IOException
{
//1,创建临时容器。
StringBuilder sb = new StringBuilder();
 
//2,循环的使用read方法不断读取字符。
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();
}
}

 

装饰设计模式:

装饰设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。

装饰和继承都能实现一样的特点:进行功能的扩展增强,但是装饰比继承灵活,装饰的特点:装饰类和被装饰类都必须所属同一个接口或者父类。

该模式和继承有什么区别呢?

它比继承有更好的灵活性。通常装饰类和被装饰类都同属与一个父类或者接口。

举例:

Writer:(注:不要误解,以下两个对象不存在,只为举例。)

|--MediaWriter

    |--BufferedMediaWriter

|--TextWriter

    |--BufferedTextWriter

Writer中子类对象过多,那么为了提高每一个对象效率,每一个对象都有一个自己的子类Buffered

虽然可以实现,但是继承体系变的很臃肿。

其实子类都是在使用缓冲技术。可以对缓冲技术进行描述,将需要增强的对象传递给缓冲区即可。这就是多态,提高了程序的扩展性。

同时BufferedWriter中一样具体write方法,只不过是增强后的write。

所以BuferedWriter也应该是Writer中的一个子类。

class BufferedWriter extends Writer
{
private Writer w;
BufferedWriter(Writer w)
{
this.w = w;
}
}

这就是装饰设计模式。

 

 

 


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值