黑马程序员——IO流中常见流的用法

来源:互联网 发布:知乎和天涯哪个真实 编辑:程序博客网 时间:2024/06/17 20:11

 

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流!---------------------- 

 

一、FileWriter:字节写入流

对于IO流的用法,首先从字节流中的FileWriter说起,目标是创建一个文件并写入一些文字数据,比如说要在当前目录下创建一个abc.txt文件,具体步骤如下:

1、创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。其实该步就是在明确数据要存放的目的地。

FileWriter fw = newFileWriter("abc.txt");

2、调用write方法,将字符串写入到流中。

fw.write("abcde");

3、刷新流对象中的缓冲中的数据。这里有两种方法:

第一种是fw.flush();将数据刷到目的地中。

第二种是直接关闭流资源fw.close(),关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。

两种方法的区别在于:flush刷新后,流可以继续使用,close刷新后,会将流关闭。

 

上面的代码在执行时是会发生IOException异常的,我们可以用采用以下思路:

问题一:fw.close()要放在finally中,因为这个关闭资源的语句是一定要执行的;

问题二:创建FileWriter对象要是全局变量,不能在try中,但newFileWriter要在try中,故采用这样的格式:

FileWriter fw = null;

try{

   fw = new FileWriter("XXXX");

   .......

}

问题三:fw.close()也要处理异常,要单独try;

问题四:当fw没被新建对象,为null时,fw.close()会发生空指针异常,所以执行它之前要加if(fw!=null)判断一下。

所以,完整代码应该如下:

FileWriter fw = null;

try{

   fw= new FileWriter("demo.txt");

   fw.write("abcdefg");

}catch (IOException e){

   System.out.println("catch:"+e.toString());

}finally{

   try{

      if(fw!=null)

      fw.close();

   }catch(IOException e){

     System.out.println(e.toString());

   }

}

 

二、FileReader字节读取流

FileReader是从程序中读取数据,在进行初始化时,如果指定的文件不存在,也会发生异常。这里可以有两种方式,第一种是一个字符一个字符读:

1、创建一个文件读取流对象,和指定名称的文件相关联。这一步要保证该文件已经存在,如果不存在,会发生异常FileNotFoundException

FileReader fr = newFileReader(“abc.txt”);//该文件必须是在程序所在目录存在的。

2、调用读取流对象的read方法:一次读一个字符,而且会自动往下读,一直读到没字符了返回-1

int ch = 0;

while((ch = fr.read())!=-1)

具体代码如下:

import java.io.*;

class FileReaderDemo{

          publicstatic void main(String[] args) throws IOException{

  FileReader fr = newFileReader("abc.txt");

                intch = 0;

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

                      System.out.println(ch);

                }

                fr.close();

}

}

第二种是通过字符数组进行读取。具体代码如下:

    import java.io.*;

class FileReaderDemo2{

          publicstatic void main(String[] args) throws IOException{

  FileReader fr = newFileReader("demo.txt");

                //定义一个字符数组。用于存储读到字符。

                char[]buf = new char[1024];

                intnum = 0;

 while((num=fr.read(buf))!=-1){ //read(char[])返回的是读到字符个数。

 System.out.println(newString(buf,0,num));//将字符数组的0num位打印出来

//这里采用这样的方式是因为,如果最后一次读取字符数组不满1024

//那么直接打印buf数组会打印多出一些字符。

                }

  fr.close();

}

}

 

三、BufferedWriter

带缓冲区的字符写入流,缓冲区的出现提高了流的效率,所以在创建缓冲区之前,必须先有流对象。所以,具体步骤如下:

1、  创建一个字符写入流对象。FileWriter fw = newFileWriter(“abc.txt”);

2、  将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

BufferedWriter bufw = newBufferedWriter(fw);

for(int x=1; x<5; x++){

bufw.write("abcd"+x);

   bufw.newLine();//readLine()是缓冲区中提供的一个跨平台的换行方法。

   bufw.flush();//只要用到缓冲区,就要刷新。

}

3、  关闭缓冲区,就是在关闭缓冲区中的流对象。

bufw.close();

 

四、BufferedReader

带缓冲区的字符读取流。

使用这个方法的好处在于这个缓冲区提供了一个一次读一行的方法readLine,方便于对文本数据的获取。当返回null时,表示读到了文件末尾。

通过缓冲区复制一个字符文件的代码如下:

import java.io.*;

class  CopyTextByBuf{

        public static void main(String[] args) {

                   //两个流都是全局变量,先创建对象,但不初始化

                  BufferedReader bufr = null;

                  BufferedWriter bufw = null;

          try{

                   //初始化两个流要放在try代码块中

                   bufr = new BufferedReader(new FileReader("abc.txt"));

                   bufw = new BufferedWriter(newFileWriter("abvc_Copy.txt"));

 

                   String line = null;//定义一个字符串

                   while((line=bufr.readLine())!=null){//当从文件中读取到的行不为null时,执行循环

                            bufw.write(line);//将每一行数据写入流中

                            bufw.newLine();//写完一行字符之后,调用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("写入关闭失败");

                   }

          }

}

}

 

五、LineNumberReader:带行号的缓冲区字符读取流

这个流其实只是在字符读取流的基础上加上了行号,可以通过setLineNumber(int lineNumber)设置行号从多少开始,通过getLineNumber()获取当前行号。

 

六、两个字节流

OutputStream字节输出流,InputStream字节输入流,这里的输入输出是相对程序来说的。这两个流也对应有BufferedOutputStreamBufferedInputStream两个带缓冲区的流来提供读写速度。

复制图片的代码如下:

import java.io.*;

class  CopyPic{

    public static void main(String[] args) {

FileOutputStream fos =null;

         FileInputStream fis = null;

try{

                   fos = new FileOutputStream("1.jpg");

                  fis = new FileInputStream("1_copy.jpg");

 

                   byte[] buf = new byte[1024];//定义一个字节数组用于暂时存储字节数据

                   int len = 0;

                  while((len=fis.read(buf))!=-1){//当字节输入流读取系统文件的字节不为0时,执行循环

                            fos.write(buf,0,len);//字节输出流将字节数组中的数据写到流中

                   }catch (IOException e){

                           throw new RuntimeException("复制文件失败");

                  }finally{

                           try{

                                if(fis!=null)

                                    fis.close();

                           }catch (IOException e){

                                thrownew RuntimeException("读取关闭失败");

                          }try{

                                if(fos!=null)

                                     fos.close();

                           }catch (IOException e){

                                 thrownew RuntimeException("写入关闭失败");

                            }

                  }

       }

}

 

七、转换流:字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流。它包括两个InputStreamReader读取转换流(字节-->字符)和OutputStreamWriter写入转换流(字符-->字节)。

另外为了提高效率,可以使用缓冲技术。故,读取键盘录入的最常见写法为:

BufferedReader bufr = newBufferedReader(new InputStream(System.in));

其中,System.in对应的是标准输入设备,默认是键盘;

BufferedWriter bufw = newBufferedWriter(new OutputStream(System.out));

其中,System.out对应的是标准输出设备,默认是控制台。

以上的输入输出设备也可以自定义,通过System.setIn()System.setOut()这两个方法。

 

八、File

File类中,最应该注意的是Filef = new File(“a.txt”);这个语句只是将a.txt封装成file对象,但是没有创建文件,要创建文件要调用createNewFile()才能创建文件,如果该文件已经存在则不创建并返回flase;如果创建成功,则返回true。这是和输出流很不一样的地方。

File类常见方法:

1、创建。

booleancreateNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false

                        和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

boolean mkdir():创建文件夹。

boolean mkdirs():创建多级文件夹。

2、删除。

boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel

voiddeleteOnExit();在程序退出时删除指定文件。

3、判断。

boolean exists() :文件是否存在.

isFile():文件是否是一个标准文件

isDirectory();文件是否是一个目录

isHidden();文件是否是一个隐藏文件

isAbsolute();此抽象路径名是否为绝对路径名。

4、获取信息。

getName():获取文件名

getPath():获取路径

getParent():返回绝对路径中的父目录;如果是相对路径,返回null,如果相对路径有上一层目录,那么该目录就是返回结果

getAbsolutePath():返回的是绝对路径字符串

getAbsolutePath():返回的是绝对路径,封装成一个文件对象

5、文件列表。

String[] list():调用list方法的file对象必须是封装了一个目录。

Sring File[] list(FilenameFilterfilter):增加一个文件过滤器接口对象。

File[] listFiles():返回的是File对象数组,可以获取多个属性。

示例代码如下:

 

import java.io.*;

class  FileDemo2{

    publicstatic void main(String[] args) {//获取C盘根目录下的所有文件的文件名和大小。

File dir = newFile("c:\\");

          File[]files = dir.listFiles();//返回File数组,即所有C盘根目录下的File对象

          for(Filef : files){//遍历File数组

                  System.out.println(f.getName()+"::"+f.length());//可以获取文件名字和长度等属性

          }

    }

   publicstatic void listDemo_2(){//使用文件过滤器,将目录下所有bmp文件列出来

          Filedir = new File("d:\\java1223\\day18");

          String[]arr = dir.list(new FilenameFilter(){//这里使用匿名内部类,因为该接口只有一个方法

               publicboolean accept(File dir,String name){//复写accept方法

System.out.println("dir:"+dir+"....name::"+name);

                  //由输出结果可以看出,accept方法可以获取指定目录下的所有文件,并根据返回值确定是否存入数组中。

                   if(name.endsWith(".bmp"))

                        returntrue;//返回true,则文件满足条件,存入列表中;

                   else

                        returnfalse;//返回false,则文件不满足条件,不存入列表

                }

           });

          for(String name : arr){//遍历所有文件名称

                 System.out.println(name);

          }

   }

   publicstatic void listDemo(){//该方法只能返回文件名称

          Filef = new File("c:\\abc.txt");

          String[]names = f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。

          for(Stringname : names){

                  System.out.println(name);

          }

   }

}

 

九、打印流

该流提供了打印方法,可以将各种数据类型都原样打印。所以在实际应用中,这个流对象是很经常使用的。它分为字节打印流PrintStream和字符打印流PrintWriter

字节打印流中定义了很多种构造函数,可以传入各种参数类型。包括file对象、字符串路径、字节输出流OutputStream

而字符打印流则比字节打印流多出了一个字符输出流Writer,所以PrintWriter相对来说也就更常用一些。

由于打印流可以接受的数据参数类型有这么几种,所以将PrintWriter作为接收流,代码可以直接变成PrintWriterpw = new PrintWriter(System.out);将流中数据输出到控制台。

另外,PrintWriter还提供了自动换行的写入方法:println(),而且如果想把flush()刷新流方法省略,PrintWriter中还有一个构造函数PrintWriter(OutputStream out,boolean autoFlush)autoFlush是一个boolean变量;如果为true,则println方法将自动刷新输出缓冲区

 

十、对象流ObjectInputStreamObjectOutputStram

功能是使得被操作的对象和流相关联,所以它的构造函数除了无参构造函数,就是带字节流参数的构造函数。

import java.io.*;

class ObjectStreamDemo{

    public static void main(String[] args)throws Exception{//要先调用写入方法,再将数据读取打印出来

          //writeObj();

          readObj();

     }

     publicstatic void readObj()throws Exception{

           ObjectInputStreamois = new ObjectInputStream(newFileInputStream("obj.txt"));

          Person p = (Person)ois.readObject();//可以调用readObject()方法直接操作Object对象

          System.out.println(p);

          ois.close();

     }

     publicstatic void writeObj()throws IOException{

           ObjectOutputStreamoos = new ObjectOutputStream(newFileOutputStream("obj.txt"));

           oos.writeObject(newPerson("lisi0",399,"kr"));//可以调用writeObject()方法直接写入对象

           oos.close();

     }

}

import java.io.*;

 class Personimplements Serializable{被操作的类要实现Serialzable接口(标记接口)

    

publicstatic final long serialVersionUID = 42L;

    private String name;

     transientint age;//如果想把非静态变量变成不能序列化的,加上transient关键字。

     staticString country = "cn";//无法将静态变量序列化。

     Person(Stringname,int age,String country){

           this.name= name;

           this.age= age;

           this.country= country;

     }

     publicString toString(){

         returnname+":"+age+":"+country;

    }

}

 

----------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流!----------------------

 详细请查看:http://edu.csdn.net

原创粉丝点击