您的位置:首页 > 编程语言 > Java开发

javaIO之字符流

2012-11-22 09:11 211 查看
1、如何判断是输入流,还是输出流

  以内存为参照,如果数据向内存流动,则是输入流,反之则为输出流



2、流的分类

(1)字节流:可以用于读写二进制文件及任何类型文件byte

(2)字符流:可以用于读写文本文件

字节流(抽象基类)

字符流(抽象基类)

输入

InputStream

Reader

输出

OutputStream

Writer

3、字符流

 3.1、写数据

问题:怎样在硬盘上创建一个文件并写入一些文字数据?

  Writer中有很多子类,找到一个专门用于操作文件Writer子类对象FileWriter。

package com.itheima.io;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

public class FileDemo0 {

public static void main(String[] args) {

//首先创建文件

File file=new File("d:"+File.separator+"heima.txt");

//判断这个文件存在不存在

if(!file.exists()){//如果不存在则创建

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//因为是把数据从流中读取到文件中,所以用到输出流

FileWriter writer=null;

try {

//创建一个文件输出流

writer=new FileWriter(file);

//往缓冲中写数据

writer.write("黑马程序员");

//因为刚写的数据不会直接写到文件中,而是写到了缓冲中,所以需要刷新

writer.flush();

} catch (IOException e) {

e.printStackTrace();

}finally{//无论如何必须关闭流,释放资源

try{

if(writer!=null)

writer.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

  从上面的实例中可以看出,对于字符流的写,它不是直接写到文件中去,而是先写到缓冲中去,如果这个缓冲装满后就往文件中写入,不满时是不会写到文件中去。如果想手动刷新,需要调用流中的flush方法。

  flush()和close()方法的区别

Flush刷新后,流可以继续使用

Close方法刷新后,会将流关闭。

上面的代码也提供了怎样处理异常的方法

Try{

  //处理流

}catch(Exception e){

}finally{

  //关闭流

}

流用完后,必须关闭,释放内存,所以应该关闭流的操作应放到finally中。

上面的操作,如果在指定位置已经有了此文件,则执行程序后会覆盖掉原来的文件。

问题:怎样在已有的文件中续写数据呢?

  通过上面的程序是无法续写的,我们查看FileWriter的文档可知,它有一个构造方法

FileWriter(File file, boolean append)

根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。 

参数:

file- 要写入数据的 File 对象

append- 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处

所以我们只需把上面的一
4000
段代码改一些即可

writer=new FileWriter(file);

改成

writer=new FileWriter(file,true);

  这样就不会覆盖掉原来的数据了,而是在原来数据的后面续写。

问题:上面可以续写了,那么怎样把续写的内容添加到下一行呢?

writer.write("黑马程序员");

改成

writer.write("黑马程序员\r\n都能找到很好的工作");即可。

3.2、读数据

问题:从硬盘文件中读取数据打印到控制台

方法一:通过字节来读

package com.itheima.io;

import java.io.File;

import java.io.FileReader;

public class FileDemo2 {

public static void main(String[] args) {

//首先创建一个文件

File file=new File("d:"+File.separator+"heima.txt");

FileReader reader=null;

try{

//创建一个读取流

reader=new FileReader(file);

int ch=0;//一个字节一个字节的读

while((ch=reader.read())!=-1){

               System.out.print((char)ch);

}

}catch(Exception e){

System.out.println("文件不存在");

}finally{

try{

if(reader!=null)

reader.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

方法二:通过字符数组来读取

package com.itheima.io;

import java.io.File;

import java.io.FileReader;

public class FileDemo2 {

public static void main(String[] args) {

//首先创建一个文件

File file=new File("d:"+File.separator+"heima.txt");

FileReader reader=null;

try{

//创建一个读取流

reader=new FileReader(file);

char[]ch=new char[1024*1024];//定义一个字符数组

int len=0;//定义一个长度

while((len=reader.read(ch))!=-1){

               System.out.print(new String(ch,0,len));

}

}catch(Exception e){

System.out.println("文件不存在");

}finally{

try{

if(reader!=null)

reader.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

  方法一用read()方法读取单个字符,是读取一个数据写入一个数据,消耗时间,而方法二read(char[]ch)是读取一个字符数组,然后一起写入,效率较高。

问题:读和写结合,将一个盘中的文本文件复制到另一个盘中。

步骤如下:

(1)在另一个盘中创建一个文件,用于存储第一个盘中的数据

(2)定义读取流和第一个盘相关联

(3)通过不断的读写完成数据的存储

(4)关闭相关的流

代码如下:

package com.itheima.io;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

public class FileDemo3 {

public static void main(String[] args) {

  //第一个盘中的文件

File file1=new File("d:"+File.separator+"heima.txt");

//第二个盘中的文件

File file2=new File("c:"+File.separator+"heima_copy.txt");

FileReader reader=null;

FileWriter writer=null;

try{

//判断一下c盘中是否有文件,没有则创建

if(!file2.exists()){

file2.createNewFile();

}

reader=new FileReader(file1);

writer=new FileWriter(file2);

//利用字符数组进行读取

char[]ch=new char[1024*1024];

int len=0;

while((len=reader.read(ch))!=-1){

//往writer写入数据

writer.write(ch,0,len);

}

}catch(Exception e){

e.printStackTrace();

}finally{

//关闭相关的流

try{

if(writer!=null)

writer.close();

if(reader!=null)

reader.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

上面的程序成功的运行。

  上面一个输入流和一个输出流,而这两个流原本没有什么联系,为了让两者有联系,创建了一个字符数组,用reader.reader()把数据读取到输入流中,存到字符数组中,然后利用writer.writer()方法,把数据写入到输出流。

4、字符流的缓冲区

  作用:提高了对数据的读写效率。所以在创建缓冲区前,必须现有缓冲区。

  在IO中对应的流为:

(1)BufferReader

(2)BufferWriter

把上面的程序通过缓冲区复制文件。

package com.itheima.io;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

public class FileDeom4 {

public static void main(String[] args) {

//把文件封装成一个File

File file1=new File("d:"+File.separator+"heima.txt");

//创建一个复制文件

File file2=new File("e:"+File.separator+"heima_copy.txt");

BufferedReader bufr=null;

BufferedWriter bufw=null;

try{

//实例化bufr对象

bufr=new BufferedReader(new FileReader(file1));

//实例化bufw对象

bufw=new BufferedWriter(new FileWriter(file2));

String line=null;

while((line=bufr.readLine())!=null){

//把读取的数据写到bufw流中

bufw.write(line);

//换行

bufw.newLine();

//刷新

bufw.flush();

}

}catch(Exception e){

System.out.println("不存在的文件");

}finally{

try{

if(bufw!=null)//关闭输出流

bufw.close();

if(bufr!=null)//关闭输入流

bufr.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

}

  通过上面的程序可以看到,我们可以一行一行的进行读取了,BufferedReader中的readLine方法就是读取一个字符串。它是对read方法的封装。

5、装饰设计模式

  当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的类成为装饰类。如BufferedReader.

 装饰类通常通过构造方法接受被装饰的对象,提供更强大的功能。

  装饰类与继承的区别

继承:(以自定义MyReader为例)

MyReader //专门用于读取数据的类

   |--MyTextReader

         |--MyBufferedTextReader

   |--MyMediaReader

         |--MyBufferedMediaReader

装饰类

MyReader

   |--MyTextReader

   |--MyMediaReader

   |--MyBufferedReader

  装饰模式比继承模式要灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系,装饰模式因为增强了已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能,所以装饰类和被装饰类都属于同一个体系。

------- android培训java培训、期待与您交流! ----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  io java