输入流,输出流

来源:互联网 发布:html时间轴源码 编辑:程序博客网 时间:2024/04/25 22:15

字节流:

InputStrean  字节输入流 从文件到程序

OutputStream  字节输出流 从程序到文件

字节输入流是指数据以字节形式从其他文件或者终端设备想程序流入;

输入流只能从流中读取数据使用InputStrean类完成

字节输出流:数据以字节形式从程序流出,输出流只能向流中写入数据,使用OutputStream

InputStrean的主要方法

方法

描述

Public void close()

关闭输入流

Public abstract int read()

以数字的方式读取内容

Public int read(byte [] b)

将内容读取到byte数组中,同时返回读入的个数

 

 

OutputStream的主要方法

方法

描述

Public void close()

关闭输出流

Public abstract int write(int b)

在数据流中写入一个字节

Public void  write(byte[] b)

在数据流中写入一个byte数组

Public void  write(byte[] b,int off,int len)

在数据流中写入一个指定范围byte数组

Public void flush()

刷新缓冲区

 

FileInputStream是InputStrean的子类,主要用于从文件读取数据;

FileOuputStream是OutputStream的子类,主要用于向文件中写入数据。

Public FileOuputStream(File f,boolean flag)

Boolean flag 参数是可选的,true表示追加模式打开文件,false表示以覆盖模式打开文件。默认flag参数值是flase

Public FielInputStream(File file);

 

BufferedInputStrean和BufferedOutputStream为InputStrean和OutputStream增加了内存缓冲区,根本目的是允许java的IO流一次操作多个字节,从而提高系统的性能。

BufferedInputStream(InputStrean in) //按照32个字节缓冲区的缓冲流

BufferedInputStream(InputStrean in,int size)//指定大小的缓冲流

 

 

BufferedOutputStream(OutputStream in) //按照32个字节缓冲区的缓冲流

BufferedOutputStream(OutputStream in,int size)//指定大小的缓冲流

BufferedOutputStream 中的flush方法可以强制输出缓冲区的数据

 

 

 

对象序列化和反序列化;

把Java对象转换成字节序列的过程成为对象序列化

把字节序列恢复到java对象的过程叫做对象的发序列化

 

序列化类的对象要求实现java.io.Serializable;

 

Public ObjectInputSrteam(inputStream in)

构造方法

构造输入对象

Final object readObject()

方法

从指定位置读取对象

 

Public ObjectOutStream

(inputStream in)

构造方法

构造输出对象

Final void writeObject()

方法

输出对象的指定位置

//对象序列化:对象转换成字节

File f=new File(“d:”+Fiel.separator+”stuInfo.txt”);

OutputStream outStream=new FileOutputStream(f);

ObjectOutputStream os=new ObjectOutputStream(outStream);

Os.writeObject(new Student(“tom”,20));

outStream.close();

os.close();

 

//对象反序列化:自己转换成对象

File f=new File(“d:”+Fiel.separator+”stuInfo.txt”);

InputStream inStream=new FileInputStream(f);

ObjectInputStream os=new ObjectInputStream(in);

Object object=in。readObject();

Student stu=(Student)object;

System.out.print(“姓名”+stu.getName());

System.out.print(“姓名”+stu.getAgee());

inStream.close();

in.close();                                                                              

 

字符流Reader和Writer 抽象类

Reader

方法

描述

Public abstract void close()

关闭输入流

Public int read()

读取单个字符

Public int read(char[] c)

将内容读取到字符流数组中,并返回读取的长度

 

writer

方法

描述

Public abstract void close()

关闭输出流

Public int writer(String str)

输出字符串到流中

Public int writer(char[] c)

输出字符数组到流中

Public abstarct void flush()

强制清空缓存

 

FileReader和FileWriter是Reander和Writer的实现子类,主要用于读写文件

File f=new File(“d:demo/.doc”);

Writer out=new FileWriter(f);

Out.wirter(“Hello word”);

Out.close();

Reader reader=new FileReader(f);

Char c[]=new char[1024];

Int len=reandre.read(c);

 

InputStreamReader 和OutputStreamWriter 分别是Reander和Writer的子类,二者用于字节流和字符流之间的转换。

InputStreamReader用于将输入的字节流转变为字符流

OutputStreamWriter  用于将输入的字符流转变为字节流

 

InputStreamReader(InputStream in)

InputStreamReader(InputStream in,String charsetName)

 

OutputStreamWriter ((OutputStream out))

OutputStreamWriter (OutputStream out,String charsetName)

 

File f=new File(“d;/demo.txt”);

OutputStreamWriter os=new OutputStreamWriter(new FileOPutInStream(f));

Os.write(“hello word”);

Os.close();

 

BufferedReader和BufferedWriter

BufferedReader和BufferedWriter是带缓冲区的Reader和Writer.

使用BufferedReader读取文本时,将首先从文件中读取字符数据并存入缓冲区中,然后调用read(),先冲缓冲区开始读取,缓冲区不足是再从文件中读取;

使用BufferedWriter时,写入数据将先存储到缓冲区中,在缓冲区饱满的情况下将一次性写入目的地。

通过缓冲区可以减少对硬盘的输入或输出操作,提高文件存取效率。

BufferedReader

方法

类型

描述

BufferedReader(Reader in )

构造方法

接受Render类实例

Public String readLine()

方法

从缓冲区读取第一行文本

Public int  read()

方法

读取单个字符

Public int  read(char[] c,int off,int len)

方法

读取字符数组的一部分

 

 

 

 

 

BufferedWriter

方法

类型

描述

BufferedWriter(Reader in )

构造方法

接受Writer类实例

Public String newe()

方法

写入一个行分隔符

Public int  write(int c)

方法

写入单个字符

Public int  writer(char[] c,int off,int len)

方法

写入字符数组的一部分

Public int witer(String s,t off,int len)

 

写入字符数串的一部分

 

File f=new File(“d;/demo.txt);

FileWriter bufWriter=new BufferedWriter(writer);

bufWriter.writer(“hello word);

bufwruter.close();

writer.close();

FileReader reader =new FileReader(“f);

BufferedReader bufReader=new BufferedReader(reader);

Sysout.out.print(bufReader.readLine());

 

PrintWriter是Writer的子类,其作用是将格式化的数据或对象输出到一个文本输出流

printWriter 类中主要的方法是print()和writer(); 二者提供非常多的参数,可以实现多种形式的输出

字节流

字符流

以字节为单位输出/输出

以字符输出

操作时不用到缓冲区(内存)

使用缓冲区

字节流按8为传输

字符按16为传输

字节流是由字节组成的,字符流是由字符组成的


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

FileInputStream是InputStrean的子类,主要用于从文件读取数据;

FileOuputStream是OutputStream的子类,主要用于向文件中写入数据。

这是一对继承于InputStream和OutputStream的类,用于本地文件读写(二进制格式读写并且是顺序读写,读和写要分别创建出不同的文件流对象);

本地文件读写编程的基本过程为:

①  生成文件流对象(对文件读操作时应该为FileInputStream类,而文件写应该为FileOutputStream类);

②  调用FileInputStream或FileOutputStream类中的功能函数如read()、write(int b)等)读写文件内容;

③  关闭文件(close())。

实例:流文件读写

流文件的单元是字节,所以它不但可以读写文本文件,也可以读写图片、声音、影像文件,这种特点非常有用,因为我们可以把这种文件变成流,然后在网络上传输。

问题是有了通用的流文件以后,为什么还要专门的字符流呢?这是因为文本可以用不同的方式存储,可以是普通的文本(UTF-8编码方式),ASCII文本和Unicode文本,字符流对象可以进行必要的转换,从而读出正确的文本。

有人认为流文件不能读写文本文件,这其实是个误会,因为文本文件本质上也是由字节组成的,当然是流文件的一种。作为读写文件的全体,这是没问题的,但是,如果要处理每次读入的内容,就最好使用字符流。

所以在文本文件处理时,使用字符流是个最常用的方法。

样例:

import java.io.*;

public class FileStreamDemo {

public static void main(String[] args) throws IOException {

//创建两个文件,face.gif是已经存在文件,newFace.gif是新创建的文件

File inFile = new File("face.gif");

File outFile = new File("newFace.gif");

//创建流文件读入与写出类

FileInputStream inStream = new FileInputStream(inFile);

FileOutputStream outStream = new FileOutputStream(outFile);

//通过available方法取得流的最大字符数

byte[] inOutb = new byte[inStream.available()];

inStream.read(inOutb);  //读入流,保存在byte数组

outStream.write(inOutb);  //写出流,保存在文件newFace.gif中

inStream.close();

outStream.close();

}

}

实例:读写任意大文件应用

因为byte数组最大存储值不超过64M,所以当一个文件大于60M 的时候,需要分开几个流操作。我们把上面的程序作一个修改,就可以写入任意大小的文件。这个程序应用了FileInputStream类的方法如下:

read(byte[] b,int off,int len)

把特定位置的流内容读入数组,已经读入byte[]数组的内容,会在流文件中删除。

程序运行的结果会产生一个新文件。

样例:

import java.io.*;

public class FileStreamDemo2 {

public static void main(String[] args) throws IOException {

//创建两个文件

File inFile = new File("tcty36.rm");

File outFile = new File("newtcty36.rm");

//最大的流为60Mb,当文件的容量大于60Mb的时候便分开流

final int MAX_BYTE = 60000000;

long streamTotal = 0;  //接受流的容量

int streamNum = 0;  //流需要分开的数量

int leave = 0;  //文件剩下的字符数

byte[] inOutb;  //byte数组接受文件的数据

//创建流文件读入与写出类

FileInputStream inStream = new FileInputStream(inFile);

FileOutputStream outStream = new FileOutputStream(outFile);

//通过available方法取得流的最大字符数

streamTotal = inStream.available();

//取得流文件需要分开的数量

streamNum = (int)Math.floor(streamTotal/MAX_BYTE);

//分开文件之后,剩余的数量

leave = (int)streamTotal % MAX_BYTE;

//文件的容量大于60Mb时进入循环

if (streamNum > 0) {

for(int i = 0; i < streamNum; ++i){

inOutb = new byte[MAX_BYTE];

//读入流,保存在byte数组

inStream.read(inOutb, 0, MAX_BYTE);

outStream.write(inOutb);  //写出流

outStream.flush();  //更新写出的结果

}

}

//写出剩下的流数据

inOutb = new byte[leave];

inStream.read(inOutb, 0, leave);

outStream.write(inOutb);

outStream.flush();

inStream.close();

outStream.close();

}

}

------------------------------------------------------------------------------------------------------------------------

BufferedInputStrean和BufferedOutputStream为InputStrean和OutputStream增加了内存缓冲区,根本目的是允许java的IO流一次操作多个字节,从而提高系统的性能。

BufferedInputStream(InputStrean in) //按照32个字节缓冲区的缓冲流

BufferedInputStream(InputStrean in,int size)//指定大小的缓冲流

BufferedOutputStream 中的flush方法可以强制输出缓冲区的数据


1.  java.io.BufferedInputStream与java.io.BufferedOutputStream可以为InputStream,OutputStream类增加缓冲区功能。构建BufferedInputStream实例时,需要给定一个InputStream类型的实例,实现BufferedInputStream时,实际上最后是实现InputStream实例。同样,构建BufferedOutputStream时,也需要给定一个OutputStream实例,实现BufferedOutputStream时,实际上最后是实现OutputStream实例。

2. BufferedInputStream的数据成员buf是一个位数组,默认为2048字节。当读取数据来源时,例如文件,BufferedInputStream会尽量将buf填满。当使用read()方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取。当buf中的数据不足时,BufferedInputStream才会再实现给定的InputStream对象的read()方法,从指定的装置中提取数据

3. BufferedOutputStream的数据成员buf也是一个位数组,默认为512字节。当使用write()方法写入数据时实际上会先将数据写到buf中,当buf已满时才会实现给定的OutputStream对象的write()方法,将buf数据写到目的地,而不是每次都对目的地作写入的动作

Java代码 复制代码
  1. package ysu.hxy;   
  2.   
  3. import java.io.*;   
  4.   
  5. public class BufferedStreamDemo   
  6. {   
  7.     public static void main(String[] args)   
  8.     {   
  9.         try  
  10.         {   
  11.             byte[] data new byte[1];   
  12.   
  13.             File srcFile new File(args[0]);   
  14.             File desFile new File(args[1]);   
  15.   
  16.             BufferedInputStream bufferedInputStream    
  17.                 new BufferedInputStream(new FileInputStream(srcFile));   
  18.   
  19.             BufferedOutputStream bufferedOutputStream    
  20.                 new BufferedOutputStream(new FileOutputStream(desFile));   
  21.   
  22.             System.out.println("复制文件:"+srcFile.length()+"字节");   
  23.   
  24.             while(bufferedInputStream.read(data)!=-1)   
  25.             {   
  26.                 bufferedOutputStream.write(data);   
  27.             }   
  28.   
  29.             //将缓冲区中的数据全部写出   
  30.             bufferedOutputStream.flush();   
  31.   
  32.             //关闭流   
  33.             bufferedInputStream.close();   
  34.             bufferedOutputStream.close();   
  35.   
  36.             System.out.println("复制完成");   
  37.         }   
  38.         catch(ArrayIndexOutOfBoundsException e)   
  39.         {   
  40.             System.out.println("using:java UseFileStream src des");   
  41.             e.printStackTrace();   
  42.         }   
  43.         catch(IOException e)   
  44.         {   
  45.             e.printStackTrace();   
  46.         }   
  47.     }   
  48. };  

   为了确保缓冲区中的数据一定被写出至目的地,建议最后执行flush()将缓冲区中的数据全部写出目的流中。


----------------------------------------------------------------------------------------------------------------------


ObjectInputStream与ObjectOutputStream类


1.

ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入

2. 

 import java.io.*;

public class serializtion {

 
 public static void main(String[] args)throws IOException{
  Student s1=new Student("张三", 1, 15, "化学");
  Student s2=new Student("李四", 2, 19, "生物");
 
  FileOutputStream fout=new FileOutputStream("student.txt");
  ObjectOutputStream out=new ObjectOutputStream(fout);
  out.writeObject(s1);
  out.writeObject(s2);
  out.close();
  FileInputStream fin=new FileInputStream("student.txt");
  ObjectInputStream in=new ObjectInputStream(fin);
  try {
   s1=(Student) in.readObject();
   s2=(Student) in.readObject();
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    in.close();
    System.out.print("name:"+s1.name);
    System.out.print(" id:"+s1.id);
    System.out.print(" age:"+s1.age);
    System.out.println(" department:"+s1.department);
    System.out.print("name:"+s2.name);
    System.out.print(" id:"+s2.id);
    System.out.print(" age:"+s2.age);
    System.out.println(" department:"+s2.department);
 }

}
3.import java.io.*;

public class Student implements Serializable {
 
        String name;
        int id ;
     int age;
        String department;

  public Student(String name, int id, int age, String department) {
   this.age = age;
   this.department = department;
   this.id = id;
   this.name = name;

  }
 }

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


FileReaderFileWriterReanderWriter的实现子类,主要用于读写文件

java中的 FileWriter类 和 FileReader类的一些基本用法

1,FileWriter类(字符输出流类)

构造方法:FileWriter fw = new FileWriter(String fileName);//创建字符输出流类对象和已存在的文件相关联。文件不存在的话,并创建。

                                             如:FileWriter fw = new FileWriter("C:\\demo.txt");

                  FileWriter fw = new FileWriter(String fileName,boolean append);//创建字符输出流类对象和已存在的文件相关联,并设置该该流对文件的操作是否为续写。

                                             如:FileWriter fw = new FileWriter("C:\\demo.txt",ture); //表示在fw对文件再次写入时,会在该文件的结尾续写,并不会覆盖掉。

主要方法: void write(String str)   //写入字符串。当执行完此方法后,字符数据还并没有写入到目的文件中去。此时字符数据会保存在缓冲区中。

                                                        此时在使用刷新方法就可以使数据保存到目的文件中去。

                  viod flush()                //刷新该流中的缓冲。将缓冲区中的字符数据保存到目的文件中去。

                  viod close()               //关闭此流。在关闭前会先刷新此流的缓冲区。在关闭后,再写入或者刷新的话,会抛IOException异常。

[java] view plaincopy
  1. package filewriter;  
  2.   
  3. import java.io.FileWriter;  
  4. import java.io.IOException;  
  5.   
  6. public class Filewriter {  
  7.   
  8.     private static final String LINE_SEPARATOR = System.getProperty("line.separator");  
  9.   
  10.     /** 
  11.      *  
  12.      * @param args 
  13.      * @throws IOException  
  14.      */  
  15.     public static void main(String[] args) throws IOException {  
  16.         /** 
  17.          * 创建一个可以往文件中写入字符数据的字符流输出流对象 
  18.          * 创建时必须明确文件的目的地 
  19.          * 如果文件不存在,这回自动创建。如果文件存在,则会覆盖。 
  20.          * 当路径错误时会抛异常 
  21.          *  
  22.          * 当在创建时加入true参数,回实现对文件的续写。 
  23.          */  
  24.         FileWriter fw = new FileWriter("C:\\demo1.txt",false);  
  25.         /** 
  26.          * 调用该对象的write方法,向文件写入字符。 
  27.          *  
  28.          * 其实写入到了临时存储缓冲区中 
  29.          */  
  30. //      fw.write("hello \r\nworld!");//windows中的换行为\r\n    unix下为\r。  
  31.         fw.write("aello"+LINE_SEPARATOR+"world!");  
  32.         fw.write("hahaha");  
  33.         /** 
  34.          * 进行刷新,将字符写到目的地中。 
  35.          */  
  36. //      fw.flush();  
  37.         /** 
  38.          * 关闭流,关闭资源。在关闭前会调用flush方法 刷新缓冲区。关闭后在写的话,会抛IOException 
  39.          */  
  40.         fw.close();  
  41.           
  42.   
  43.     }  
  44.   
  45. }  

关于FileWriter的的异常处理。

[java] view plaincopy
  1. package filewriter;  
  2.   
  3. import java.io.FileWriter;  
  4. import java.io.IOException;  
  5.   
  6. public class IOExceptionDemo {  
  7.   
  8.     private static final String LINE_SEPARATOR = System.getProperty("line.separator");  
  9.     public static void main(String[] args) {  
  10.   
  11.         FileWriter fw = null;  
  12.         try {  
  13.             fw = new FileWriter("k:\\Demo.txt"true);  
  14.             fw.write("hello" + LINE_SEPARATOR + "world!");  
  15.         } catch (Exception e) {  
  16.             System.out.println(e.toString());  
  17.         } finally {  
  18.             if (fw != null)  
  19.                 try {  
  20.                     fw.close();  
  21.                 } catch (IOException e) {  
  22.                     throw new RuntimeException("关闭失败!");  
  23.                 }  
  24.         }  
  25.     }  
  26. }  

2,FileReader类

1,构造方法

FileReader fr = new FileReader(String fileName);//使用带有指定文件的String参数的构造方法。创建该输入流对象。并关联源文件。

2,主要方法

int read(); // 读取单个字符。返回作为整数读取的字符,如果已达到流末尾,则返回 -1。

int read(char []cbuf);//将字符读入数组。返回读取的字符数。如果已经到达尾部,则返回-1。

void close();//关闭此流对象。释放与之关联的所有资源。

[java] view plaincopy
  1. package Filereader;  
  2.   
  3. import java.io.FileReader;  
  4. import java.io.IOException;  
  5.   
  6. public class FileReaderDemo {  
  7.   
  8.     public static void main(String[] args) throws IOException {  
  9.         /** 
  10.          * 创建读取字符数据的流对象。 
  11.          * 读取路径不正确时会抛 IOException 
  12.          * 用以个读取流对象关联一个已存在文件。 
  13.          */  
  14.         FileReader fr = new FileReader("demo.txt");  
  15.         /** 
  16.          * 用Reader中的read方法读取字符。 
  17.          */  
  18.         /*int ch = fr.read(); 
  19.         System.out.print((char)ch); 
  20.         int ch1 = fr.read(); 
  21.         System.out.print((char)ch1); 
  22.         int ch2 = fr.read(); 
  23.         System.out.print((char)ch2);*/  
  24.         int ch = 0;  
  25.         while((ch = fr.read()) != -1){  
  26.             System.out.print((char)ch);  
  27.         }  
  28.         fr.close();  
  29.         }  
  30. }  


 

用FileReader  和 FileWriter 写的复制文本文件的小程序。

[java] view plaincopy
  1. package IOtest;  
  2.   
  3. import java.io.FileNotFoundException;  
  4. import java.io.FileReader;  
  5. import java.io.FileWriter;  
  6. import java.io.IOException;  
  7.   
  8. public class TxtCopy {  
  9.   
  10.     /** 
  11.      * 将C:\\的myHeart.txt copy 到 D:\\下 
  12.      *  
  13.      * 首先创建Reader读取数据数据的 读取流对象。 
  14.      *  
  15.      * @throws FileNotFoundException 
  16.      */  
  17.     public static void main(String[] args) {  
  18.         FileReader fr = null;  
  19.         FileWriter fw = null;  
  20.         try {  
  21.             fr = new FileReader("C:\\my.txt");  
  22.             fw = new FileWriter("D:\\you.txt");  
  23.             //读一个字符,写一个字符方法  
  24. //          int ch = 0;  
  25. //  
  26. //          while ((ch = fr.read()) != -1) {  
  27. //              fw.write(ch);  
  28. //          }  
  29.             char []buf = new char[1024];  
  30.             int len = 0;  
  31.             //读一个数组大小,写一个数组大小方法。  
  32.             while((len = fr.read(buf)) != -1){  
  33.                 fw.write(buf, 0, len);                
  34.             }  
  35.               
  36.         } catch (Exception e) {  
  37.             System.out.println(e.toString());  
  38.         } finally {  
  39.             if (fr != null)  
  40.                 try {  
  41.                     fr.close();  
  42.                 } catch (Exception e2) {  
  43.                     throw new RuntimeException("关闭失败!");  
  44.                 }  
  45.             if (fw != null)  
  46.                 try {  
  47.                     fw.close();  
  48.                 } catch (IOException e) {  
  49.                     throw new RuntimeException("关闭失败!");  
  50.                 }  
  51.         }  
  52.     }  
  53. }  
-------------------------------------------------------------------------------------------------------------------------------

BufferedReaderBufferedWriter

很明显bufferedreader的用法比inputstream要复杂,复杂的存在必然会导致优势的存在!我们都知道inputstream是一个字节一个字节的读取,每次读取都会执行一次IO,我们知道io的操作是很费时间的,这就必然会导致程序的效率,而bufferedreader很好的解决这一问题,它可以一次读取大量的数据,大大减少了io次数,效率也就上去了,这就像有辆能乘坐一百人的大巴,从热力输送学生到理工本部,司机脑残,学生没睡醒,非要一次只坐一个同学,大巴的来回跑一百趟才能把这一百人全部送到学校,这就类似inputstream,另一个司机是清华毕业,智商当然高了,他让这一百人全部上车,一次九ok了,虽然在学生上车时多用了点时间,但总时间要远比那个脑残司机要少的多!!!当然在计算机中不会有这么大的时间差!!哔哔了这么多,应该表述清楚了,下面是一个bufferedreader的例子,本想写个关于bufferedreader比inputstream快的例子,可能是本人人品太好了吧,运行的结果每次都是0毫秒~~~

package cn.tsp2s.liu.liubao;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Administrator
 */
public class TestBufferedReader {
    public static void main(String[] args){
        FileReader in=null;
        BufferedReader read=null;
        String s=null;
        BufferedWriter writer=null;
        try {
            in = new FileReader("d:\\java\\TestLeap.java");
            read=new BufferedReader(in);
            writer=new BufferedWriter(new FileWriter("d:\\java\\leap.txt"));
            while ((s = read.readLine()) != null) {
               // System.out.println(s);
                writer.write(s);
                //这里调用newline()方法是让它输出和读取的完全一致,理由不解释
                writer.newLine();
                //这里一定要调用flush()方法,如果不调用,文件中将会显示不全或者压根就不显示任何东西,理由不解释,你肯定知道
                writer.flush();     
            }
        } catch (FileNotFoundException ex) {
            System.out.println("找不到指定文件!!");
        }catch (IOException e) {
            System.out.println("文件读取有误!");
        }finally{
            try {
                writer.close();
                read.close();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }
}

int b;
   while((b=bf.read())!=-1){
    System.out.println(bf.readLine());
   }

发现每行的第一个字符都没有显示出来,原因呢:b=bf.read())!=-1  每次都会先读取一个字节出来,所以后面的bf.readLine());
读取的就是每行少一个字节

所以,应该使用

String valueString = null;
   while ((valueString=bf.readLine())!=null){
    
    
    System.out.println(valueString);
   }

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

PrintStream和PrintWriter

PrintStream

PrintStream在OutputStream基础之上提供了增强的功能,即可以方便地输出各种类型的数据(而不仅限于byte型)的格式化表示形式。PrintStream的方法从不抛出IOEceptin

 

PrintWriter

PrintWriter提供了PrintStream的所有打印方法,其方法也从不抛出IOException。

与PrintStream的区别:作为处理流使用时,PrintStream只能封装OutputStream类型的字节流,而PrintWriter既可以封装OutputStream类型的字节流,还能够封装Writer类型的字符输出流并增强其功能。

 

 

实例:复制文件。

[java] view plaincopy
  1. import java.io.*;  
  2. class IODemo  
  3. {  
  4.     public static void main(String[] args)   
  5.     {  
  6.         try  
  7.         {  
  8.         FileReader fr=new FileReader("a.txt");  
  9.         BufferedReader br=new BufferedReader(fr);  
  10.         FileWriter fw=new FileWriter("33.txt");  
  11.         PrintWriter pw=new PrintWriter(fw);  
  12.   
  13.         String s=br.readLine();  
  14.             while(null!=s)  
  15.             {  
  16.                 //PrintWriter的println方法 相当于  
  17.                 //BufferedWriter 的write() + newLine()  
  18.                 pw.println(s);  
  19.                 s=br.readLine();  
  20.             }  
  21.   
  22.             br.close();  
  23.             pw.close();  
  24.         }  
  25.         catch (IOException e)  
  26.         {  
  27.             e.printStackTrace();  
  28.         }  
  29.           
  30.     }  
  31. }  


如果将上面的PrintWriter换成PrintStream会报错,因为PrintStream只能封装字节流,不能封装Writer类对象。

 

注:如果对输出流的格式有特殊要求,使用 PrintStream, PrintWriter显然会比较方便,详细可以产看JAVA API文档。

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

java.ByteArrayInputStream与ByteArrayOutputStream再次理解

第一次看到ByteArrayOutputStream的时候是在Nutch的部分源码,后来在涉及IO操作时频频发现这两个类的踪迹,觉得确实是很好用,所以把它们的用法总结一下。

  ByteArrayOutputStream的用法

以下是JDK中的记载: 

public class ByteArrayOutputStream  extends OutputStream

    此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()和 toString()获取数据

    关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException

   我的个人理解是ByteArrayOutputStream是用来缓存数据的(数据写入的目标(output stream原义)),向它的内部缓冲区写入数据,缓冲区自动增长,当写入完成时可以从中提取数据。由于这个原因,ByteArrayOutputStream常用于存储数据以用于一次写入。

实例:

从文件中读取二进制数据,全部存储到ByteArrayOutputStream中。

FileInputStream fis=new FileInputStream("test");

BufferedInputStream bis=new BufferedInputStream(fis);

ByteArrayOutputStream baos=new ByteArrayOutputStream();

int c=bis.read();//读取bis流中的下一个字节

while(c!=-1){

     baos.write(c);

     c=bis.read();

}

bis.close();

byte retArr[]=baos.toByteArray();

 

ByteArrayInputStream的用法

    相对而言,ByteArrayInputStream比较少见。先看JDK文档中的介绍:

public class ByteArrayInputStreamextends InputStreamByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。

关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。

构造函数:

ByteArrayInputStream(byte[] buf) 

注意它需要提供一个byte数组作为缓冲区。

    与大部分Inputstream的语义类似,可以从它的缓冲区中读取数据,所以我们可以在它的外面包装另一层的inputstream以使用我们需要的读取方法。

    个人认为一个比较好的用途是在网络中读取数据包,由于数据包一般是定长的,我们可以先分配一个够大的byte数组,比如byte buf[]=new byte[1024];

然后调用某个方法得到网络中的数据包,例如:

Socket s=...;

DataInputStream dis=new DataInputStream(s.getInputStream());

dis.read(buf);//把所有数据存到buf中

ByteArrayInputStream bais=new ByteArrayInputStream(buf); //把刚才的部分视为输入流

DataInputStream dis_2=new DataInputStream(bais);

//现在可以使用dis_2的各种read方法,读取指定的字节

比如第一个字节是版本号,dis_2.readByte();

等等……

上面的示例的两次包装看上去有点多此一举,但使用ByteArrayInputStream的好处是关掉流之后它的数据仍然存在。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

包装类DataOutputStream、DataInputStream的常见用法

包装类DataOutputStream、DataInputStream为我们提供了多种对文件的写入和读取方法,

如writeBoolean(),writeUTF(),writeChar,writeByte(),writeDouble()等和对应的read方法,

这些方法极大的方便了我们的写入和读取操作,下面结合一个程序来探讨一下这些方法的使用。

 

import java.io.*;
public class TestDataStream {

 public static void main(String[] args) throws Exception {
  
  FileOutputStream fos=new FileOutputStream("data.txt");
  BufferedOutputStream bos=new BufferedOutputStream(fos);
  DataOutputStream dos=new DataOutputStream(bos);
  
  FileInputStream fis=new FileInputStream("data.txt");
  BufferedInputStream bis=new BufferedInputStream(fis);
  DataInputStream dis=new DataInputStream(bis);
  
  String str="你好hi";
  dos.writeUTF(str);   //按UTF-8格式写入
  dos.writeChars(str); //按字符写入
  //按字节写入有两种方法,第一种方法只能适应无汉字的情况;
  //因为方法1在写入时会把所有的字符都按1个字节写入,而汉字的表示需要2个字节,
  //这就造成了数据的丢失,读入时就会出现乱码。
  //而方法2在将字符串转换为字节数组时就把汉字字符变为了2个字节,
  //写入文件的时候也会按2个字节的文字写入,这样读取的时候就不会出现问题
  dos.writeBytes(str);//方法1:将整个字符串按字节写入
  byte[] b=str.getBytes();
  dos.write(b);  //方法2:将字符串转换为字节数组后再逐一写入
  dos.close();
  //按UTF-8格式读取

  System.out.println(dis.readUTF());
  //字符读取
  char [] c=new char[4];
  for(int i=0;i<4;i++){     
   c[i]=dis.readChar();   //读取4个字符
  }
  System.out.print(new String(c,0,4));
  System.out.println();
  //字节读取

  byte [] b1=new byte[4];
  dis.read(b1); //读取4个字节
  System.out.print(new String(b1,0,4));//输出时会出现乱码
  System.out.println();
  
  byte [] b2=new byte[1024];
  int len=dis.read(b2); //按字节读取剩余的内容
  System.out.println(new String(b2,0,len));
 }

}

输出结果为:

你好hi
你好hi
`}hi
你好hi

 

注意1:一般情况下在读入时尽量按照写入时的格式进行读取,

否则有可能会出现显示乱码或程序出现异常。

如首先写入文件用的是writeUTF(),在读取的时候如果不是用readUTF()就会出现乱码,

如果readUTF()读取的内容不是UTF-8格式的,程序就会抛出异常。

 

注意2:如程序中注释所说,对于出现汉字字符的情况不能用writeBytes(),这会在写入文件时丢弃汉字字符的第一个字节从而在读取时出现错误。

 

注意3:所有的读取方法都是共享一个位置指示器的,即在前面的read方法执行后,后面再执行其他read方法都是从上一个read方法读取到的位置开始向后读取的。如开始执行了1次readByte()后面的readChar是从第2个字节开始读的。


0 0
原创粉丝点击