02_IO操作的基本规律(InputStream,OutputStream,Reader,Writer,FileReader,FileWriter,BufferedReader,BufferedWri

简介:  模拟BufferedInputStream,编写一个类 package toto.IO;   import java.io.IOException; import java.io.InputStream;   class MyBufferedInputStream{     private InputStream in;   


模拟BufferedInputStream,编写一个类

package toto.IO;

 

import java.io.IOException;

import java.io.InputStream;

 

class MyBufferedInputStream{

    private InputStream in;

    private byte[] buf = new byte[1024*4];

    private int pos = 0,count = 0;

    MyBufferedInputStream(InputStream in){

       this.in = in;

    }

    //从缓冲区中读取一个字节

    /**

    *缓冲区的原理:

    *其实就是定义了一个临时容器

    *然后将获取到的数据都存入到临时容器中,通过临时容器的方法获取数据,当临时容器

    *中的数据取完后,再获取一批数据进容器、

   

发现自定义的缓冲区出现了秒杀效果

为什么秒杀呢?

因为MP3这样的媒体数据,对应的二进制数据,很有可能出现连续多个1的情况。而连续的过程中,出现-1,程序就认为读到了末尾,程序停止读取。

   

为了避免这种情况,将获取的一个字节数据,进行提升,变成int ,并在保留原有八位的基础上补零。补完后,就变成了正数,就避免了-1的这种情况。

     */

    public int myRead() throws IOException{

       if(count == 0){

           count = in.read(buf);//通过流对象从硬盘获取一批数据装入缓冲去

          

           pos = 0;//0开始取

           byte b = buf[pos];//将数据存入数组

           pos++;//取完之后pos++

           count--;//取走一个减少一个

           return b&oxff;   //这里与上的是255。这里进行了自动提升效果。

       }else if(count>0){

           //第二次取时count>0

           byte b = buf[pos];

           pos++;

           count--;

           return b;

       }else {

           return -1;

       }

    }

    public void myClose()throws IOException{

       in.close();

    }

}

 

public class Demo1 {

 

   

}

 

/*package toto.IO;

 

import java.io.IOException;

import java.io.Reader;

 

*//**

 * 按照装饰设计模式的思想

 * 自定义MyBufferedReader

 * 一样提供一个和BufferedReader功能相同的readLine方法。

 *//*

class MyBufferedReader{//extends Reader{

    由于它里面中提供Reader中的所有方法,故它要继承Reader类。这里继承的原因是里面的方法太多这里不写了

   

    private FileReader r;这种方式只能包装FileReader类,

    要想包装所有的Reader的子类,我们写成以下方式:

   

    private Reader r;

   

    MyBufferedReader(Reader r) {//这里是被包对象

       this.r = r;

    }

    提供一个一次读一行的方法。

     * 1、使用的还是Readerread()方法,一次读一个。

     * 2、将读到一个字符进行临时存储。数组和StringBuilder都可以。

     * 这里选用StringBuilder,因为可以省略数组延长部分代码的编写。该Builder中使用就是数组

     * 而且可变长度,并且最终变成字符串。

     * 3、因为自负有很多需要循环读取。

     * 4,读取到的字符进行判断,如果是回车符,那么就将StringBuilder中的存储数据作为字符串返回

   

    public String myReadLine() throws IOException {

       StringBuilder sb = new StringBuilder();

      

       int ch = 0;

       while((ch==r.read())!=-1) {//使用初进来的read方法,并且要判断不等于-1

           if(ch=='\r')//遇到这个转义字符时,不能将这个数据读进去,并且将这个数据向下读一个

              continue;

           if(ch=='\n')

              return sb.toString();

           sb.append((char)ch);//如果两个都满足,就将数据向里面转了。

       }

       return null;

    }

   

    public void myClose() throws IOException{

       r.close();

    }

}

public class MyBufferedReader{

 

   

    public static void main(String[] args) {

       // TODO Auto-generated method stub

 

    }

 

}

*/

 

 

 

转换流

/*

 * 转换流,涉及的对象都在字符流体系中。

 * InputStreamReader字节转到字符的桥梁。 把看不懂得转换成为看的懂的。

 * OutputStreamWriter:字符转到字节的桥梁。把看得懂的转换成为看不懂的。

 * 该类本身是一个字符流,因为它是桥梁,需要把一个指定的字节流传给构造函数。

 * 将制定的字节流转成字符流。*/

 

package toto.IO;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

 

public class Demo2 {

 

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

       //readIn();

//     System.out.println('-'+0);

//     System.out.println('1'+0);

       readLineByKey();

    }

    /*

     * 读取键盘录入,并打入的录入的数据

     * 当录入了一行数据后,打印录入的一行数据内容。而其可以不断的进行录入

     * 一次打印一行。

     *

     *1,读取键盘通过System.in完成

     *2,需要一次打印一行。那么就需要定义一个临时容器,将读取到自己额进行临时存储。

     *当读到回车符的时候就降临时容器中存储的数据一次性打印、*/

   

    public static void printLineByKey() throws Exception{

       InputStream in = System.in;

       int by = 0;

       StringBuilder sb = new StringBuilder();

 

       while((by==in.read())!=-1){//这里有警告,不知道为什么

           if(by=='\r')

              continue;

           if(by=='\n')

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

           else

              sb.append((char)by);

       }

    }

   

    public static void readIn() throws IOException {

       //获取标准的输入流,对应的默认设备就是键盘。

       //从键盘获取到的数据都是字节数据。

       InputStream in = System.in;

       //读取键盘录入的一个字节

      

       //通过循环形式,读取一个字节,打印一个字节

       int by = 0;

       while((by=in.read())!=-1){

           System.out.println(by);

       }

      

    }

    public static void readLineByKey() throws IOException {

       //字节读取流

        InputStream in =System.in;

       

       //要想使用readLine方法读取一样,就要建立BufferReader对象

       //但是该字符流的缓冲区,在对象在初始化时,

       //要将一个字符对象作为参数传递给BufferReader的构造函数

        //读取键盘是字节流,如何让字符流的缓冲区所使用呢?,这时就需要将字节流转成字节流

        //想要进行字节和字符流的转换,就需要IO包中的转换流

        //由于早期只有字节流,只有涉及到字符流之后才涉及到转换,故这个转换体系在字符流中。

        //InputStreamReader的前面是字节流,后面是字符流。故通过它转换。

       InputStreamReader isr = new InputStreamReader(in);

        //因为BufferedReader只能包装字符流。故只需将isr传递进去就行了。

        BufferedReader bufr = newBufferedReader(isr);

      

        String line = null;

       

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

        if(line.equals("over")){

            break;

        }

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

        }

        bufr.close();

    }

   

}

 

 

package toto.IO;

/*流操作的基本规律

 * 流操作要明确数据源和数据目的(数据汇)

 *

 * 在现有程序中,

 * 源:键盘

 * 目的控制台。

 * 1、需求:将一个硬盘上的文件打印在控制台上

 * 2、需求:将键盘录入的数据存储到一个文件中。

 *

 * */

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

 

public class TransStreamDemo2 {

 

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

       /*InputStream in = System.in;

       InputStreamReader isr = new InputStreamReader(in);

       BufferedReader bufr = new BufferedReader(isr);*/

       //上面三行可以转换成一行,读取键盘最方便方式,因为键盘录入的都是文本数据。所以一次读一行最方便,先将字节流包装成字符流,再将字符流写入缓冲区,提高效率。

       /*BufferedReader bufr = new

           BufferedReader(new InputStreamReader(System.in));*/

      

      

       //硬盘上的文件是字节流,要将它转换成字符流,读取硬盘上的一个文件的方式:

       BufferedReader bufr = new

       BufferedReader(new InputStreamReader(new FileInputStream("文件地址")));

      

      

       /*向控制台上输出,使用System.out

OutputStream out = System.out;

       OutputStreamWriter osw = new OutputStreamWriter(out);

       BufferedWriter bufw = new BufferedWriter(osw);*/

      

//     BufferedWriter bufw = new BufferedWriter(newOutputStreamWriter(System.out));

      

       //写需求1时,上面包装流中式文件路径,下面是System.out,当写需求2时,上面是System.in,下面是要写到的文件的路径。当上下都是文件名称时,相当于文件的复制。

       BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("要写到的文件的地址")));

       String line = null;

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

           if("over".equals(line)){

              break;

           }

           bufw.write(line.toUpperCase());

           bufw.newLine();

           bufw.flush();

       }

       bufw.close();

       bufr.close();

    }

 

}

 

IO包中对象其实都是以围绕读写为主,用于操作数据。

IO技术的难点:因为io包中的对象太多,在实际开发,不太容易明确使用哪个对象

 

IO操作的基本规律:

1、 作用的数据源和数据目的。

如果是操作数据源:输入流。(InputStream Reader,读入的是字节流用InputStream,读入的是字符流用Reader.

如果是操作数据汇:就是输入流。(OutputStreamWriter),输出成字节流用OutputStream,输出成字符用writer

 

2、 要操作的数据是不是纯文本数据。

如果是:使用字符流

如果不是:使用字节流。

3,根据源和目的的设备来确定要操作的对象。

 

 

无论数据源或者数据汇都有存在设备。

源设备:硬盘(File)。键盘(键盘对应的是System.in)。内存(内存对应的都是数组)。

目的设备:硬盘(File),控制台(控制台对应的是:System.out),内存(内存对应的是数组)。

 

 

这两个明确可以确定到底要使用上面四个体系中的那个体系。

 

需求一:对文本文件进行复制

1, 这个需求既有源又有目的

源:硬盘上的文件。InputStream Reader

目的:硬盘上的文件。OutputStream or Writer

 

是不是纯文本数据呢?是。

源:要使用字符读取流Reader

目的:要使用字符输出流Writer

 

那么体系确定后,要使用该体系中那个对象呢?

源:是一个文件。所以要使用字符读取流中可以操作文件的对象:FileReader

目的:也是一个文件,所以要使用字符写入流中的可以操作文件的对象:FileWriter

 

FileReader fr = new FileReader(“a.txt”);

FileWriter fw = new FileWriter(“b.txt”);

 

该操作过程中是否需要提高侠侣呢?是。

如果是:加入缓冲技术。

代码就变成:

BufferedReader bufr = newBufferedReader(new FileReader(“a.txt”));

BufferedWriter bufw = newBufferedWriter(new FileWriter(“b.txt”));

 

 

需求二,将一个硬盘上的文件打印在控制台上。

1, 明确源和目的

源:硬盘的文件。读取文件,体系是InputStream or Reader

目的:控制台。OutputStream or Writer

     对于控制台较为特殊,其默认的目的是System.out

2, 是不是纯文本数据

源:Reader

目的Writer

3,明确体系中的对象

源:因为是一个文件,FileReader

目的:因为是控制台对应的对象是System.out,为了便于字符操作,所以将System.out转换成字符流。

FileReader fr =new FileReader(“a.txt”);  读取字符流

OutputStreamWriterout =new OutputStreamWriter(System.out;); //输出字节流

      

FileReader fr =new FileReader(“a.txt”);  读取字符流

OutputStreamWriterosw = new OutputStreamWriter(System.out);这里也变成了字符流了

 

  char[] buf = new char[1024];

int len = 0;

while((len=fr.read(buf))!=-1){

   osw.writer(buf,o.len);   //将数据写到目的了(buf),即控制体。

}

 

为了提高效率,加入缓冲技术。

BufferedReader buf = new BufferReader(newFileReader(“a.txt”));

BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(“b.txt”));

 

String line = null;

While((lien=bufr.readLine())!=null){

       bufw.write(line);

       bufw.newLine();

       bufw.flush();

}

 

 

需求三,将录入的文件写入硬盘上的文件。

1,明确体系;

源:InputStream    System.in

目的:硬盘文件  OutputStreamWriter

2, 明确纯文本。

因为键盘录入的都是字节数据。但是该数据最终得转化成为纯文本。

所以可以使用字符流。

源:Reader

目的:Writer

3, 明确体系对象

源:因为键盘录入,对应的对象是System.in,是一个字节读取流。

为了可以使用字符读取留来操作这些数据,可以将其转换成字符读取流

 

目的:因为是一个文本文件,所以可以使用FileWriter

InputStreamReaderisr = new InputStreamReader(System.in);

 

FileWriter fw =new FileWriter(“a.txt”);

 

   为了提高效率,加入了缓冲技术

 

Bufferreader bufr = new BufferedReader(newInputStreamReader(System,in));

BufferedWriter bufw = newBufferedWriter(new FileWriter(“a.txt”));

 

需求四:读取键盘录入,将录入的信息打印在控制台上,

1体系:

源:InputStream  Reader

目的:OutputStreamWriter

2纯文本:是

源:Reader

目的:Writer

4, 对象:

源:System.in

目的:System.out

因为键盘录入都是纯文本,所以用字符流操作很方便。

那么就将源和目的都转换成字符流

InputStreamReader isr = newInputStreamReader(System.in);

 

OutputStreamWriter osw = newOutputStreamWriter(System.out);

 

需要高效

BufferedReader bufr = newBufferedReader(new InputStreamReaderl(System,in));

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

 

注意:在使用写入缓冲区时,记得要进行刷新。flush().

 

 

 

需求五:将一个文本文件中的数据存储到另一个文本文件中,要求按照UTF-8的编码形式存储

1, 体系

InputStream or Reader

目的:OutputStream or Writer

2,纯文本?yes

源:Reader

目的:Writer

3,对象:

因为操作是文本,而且没有指定编码。所以可以按照默认编码形式

。那么就可以使用FileReader

目的:

按照一般思想,会去找FileWriter。但是FileWriter使用的默认编码。

而需求中要求按照指定编码UTF-8形式存储

那么这时就要用到转换流,因为只有转换流可以在初始化是指定编码。

 

目的也是一个文件。那么就明确要使用的对象是FileOutStream

 

FileReader fr =new FileReader(“a.txt”);

OutlputStreamWriterosw = new OutputStream(new FileOutputStream(“b.txt”),”UTF-8”);

需要提高效率

BufferedReaderbufr = new BufferedReader(new FileReader(a.txt));

   

   BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(“b.txt”),”UTF-8”));

 

package toto.IO;

 

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.OutputStreamWriter;

 

public class TransStreamDemo {

 

       /**

        * @param args

        */

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

              //writeText();

              readText();

       }

       publicstatic void readAndWrite()throws IOException{

              FileReaderfr = new FileReader("test.txt");//字符流

              //FileWriterfw = new FileWriter("test1.txt");//默认的字符集。

              OutputStreamWriterosw = new OutputStreamWriter(new

                            FileOutputStream("text1.txt"),"utf-8");//字符流

             

              char[] buf = new char[1024];

              intlen = 0;

              while((len=fr.read(buf))!=-1){

                     osw.write(buf,0,len);

              }

              osw.close();

              fr.close();

       }

       publicstatic void readText() throws IOException{

              FileReaderfr = new FileReader("test.txt");//这种编码默认是gbk

              intch = fr.read();

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

             

              intch1 = fr.read();

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

              fr.close();

       }

       publicstatic void writeText() throws IOException{

              FileWriterfw = new FileWriter("test.txt");

              fw.write("你好");

              fw.close();

       }

 

}

 

读取一个UTF-8编码的文件。

BufferedReader bufr =

New BufferedReader(new FileInputStream(“text.txt”,”utf-8”) )

 

或通过:

InputStreamReaderisr = new InputStreamReader(new FileInputStream(“text.txt”,”utf-8”));

 

char[] buf = new char[1024];

目录
相关文章
|
2月前
|
存储 Linux API
Linux应用开发基础知识——文件IO操作(三)
Linux应用开发基础知识——文件IO操作(三)
54 2
Linux应用开发基础知识——文件IO操作(三)
|
6月前
|
Java 测试技术 Apache
Java IO 与 NIO:高效的输入输出操作探究
输入输出(IO)是任何编程语言中的核心概念,而在Java中,IO操作更是应用程序成功运行的基石。随着计算机系统变得越来越复杂,对IO的要求也日益增加。在本文中,我们将探讨Java IO和非阻塞IO(NIO)的重要性以及如何在Java中实现高效的输入输出操作。
|
6月前
|
存储 数据处理 索引
【100天精通python】Day27:文件与IO操作_CSV文件处理
【100天精通python】Day27:文件与IO操作_CSV文件处理
31 0
|
2月前
|
大数据 程序员 Python
Python中的异步编程:使用asyncio库实现高效IO操作
传统的同步编程模式在处理IO密集型任务时效率较低,因此异步编程成为了解决这一问题的关键。本文将介绍如何利用Python中的asyncio库实现异步编程,以及如何利用异步特性提高IO操作的效率,让你的程序更加响应迅速。
|
3月前
|
Java
【JavaEE】IO 操作
【JavaEE】IO 操作
|
3月前
|
存储 缓存 Linux
Linux系统IO—探索输入输出操作的奥秘
Linux系统IO—探索输入输出操作的奥秘
|
8月前
|
索引
文件IO之 File 类和 InputStream, OutputStream 的用法(三)
文件IO之 File 类和 InputStream, OutputStream 的用法
63 0
|
8月前
|
存储 Java
文件IO之 File 类和 InputStream, OutputStream 的用法(一)
文件IO之 File 类和 InputStream, OutputStream 的用法
54 0
|
3月前
IO流:字符输入流Reader的超详细用法及底层原理
IO流:字符输入流Reader的超详细用法及底层原理
|
4月前
|
JSON 数据挖掘 数据库
Pandas 高级教程——IO 操作
Pandas 高级教程——IO 操作
172 2