java基础--07(io)

版权声明:Mr.Wang 汪先生 https://blog.csdn.net/weixin_37650458/article/details/85936453

  1.java的IO体系

    文件读写的基本类(io)

    输入流:文件到程序

    输出流:程序到文件

    技巧;数据向内存流动就是输入流,反之就是输出流

    java的流分两种:字节流和字符流

    字节流:以字节为单位去读取的 可以用于读写二进制文件以及任何类型的文件

   接口:InputStream         OutputStream

   类:   FileInputStream    FileOutputStream

   方法    read                     write

   能用记事本打开的都是文本文件,否则是二进制文件

   字符流:可以用于读写文本文件,但是不能操作二进制文件

   接口:Reader        Writer

   类:    FileReader  FileWriter

  方法: read             write

  

java 字节流与字符流的区别?:
       实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作         文件就是说程序没有关闭,流没有关闭的时候字符流操作的数据还留在缓冲区如果想在不关闭时也可以将字符流的内容全部输出,则         可以使用Writer类中的flush()方法完成。

使用字节流好还是字符流好?

      在回答之前,先为读者讲解这样的一个概念,所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所以在开发中,字节流使用较为广泛。

基于磁盘的io接口:file

基于网络的io接口:socket

InputStreamReader类是从字符到字节的转化桥梁

1.File类:将文件系统中的文件和文件夹封装成了对象。提供了更多的属性和行为可以对这些文件和文件夹进行操作。这些是流对象办不到的,因为流只操作数据。File可以用来检查和创建目录,判断目录是否存在等等

File类:可以找到磁盘上的一个文件

File类与FileInputStream类的区别:

FileInputStream类关注的是文件内容,而File类关注的是文件在磁盘上的存储。

File不属于文件流,只能代表一个文件或是目录的路径名而已。

2.代码:

public static void main(String[] args) throws IOException { //读、写都会发生IO异常
    /*
    1:创建一个字符输出流对象,用于操作文件。该对象一建立,就必须明确数据存储位置,是一个文件。
    2:对象产生后,会在堆内存中有一个实体,同时也调用了系统底层资源,在指定的位置创建了一个存储数据的文件。
    3:如果指定位置,出现了同名文件,文件会被覆盖。
    */
    FileWriter fw = new FileWriter("demo.txt"); // FileNotFoundException
    /*
    调用Writer类中的write方法写入字符串。字符串并未直接写入到目的地中,而是写入到了流中,(其实是写入到内存缓冲区中)。怎么把数据弄到文件中?
    */
    fw.write("abcde");
    fw.flush(); // 刷新缓冲区,将缓冲区中的数据刷到目的地文件中。
    fw.close(); // 关闭流,其实关闭的就是java调用的系统底层资源。在关闭前,会先刷新该流。
  }
public static void main(String[] args) throws IOException {
      /*
      创建可以读取文本文件的流对象,FileReader让创建好的流对象和指定的文件相关联。
      */
      FileReader fr = new FileReader("demo.txt");
      int ch = 0;
      while((ch = fr.read())!= —1) { //条件是没有读到结尾
        System.out.println((char)ch); //调用读取流的read方法,读取一个字符。
      }
      fr.close();
    }
}

 

public static void main(String[] args) throws IOException {
      FileReader fr = new FileReader("demo.txt"); //创建读取流对象和指定文件关联。
      //因为要使用read(char[])方法,将读取到字符存入数组。所以要创建一个字符数组,一般数组的长度都是1024的整数倍。
      char[] buf = new char[1024];
      int len = 0;
      while(( len=fr.read(buf)) != —1) {
        System.out.println(new String(buf,0,len));
      }
      fr.close();
    }
  }

 BufferedWriterFileWriter fileWriter ):将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。是给字符输出流提高效率用的,那就意味着,缓冲区对象建立时,必须要先有流对象。明确要提高具体的流对象的效率。传入一个FileWriter  就明确关联了FileWriter 流对象,

 //记住,只要一读取键盘录入,就用这句话。

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));//输出到控制台

FileWriter fw = new FileWriter("bufdemo.txt");
    BufferedWriter bufw = new BufferedWriter(fw);//让缓冲区和指定流相关联。
    for(int x=0; x<4; x++){
      bufw.write(x+"abc");
      bufw.newLine(); //写入一个换行符,这个换行符可以依据平台的不同写入不同的换行符。
      bufw.flush();//对缓冲区进行刷新,可以让数据到目的地中。
    }
    bufw.close();//关闭缓冲区,其实就是在关闭具体的流。

 

流的操作规律

    1,明确源和目的。

      数据源:就是需要读取,可以使用两个体系:InputStream、Reader;

      数据汇:就是需要写入,可以使用两个体系:OutputStream、Writer;

    2,操作的数据是否是纯文本数据?

      如果是:数据源:Reader

        数据汇:Writer 

      如果不是:数据源:InputStream

          数据汇:OutputStream

    3,虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?

      明确操作的数据设备。

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

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

    4,需要在基本操作上附加其他功能吗?比如缓冲。

      如果需要就进行装饰。

 转换流特有功能:转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。转换流的最强功能就是基于 字节流 + 编码表 。没有转换,没有字符流。

发现转换流有一个子类就是操作文件的字符流对象:

  InputStreamReader

    |——FileReader

  OutputStreamWriter

    |——FileWrier

  想要操作文本文件,必须要进行编码转换,而编码转换动作转换流都完成了。所以操作文件的流对象只要继承自转换流就可以读取一个字符了。

  但是子类有一个局限性,就是子类中使用的编码是固定的,是本机默认的编码表,对于简体中文版的系统默认码表是GBK

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

  InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");

  以上两句代码功能一致,

  如果仅仅使用平台默认码表,就使用FileReader fr = new FileReader("a.txt"); //因为简化。

 

3.问题:

  1. 为什么会有两种流的出现?

     GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流

     2.close()flush()的区别:他们都有将数据刷新到缓冲区的功能,但是一个关闭了流。一个没有关闭流。

     3.缓冲区是提高效率用的,给谁提高呢?

       缓冲区对象建立时,必须要先有流对象。明确要提高具体的流对象的效率,给他传入的那个流对象提高效率用的。

     4. 使用流的原则:清楚输入输出设备,清楚文件的类型。

     5.为什么适配器类可以进行流类型的转换(这个转换时字节流到字符流)?原因在于,将获取到的字节通过查编码表获取到指定对应字符。

    6.操作什么文件的时候需要进行编码转换?或者什么时候使用转换流?

     操作文本文件的时候就需要进行编码转换,但是这个适配器类下面有两个子类,分别是FileReaderFileWrier。所以操作文件的流对象只要继承自转换流就可以读取一个字符了。编码转换就被流自动完成了。默认的情况下,就是使用本机的默认码表,对于简体中文版的系统默认码表是GBK。但是如果需要指定码表就必须使用转换流对象。凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。

  7.除了输入输出流以外还有什么流?

  打印流:PrintStream  序列流:SequenceInputStream  管道流:PipedInputStream 

  8.对象为什么要进行序列化?

  将一个具体的对象进行持久化,写入到硬盘上。对象都是在堆内存中的。所以不在对内存上的数据是不能被序列化的。注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。如何将非静态的数据不进行序列化?用transient 关键字修饰此变量即可。

猜你喜欢

转载自blog.csdn.net/weixin_37650458/article/details/85936453
今日推荐