黑马程序员——IO流(字符流)



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


字符流的抽象基类

     Reader    Writer

黑马程序员——IO流(字符流)_第1张图片



一、读文件

1.

public static void main(String[] args) throwsIOException

   {

       //创建一个文件读取流对象,和指定名称的文件相关联

       //要保证文件已存在,否则会发生FileNotFoundException

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

       //调用读取流对象的read方法

       //read():一次读取一个字符,而且会自动向下读

       int ch = 0;

       while((ch = fr.read())!=-1)//当返回-1时,说明到文件末尾。

       {

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

       }

   }

2.

read(char[]cbuf);通过字符数组进行读取

public static void main(String[] args) throwsIOException

   {

       FileReaderfr = new FileReader("demo.txt");

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

       //该read(char[] cbuf)返回的是读到的字符个数

       char[] buf = new char[1024];

       int num = 0;

       while((num = fr.read(buf))!=-1)

       {

           System.out.println(newString(buf,0,num));

       }

       fr.close();

   }



二、写文件

需求:在硬盘上,创建一个文件并写入一些文字数据

找到一个专门用于操作文件的Writer子类对象FileWriter

后缀名是父类名,前缀名是该流对象的功能

public static void main(String[] args)throwsIOException

{

    //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件

    //而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖

    //其实该步就是在明确数据要存放的目的地。

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

   //调用write方法,将字符串写入到流中

    fw.write("abcd");

    //刷新流对象中的缓冲中的数据

    //将数据刷到目的地中

    //fw.flush();

    //关闭流资源,但是关闭之前会刷新一次内部的缓冲区中的数据

    //将数据刷到目的地中

    fw.close();    

    //和flush区别:flush刷新后,流可以继续使用,

    //close刷新后,会将流关闭

    //fw.write("haha");

}



三、IO异常的处理方式

public static void main(String[] args)

   {

       FileWriterfw = null;//在外边建立引用保证fw的作用范围

       try

       {                       //FileNotFoundException文件找不到异常

           fw =new FileWriter("k:\\demo.txt");//在内部初始化//抛出异常,初始化失败,fw为null

            fw.write("abcd");          

        }

       catch(IOException e)

       {

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

       }

       finally

       {   //fw.close() 也抛异常要单独 try一下

           try

           {

               //fw对象为null能调用close

               //会抛NullPointerException异常,所以用if判断一下对象是否为空。

               if(fw!=null)

                   fw.close();//关闭流动作一定要执行

           }

           catch(IOException e)

           {

               System.out.println(e);

           }          

        }      

    }




四、字符流的缓冲区:

对应类:

BufferedWriter(写入流缓冲区)

BufferedReader (读取流缓冲区)

缓冲区要结合流才可以使用

缓冲区的出现提高了流的操作效率

在流的基础上对流的功能进行了增强

所以在创建缓冲区之前,必须要先有流对

1.

该缓冲区中提供了一个跨平台的换行符:newLine();

//BufferedWriter(写入流缓冲区) 演示

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

   {

       //创建一个字符写入流对象

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

       //为了提高字符写入流效率,加入了缓冲技术

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

       BufferedWriter bufw = new BufferedWriter(fw);

       //bufw.write("abcd");

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

       {

           bufw.write("abcd..."+x);

           bufw.newLine();//换行

           bufw.flush();

       }

       //记住只要用到缓冲区就要刷新

       //bufw.flush();

       //其实关闭缓冲区,就是在关闭缓冲区中的流对象

       bufw.close();

   }

2.

BufferedReader (读取流缓冲区) 演示

该缓冲区提供了一次读一行的方法:readLine();

方便于对文本数据的获取,当返回null时,表示读到文件末尾

该方法返回的时候只返回回车符之前的数据内容,并不返回回车符


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

   {

       //创建一个读取流对象和文件相关联

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

       //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲区对象的构造函数

       BufferedReader bufr = new BufferedReader(fr);

       String line = null;

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

       {

           System.out.println(line);

       }

       bufr.close();

   }


3.

根据原理自定义BufferedReader

readLine()方法的原理

   无论是读一行或者读取多个字符其实最终都是在

   硬盘上一个一个读取,所以最终使用的还是read()方法,一次读一个的方法。

明白了BufferedReader类中特有方法readerLine的原理后,可以自定义一个类中包含一个功能和readLine一致的方法

来模拟一下BufferedReader


class MyBufferedReader extends Reader

{

   private Reader fr;

   MyBufferedReader(Reader fr)

   {

       this.fr = fr;

   }

   //可以一次读一行数据的方法

   public String myReaderLine()throws IOException

   {

       //定义一个临时容器BufferedReader封装的是字符数组

       //为了演示方便定义一个StringBuilder容器因为最终还是要将数据变成字符串

       StringBuilder sb = new StringBuilder();

       int ch = 0;

       while((ch=fr.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

   {

       fr.close();

   }

   //覆盖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();

   }

}


复制一个文件 

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("BufferedWriterCopy.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("写入关闭失败");
         }
      }
   }
}

 黑马程序员——IO流(字符流)_第2张图片

五、LineNumberReader

Reader

   |--BufferedReader

      |--LineNumberReader:跟踪行号的缓冲字符输入流

           方法setLineNumber()设置行号

                 getLineNumber()获取行号

           默认情况下,行编号从0开始      

           LineNumberReader lnr = new LineNumberReader(new FileReader("BufferedReaderDemo.java"));

           String line = null;

           lnr.setLineNumber(100);//设置开始行号

           while((line = lnr.readLine())!=null)

           {

               System.out.println(lnr.getLineNumber()+":"+line);

           }  


六、转换流 

InputStreamReader 是字节流通向字符流的桥梁

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

   {

       //获取键盘录入对象

       InputStream in = System.in;

       //将字节流对象转成字符流对象,使用转换流InputStreamReader

       InputStreamReader isr = new InputStreamReader(in);

       //为了提高效率,将字符串进行缓冲区的操作,BufferedReader

       BufferedReader br = new BufferedReader(isr);

       //键盘录入的最常见写法,三句并一句

       //BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

       //输出对象

       OutputStream out = System.out;

       //将字符流对象转成字节流对象,使用转换流OutputStreamWriter

       OutputStreamWriter osw = new OutputStreamWriter(out);

       BufferedWriter bw = new BufferedWriter(osw);

       //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

       String line = null;

       while((line=br.readLine())!=null)

       {

           if("over".equals(line))

               break;

           //有了输出流对象,就可以不用输出语句了

           bw.write(line.toUpperCase());

           bw.newLine();//BufferedWriter的换行方法

           bw.flush();//写出到了缓冲区,需要刷新

           //System.out.println(line.toUpperCase());

           //String toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

       }

       br.close();

       bw.close();

   }





 


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








































你可能感兴趣的:(java)