1、先认识一个类————File类

前言:IO相关的一些常识

  • I / O————输入输出
    • I     输入     input
    • 0    输出     output
  • I / o 按数据的流动方向来分————流动方向:指的是计算机的数据流动————其实这个是有参考系的,如:如果说想要把一个数据弄到主存中来,那我所处的角度(位置)就是主存,数据就只是我的目标,因此:这时读数据就是input(从另外的地方把数据读进来嘛),而从本身中(主存中)把数据弄到另一个地方去,那就是output——写数据(把数据向指定地方写进去嘛)————这样就可以理解了涩

    • 读数据————输入 input
    • 写数据————输出 output
    • 这两个东西别搞懵了,很多人在这个地方直接懵了,什么input叫读数据,什么output叫写数据的,这不是反着的吗,所以有些人学完流技术之后,搞来搞去,最后懵逼了(注意:前面我写的   “ 如: ” 中的这个例子)
  • I / o按操作目标来分

    • 文件流
    • 字符流
    • 对象流
    • 网络流
    • ................
  • 什么是文件?
    • 指的就是电脑中的一种存储形式嘛
      • 如:.txt,.doc,.docx,.ppt.........这些都是文件嘛
  • 什么是文件夹?

    • 指的就是目录的路径涩

      • 如:D:\IntallationList\MaveIntallationList,这不就指的是前面这一串儿文件夹下的MavenIntallationList这个文件夹吗,所以它就是一个目录的路径涩
  • File类是什么?
    • 首先它是一个类,在java.io包下
    • 其次它和电脑上的文件产生一 一对应的“映射关系”
    • 最后:这个类只是对文件本身进行操作,文件里面的数据搞不了( 但是套一层金刚伏魔圈儿就可以搞了 )——后续学了流就懂了
    • 它是个类,则就有对象,这个对象就是指的文件 / 文件夹,但是:这个文件 / 文件夹并不是电脑中真实硬盘的文件 / 文件夹

      • 而是指的是:“堆内存”中的一个对象,这个对象<————>映射<————>电脑中真实的文件 / 文件夹
  • File类如何创建对象?
    • 通过new关键字进行创建————有方法重载,但是最常用的是下面这个
      • File f = new File( String filePathName )————参数中必须跟一个电脑中真实存在的 文件 / 文件夹路径(是全路径 )————虽然不是真实的也没错,但是就当必须是真实的路径就行(养成习惯),如:

          1. // 1、创建File对象
          2. File file = new File( "D:\\InatallationPackage\\Mybatis\\Resources" ); // 当然这里的 \\,也可以写成 /

 

  • File类中的一些常用方法(完整的方法集可以直接看API)

    • length()————获取文件的字节大小

        1. File file = new File("D:\\InatallationPackage\\Mybatis\\Resources");
        2.  
        3. System.out.println( file.length() );
    • boolean = CanRead()———查看文件是否可读

        1. // 2、查看文件是否可读
        2. System.out.println( file.canRead() );
    • boolean = CanWrite()————查看文件是否可写

        1. // 3、查看文件是否可写
        2. System.out.println( file.canWrite() );
    • boolean = CreatNewFile()————创建一个新文件————相比其他这个方法更常用

        1. // 4、创建一个新文件
        2. try {
        3.  
        4. System.out.println( new File("D:/IntallationList/creatNewFile.txt").createNewFile() );
        5. System.out.println( new File("d:/creatNewFile.txt").createNewFile() ); // 这两种创建都行
        6. /*
        7. 注:
        8. 1、这个方法需要处理异常————抛出或捕获都行
        9. 2、创建的文件前面的路径必须是真实有效的,否则:无法创建
        10. */
        11.  
        12. } catch (IOException e) {
        13. e.printStackTrace();
        14. }
    • boolean = delete()————删除一个文件 / 文件夹————如果删除的文件夹中还有文件 / 文件夹,则:无法删除   

        1. // 5、删除一个文件
        2. System.out.println( new File("D:\\test\\hit-me.txt").delete() );
    • boolean = exists()————查看一个文件是否存在——这个在开发中还有点用

        1. // 6、查看一个文件是否存在
        2. System.out.println( new File("d:/test/aaa.txt").exists() );
    • String = getAbsolutePath()————获取文件的绝对路径——还有点用

        1. // 7、获取文件夹的绝对路径————即:文件夹的全路径
        2. System.out.println( new File("D:\\IntallationList\\MaveIntallationList").getAbsolutePath() );
    • String = getName()————获取文件的名字————也有点用

        1. // 8、获取文件的名字————本例子中结果为:MaveIntallationList
        1. System.out.println( new File("D:\\IntallationList\\MaveIntallationList").getName() );
    • String = getParent()————获取当前文件的上一层的整个文件路径————结果是个字符串,也没多大用

        1. // 9、获取文件的上层全路径————本例中结果为:D:\IntallationList,这个值是一个字符串
        2. System.out.println( new File("D:\\IntallationList\\MaveIntallationList").getParent() );
    • File = getParentFile()————获取当前文件的上一届的整个文件路径对象————这个就有点用了,因为:返回的是一个File对象

        1. // 10、返回当前文件的上一层的整个文件路径的对象————本例中结果为:D:\IntallationList,但是这个值是一个File对象
        2. System.out.println( new File("D:\\IntallationList\\MaveIntallationList").getParentFile() );
    • String[ ] = list()————返回指定文件夹中的所有文件 / 文件夹名 的 String类型数组————还是没多大用

        1. // 11、返回一个文件夹中的所有文件 / 文件夹 名的 String数组
        2. String[] fileList = new File("D:\\IntallationList").list();
        3.  
        4. for (String list : fileList) {
        5.  
        6. System.out.println( list );
        7. }
    • File[] = listFiles()————返回指定文件夹中的所有文件 / 文件夹 的全路径的 File对象数组————这个才是有用的

        1. // 12、返回指定文件夹中的所有文件 / 文件夹 的 全路径的 File对象数组
        2. File[] files = new File("D:\\IntallationList").listFiles();
        3. for (File f : files) {
        4.  
        5. System.out.println( f );
        6. }
    • mkdir()————创建文件夹,是文件夹,不是前面说的文件————但是:这个方法创建,必须保证要创的文件夹外面那一层文件夹是真实存在的,否则:创建不了————但是这个方法也没什么卵用

        1. // 13、创建文件夹
        2. System.out.println( new File("d:/test/demo").mkdir() ); // 这种好使,因为demo的上一级test是存在的
        3. ew File("d:/test/aaa/bbb").mkdir(); // 这种就不得吃,因为bbb的上一层aaa并没有
    • mkdirs()————这个才是有用的一个,上一层没有文件夹也可以帮忙创建上一层
  • 对文件里面的数据进行操作————真正的IO流技术

    • IO体系是咋个样的?————就下面这个样,知识好多哦!!!!

流体系学懂一个,其他的都懂了,流程都是如上图 底部中说的那样,全部流技术都是一模球儿一样的流程

  • 1、文件流

    • 指的是:

      • 从其他地方读取文件的信息( input )
      • 将信息写入其他地方的文件中( output )
    • 文件流分为:

      • 1、字节型文件流————即:读取 / 写出是以字节形式读写文件

        • FileInputStream      字节型文件输入流
        • FileOutputStream   字节型文件输出流
      • 2、字符型文件流————即:读取 / 写出是以字符形式读写文件

        • 1、FileReader————字符型文件输入流
        • 2、FileWriter————字符型文件输出流

文件流的操作原理————堆内存是JVM里面的那个,在前面的知识中画过多次JVM分析图了

从这图中就可以看出:引入流技术的原因、

  • 变量、数组、集合都是java中的类型————这是用对象进行操作内存,都存储在内存中,程序执行完毕之后,虚拟机就停止了,相应的内存中的东西就被回收了,所以这些数据都是临时存储的。而文件也可以存储很多数据,同时是存储在磁盘上的,是永久性保存
  • 因此:引入流技术的原因就是
    • 在文件中,虽然数据安全了,但不是在内存中,是在磁盘上的,故:无法直接进行操作,因此:引入流技术通过IO操作文件

文件流(重点)

1、字节型文件流

  • 1、字节型文件输入流————FileInputStream———套个儿子

    • 把一个指定地方的文件的数据读取出来
    • java.io包下
    • FileInputStream继承了InputStream类————InputStream类是字节型输入流的老爹(这是一个抽象类)
    • FileInputStream怎么创建对象?

      • 通过new关键字创建,但是需要传参,参数有三种方式————最常用的是下图中的前两种

          1. try {
          2.  
          3. // 1、直接利用String类型的有参构造————注意:处理异常,可以抛出,也可以捕获
          4. FileInputStream fis = new FileInputStream( "D:\\IntallationList" );
          5.  
          6. // 2、通过套个儿子的方式创建
          7. FileInputStream fis2 = new FileInputStream( new File("D:\\IntallationList") );
          8.  
          9. } catch (FileNotFoundException e) {
          10. e.printStackTrace();
          11. }
    • FileInputStream类中的常用方法————这里面的方法就是真的常用了

      • int = read()————指的是:每次从流管道中读取一个字节————有重载

        • 对这个方法返回值类型是 int 类型的解释————这是一个反人类的设计——以前的返回值都是指:我们传递进去的数据类型参数(如:这里的int)参与计算得出的值,即:输入型参数————而这里的int不再是我们传进去的数据类型参数参与计算得到的,而是一种输出型参数

          • 1、如果是无参的这个read(),则:得到的int值表示的是——要读取的数据的下一个字节的字节码,若:读取的数据已经到了最后,则:返回-1
          • 2、read( byte[ ] b , int off , int len )———题外话:off是偏移量,指的是:跳过off之前的字节,从off位置开始读取,len是指:需要读取的字节长度,即:从off开始,往后读取多少个字节
            • 如果是使用的这个三个参数的方法,则:得到的int值表示的是——读取的数据的字节数,即:读取了多少个字节的数据,若是文件最后,也是返回-1
          • 3、如果是使用的read( byte[ ] b )————这个方法其实调用了2中的三参方法。它得到的int值取决于两个方面
            • 如果我们读取的数据长度 比 我们用来装读取出来的数据 的 容器要大,则:得到的这个int值就是这个容器的大小
            • 如果我们读取的数据长度 比 我们用来装读取出来的数据 的 容器要小,则:得到的这个int值就是我们读取的数据的字节长度————对于这里所说的容器不懂的话,那就等到这个流技术最后写整个流程知识那里,就懂这里说的容器是什么了
            • 同样的,如果是在文件的最后,返回的也是-1
      • int count = available()————查看流管道中还有多少字节
      • long  = skip( Long n )————就是跳过n个字节,然后再从n之后读取文件————和read( byte[ ] b , int off , int len )达到的效果一样,看情况——哪个适合用哪个

        • 这个方法可以用在多线程中

          • 利用几个线程同时读取一个文件

            • 如:文件中有10000个字节,就可以通过5个线程去进行读取——这样效率不就很快了吗

              • 1线程读取1——2000
              • 2线程读取2001——4000
              • 3线程读取4001——6000
              • 4线程读取6001——8000
              • 5线程读取8001——10000
      • void = close()————将流管道关闭————这一步在文件操作中是必须要的

        • 故:这个方法就可以放在finally结构中
        • 注:在把close()放在finally结构中时,应注意:代码的健壮性,所以判断要严谨
          • 如:判断文件是否操作完毕了,完成了才关闭流管道,否则:就如:打开了一个文件(没关闭),但是执行删除操作一样———删不了,同理:流管道能够关闭吗?——流管道不关闭很耗内存的
  • FileInputStream流技术的操作流程的三步骤(死流程)————三板斧^ _ ^

    • 创建流
    • 读数据
    • 关闭流管道
  • 实例

      1. import java.io.FileInputStream;
      2. import java.io.IOException;
      3.  
      4. public class Test {
      5.  
      6. public static void main(String[] args) {
      7.  
      8. // 1、创建流
      9. FileInputStream fis = null;
      10. try {
      11. fis = new FileInputStream("D:\\InatallationPackage\\Maven\\pom.xml");
      12.  
      13. // 2、读数据
      14. // 准备一个容器————用来装读取出来的数据
      15. byte[] data = new byte[1024]; // 大小可以任意取,建议用这个大小
      16. int len; // 这len是为了给read()读取的int结果 同时为了判断————注:别把这个len放在while那个判断力,会出问题
      17. while ( ( len = fis.read( data ) ) != -1 ){ // read()读取文件
        // 同时把读取出来的结果放到新建的data数组容器里。另外:这里的判断可以不写成 != -1,还可以写成 > 0
      18.  
      19. System.out.println( new String( data , 0,len ) ); // 这里可以看需求弄成其他方式,我只是为了看效果,所以打印了而已
      20. }
      21.  
      22. } catch (IOException e) {
      23.  
      24. e.printStackTrace();
      25.  
      26. }finally {
      27.  
      28. // 关闭流管道
      29.  
      30. // 保证代码健壮性
      31. if ( fis != null ){ // 判断一手儿,为什么是 != nul才关闭流管道?看起来应该是fis中为null了,才说明没有内容需要读写了涩
        // 别忘了 真正去进行映射操作文件的是哪个吊毛————File对象,所以这里的fis只是一个对象,它指向的是File
        // 所以要是fis为null了,那不就说明fis没有引用了吗,这不就没有一个指向者了————最后也就会导致空指针异常
        // 后续另外的流也是这么一个原因
      32.  
      33. try {
      34.  
      35. fis.close(); // 再关闭流管道
      36.  
      37. } catch (IOException e) {
      38.  
      39. e.printStackTrace();
      40. }
      41. }
      42. }
      43.  
      44. }
      45. }
  • 2、字节型文件输出流——FileOutputStream

    • 将一些数据写入到一个指定的文件中
    • 在java.io包下
    • FileOutputStream继承了OutputStream
    • FileOutputStream怎么创建对象?

      • 和FileInputStream一样


      • 只是有一个地方需要注意:就是这个输出流是可以操控 是否可以追加内容的,即:上图中的第2和第4种创建方式,参数中有一个boolean类型的参数,这个参数就是表示:是否需要追加,默认是false

        • 追加是什么意思? 

          • 就是下一次添加内容到同一个文件的时候,可以追加的话,就表示:从文件的后面接着添加内容。不可以追加的话,就表示:系统把原文件删了,然后重新创建一个和原文件名字一模一样的文件,最后再添加本次的内容
  • FileOutputStream中的常用方法

    • 和FileInputStream一样,所以:不再玩儿了
    • 但有一个额外的方法需要说明:
      • flush()————刷新( 指的其实就是:将流管道中的数据推入【刷新】文件中去 ),这一步必须有,不然数据无法添加进文件中

        • 另外:close()在这里既有关闭流管道,又有刷新的功能
  • FileOutputStream的使用流程是怎么样的?——还是三板斧

    • 创建流
    • 写数据
    • 关闭流管道

实例:

    1. import java.io.FileOutputStream;
    2. import java.io.IOException;
    3.  
    4. // 字节型文件输出流
    5. public class TestFileOutputStream {
    6.  
    7. public static void main(String[] args) {
    8.  
    9. // 1、创建流
    10. FileOutputStream fos = null;
    11. try {
    12.  
    13. fos = new FileOutputStream("d:/test/demo.txt",true); // true为:可以追加内容
    14.  
    15. // 2、写数据————想要向上面的文件中写入什么内容————利用write()方法————但是这个方法的参数是int 或 byte[]
    16. fos.write( "这是想要写入的String类型的内容".getBytes() ); // 利用String中的getBytes()方法就把String转为 byte[]字节数组了
    17.  
    18. // 也可以在这里加上flush()————即:把2中的数据从流管道中推入文件中
    19. fos.flush(); // 但是:不用加也可以,因为:close()在这里面有关闭流管道、刷新文件中数据的功能
    20. } catch (IOException e) {
    21.  
    22. e.printStackTrace();
    23. }finally {
    24.  
    25. // 3、关闭流管道
    26. if ( fos != null ){ // 为了代码的健壮性,严谨判断一手儿
    27. try {
    28.  
    29. fos.close(); // 关闭流管道
    30. } catch (IOException e) {
    31.  
    32. e.printStackTrace();
    33. }
    34. }
    35. }
    36. }
    37. }
  • 利用FileInputStream 和 FileOutputStream实操一手儿
  1. import java.io.FileInputStream;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.util.Date;
  5. import java.util.Scanner;
  6.  
  7. /**
  8. * 有这么一个需求:
  9. * 1、从控制台输入
  10. * 日记标题
  11. * 输入正文
  12. * 然后保存到一个文件中————要求每一篇的日记名字都不一样
  13. *
  14. * 2、从日记文件中读取指定名字的日记,从而在控制台显示出对应的日记内容
  15. */
  16. public class Note {
  17.  
  18. public static void main(String[] args) {
  19.  
  20. writeNote();
  21. readNote();
  22. }
  23.  
  24. // 录入日记
  25. public static void writeNote() {
  26.  
  27. System.out.println("请输入日记的标题:");
  28. Scanner input = new Scanner(System.in);
  29. String title = input.next();
  30.  
  31. System.out.println("请输入日记的正文:");
  32. String text = input.next();
  33.  
  34. // 把控制台输入的东西 放到指定文件中去
  35.  
  36. // 1、创建输出流
  37. FileOutputStream fos = null;
  38. try {
  39.  
  40. fos = new FileOutputStream("d:/test/note/" + new Date().getTime() + ".txt");

  41.         // 2、写数据
  42. // 把标题写入文件中去
  43. fos.write( "标题:".getBytes() );
  44. fos.write(title.getBytes() );
  45. fos.write( "\n".getBytes() ); // 换行
  46.  
  47. // 把输入的正文写入到文件中去
  48. fos.write( "正文:".getBytes() );
  49. fos.write( text.getBytes() );
  50.  
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }finally {

  54.        // 3、关闭流管道
  55. if ( fos != null ){
  56. try {
  57. fos.close();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. }
  61. }

           System.out.println( "录入成功" );

  62. }
  63. }
  64.  
  65. // 读取指定名字的日记
  66. public static void readNote() {
  67.  
  68. System.out.println("请输入你想要查看的日记名:");
  69. Scanner input = new Scanner(System.in);
  70. String noteName = input.next();
  71. String realName = noteName + ".txt";
  72.  
  73. // 创建输入流
  74. FileInputStream fis = null;
  75. try {
  76. fis = new FileInputStream("d:/test/note/" + realName);
  77.  
  78. // 读数据
  79. byte[] text = new byte[1024];
  80. int len;
  81. while ( ( len = fis.read(text) ) != -1 ){
  82.  
  83. System.out.println( new String( text,0,len ) );
  84. }
  85. } catch (IOException e) {
  86. e.printStackTrace();
  87. }finally {
  88.  
  89. // 关闭流管道
  90. if ( fis != null ){
  91. try {
  92. fis.close();
  93. } catch (IOException e) {
  94. e.printStackTrace();
  95. }
  96. }
  97. }
  98. }
  99. }

效果图如下:

2、字符型文件流

  • 1、字符型文件流——以字符的形式读取文件,通常是纯文本文件(如:txt文件)——excel、doc这种不是纯文本,它是一种软件

    • 为什么要有字符型文件流?

      • 假设有这么一个文件————里面有中文和英文

      • 如果想要去读取这个文件,而用来装读取内容的容器大小刚好是16呢?————即:大小位置为“你”这个字哪里,“你"之前的 , 逗号那里为15,空格也是一个字符
        • 这种情况继续用字节型文件流来读取会怎么样?———— 一个中文占2个字节

          • 那这样,想要把“你”字完全读出来,理论上应该是容器大小为17,这样才可以装得下“你”这个字涩
          • 但是:容器大小是16————所以会导致:中文读取失败( 即:无法完整读取 )
          • 同时:以字符的形式读取 比 字节的形式更快一点
          • 因此:有了字符型文件流
  • 字符型文件流的分类

    • FileReader     字符输入流————核心方法就:read()
    • FileWriter       字符输出流————核心方法就:write()
  • 怎么创建对象?

    •  
  • 实例使用——三板斧———流的使用都是这样,后续不再说明了

      1. package cn.xieGongZi.testFileReaderAndFileWriter;
      2.  
      3. import java.io.FileReader;
      4. import java.io.FileWriter;
      5. import java.io.IOException;
      6.  
      7. public class Demo {
      8.  
      9. public static void main(String[] args) throws IOException {
      10.  
      11. readData();
      12. writeData();
      13. }
      14.  
      15. // 读数据
      16. public static void readData() throws IOException {
      17.  
      18. // 创建流管道
      19. FileReader fr = new FileReader("D:\\InatallationPackage\\Maven\\pom.xml");
      20.  
      21. // 读数据
      22. char[] data = new char[1024];
      23. int len;
      24. while ( (len = fr.read(data)) != -1 ){
      25.  
      26. System.out.println( new String( data,0,len) );
      27. }
      28.  
      29. if ( fr != null ){
      30.  
      31. fr.close();
      32. }
      33. }
      34.  
      35. // 写数据
      36. public static void writeData() throws IOException {
      37.  
      38. // 创建流管道
      39. FileWriter fw = new FileWriter("d:/test/play.txt", true);
      40.  
      41. // 写数据
      42. fw.write("天王盖地fu,宝塔镇huo妖");
      43.  
      44. // 关闭流管道
      45. if ( fw != null ){
      46. fw.close();
      47. System.out.println("数据写入完毕");
      48. }
      49. }
      50. }

学了字节型和字符型文件流操作,其实其他的流操作都已经会了,因为一样的,分类也一样,只是有细微的区别而已

缓冲流————也可以叫包装流——照样不断套娃嘛

  • 就是在流管道中增加缓存数据,从而让我们的数据读写更快,更加流畅,就好比:在文件流的基础上把一部分的流管道容量加大了

1、字节型缓冲流

  • 字节型输入缓冲流————BufferedInputStream

  • 字节型输出缓冲流————BufferOutputStream

这两个没啥好说的,对照字节型文件流就可以了

 2、字符型缓冲流

  •  字符输入流——BufferedReader————对照FileReader

    • 但是:这个有一个需要注意的地方————BufferedReader的一个方法

      • nextLine()————读取纯文本中一行的内容——很重要啊,用这个流读数据就用这个方法,不再用read()

  •  字符输出流——BufferedWriter———对照FileWriter

    • 这个流也有一个特殊的地方————BufferedWriter的一个方法

      • newLine()————这个方法就相当于是换行

 实操一手儿

    1. package cn.xieGongZi.buffer;
    2.  
    3. import java.io.*;
    4.  
    5. public class Demo {
    6.  
    7. public static void main(String[] args) throws IOException {
    8.  
    9. readData();
    10. writeData();
    11.  
    12. }
    13.  
    14. // 读数据
    15. public static void readData() throws IOException {
    16.  
    17. BufferedReader br = new BufferedReader(new FileReader("D:\\IntallationPackage\\Maven\\pom.xml"));
    18.  
    19. String data = null;
    20.  
    21. while ( ( data = br.readLine()) != null ){ // readline()一行一行的读取内容
    22.  
    23. System.out.println(data);
    24. }
    25.  
    26. }
    27.  
    28. // 写数据
    29. public static void writeData() throws IOException {
    30.  
    31. // 创建输出流
    32. BufferedWriter bw = new BufferedWriter(new FileWriter("d:/test/play.txt",true));
    33.  
    34. // 写要录入文件的数据
    35. bw.newLine(); // 换行————在新的一行中开始添加内容
    36. bw.write("老衲来自西方极乐世界,到南方来享受金乌施主的温柔阳光");
    37.  
    38. // 关闭流管道
    39. if ( bw != null ){
    40.  
    41. bw.close();
    42. System.out.println("数据写入成功");
    43. }
    44.  
    45. }
    46. }

转换流(重点)

转换流的作用:

  • 有时读写文件的时候,用字节的方式来读写太慢了,利用字符的形式读写要快得多涩,所以这个时候就需要把字节型流 转换为 字符型流,这样读写的效率就快得多了

    • 根据上面的理论,好像也可以套儿子嘛,因为是字节型转为字符型,所以直接在字符型中再套一个字节型就可以了涩( 因为字符流 就是 基于字节流实现的嘛 )。如下所示(字节文件输入 转 字符文件输入):
  1. FileReader fr = new FileReader( new FileInputStream("d:/test/play.txt") ); // 这样看起来貌似就是想要的效果嘛

麻嘞个巴子咧~~别乱玩儿啊,看一下创建FileReader对象的时候,传递的参数是啥类型?————是字符串 / File类啊————所以上面的那种创建就是乱弹琴

1、字节输入流 转 字符输入流( InputStreamReader ——— 看名字记嘛,inputStream是字节输入流涩,Reader是字符流里面的啊,所以就是字节输入流 转 字符输入流咯)

  • InputStreamReader流的使用

      1. // 创建流
      2. InputStreamReader isr = new InputStreamReader(new FileInputStream("d:/test/play.txt"));
      3.  
      4. // 读数据
        isr.read(????); // 但是这里传递的参数是一个char[] / charBuffer,而read()读出来之后的返回值又是int类型的,咋个办?
           // 强转?char————>int确定没问题?转不转得了是一回事,重要的是:不会造成数据丢失吗?
      5.  
      6. // 那就给这个字符流再找个爹儿,变一下嘛.........
    • 套个爹儿的玩法
        1. // 创建流
        2. BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("d:/test/play.txt") ) );
        3.  
        4. // 读数据————读出来了得有个容器接一下嘛
        5. String buffer;
        6. while ( ( buffer = br.readLine() ) != null ){
        7. System.out.println( buffer );
        8. }
        9.  
        10. // 关闭流管道
        11. if ( br != null ){
        12. br.close();
        13. }

2、字节型输出流 转 字符型输出流———和1一样,所以直接上实例

    1. // 字节型输出流——————>字符型输出流
    2.  
    3. // 创建流
    4. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/test/play.txt",true)));
    5.  
    6. // 写数据
    7. bw.newLine(); // 换行再录入数据
    8. bw.write("贫道突然不知道录入个啥子数据进去好了");
    9.  
    10. // 关闭流管道
    11. if ( bw != null ){
    12. bw.close();
    13. System.out.println("数据录入成功");
    14. }

对象流(重点)——ObjectStream

为什么要搞对象流这个东西?

  • 在面向对象编程篇的特征修饰符中见过一个修饰符了涩————transient,即:瞬时的(通俗讲就是:不把对象序列化)

    • 这个猫玩意儿就需要用到这里来了
  • 另外就是:分布式开发的时候,这个鸟儿东西就很有用了,因为:可以跨服务器调用彼此之间的东西,如:在A服务器上,调用B服务器的属性和方法,就可以利用这个骚东西知识(配合transient修饰符)来整了

1、序列化对象流————ObjectOutputStream

  • 指的是:把一个完整的对象(这个对象保存的就是自己要录入的数据)  拆分成    字节碎片(这种东西人看都看球不懂,但计算机懂就行),然后存入到指定的文件中去
  • ObjectOutputStream流如何创建对象?

    • ObjectOutputStream = new ObjectOutputStream( OutputStream os )
  • 序列化的实现方式

    • 让对象实现Serializable接口(序列化接口),这就是一个标志接口,里面啥子都没有(在面向对象的接口知识中已说明)————另外:让对象实现这个接口之后,对对象本身没有任何影响,就是给这个对象做了一个标志而已
  • 实例走起

    • 创建一个对象————先创建一个类(用其他对象也可以)

        1. package cn.xieGongZi.objectStream.test;
        2.  
        3. import java.io.Serializable;
        4.  
        5. public class Person implements Serializable { // 让这个类实现Serializable接口,表明这个类是可序列化的
        6.  
        7. private String name;
        8. private char sex;
        9. private Integer age;
        10.  
        11. @Override
        12. public String toString() {
        13. return "Person{" +
        14. "name='" + name + '\'' +
        15. ", sex=" + sex +
        16. ", age=" + age +
        17. '}';
        18. }
        19.  
        20. public Person() {
        21. }
        22.  
        23. public Person(String name, char sex, Integer age) {
        24. this.name = name;
        25. this.sex = sex;
        26. this.age = age;
        27. }
        28.  
        29. public String getName() {
        30. return name;
        31. }
        32.  
        33. public void setName(String name) {
        34. this.name = name;
        35. }
        36.  
        37. public char getSex() {
        38. return sex;
        39. }
        40.  
        41. public void setSex(char sex) {
        42. this.sex = sex;
        43. }
        44.  
        45. public Integer getAge() {
        46. return age;
        47. }
        48.  
        49. public void setAge(Integer age) {
        50. this.age = age;
        51. }
        52. }
    • 进行序列化
        1. // 序列化流
        2.  
        3. // 创建流
        4. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/test/ObjectOutputStream.txt"));
        5.  
        6. // 写数据
        7. oos.writeObject(new Person("邪公子", '女', 18)); // 注意:这里是使用WriteObject()
        8. oos.writeObject(new Person("紫邪情", '女', 30));
        9. oos.writeObject(new Person("小紫", '女', 150));
        10. oos.writeObject(new Person("韩非", '男', 100));
        11.  
        12. // 关闭流管道
        13. if (oos != null ){
        14. oos.close();
        15. System.out.println("对象序列化完毕");
        16. }
      • 效果如下:看不懂就对了,这就是字节碎片,是计算机底层的东西,这个内容是计算机强行显示出来的内容,在底层也就是二进制存储的

把对象序列化到文件中去,这都是计算机语言,看都看球不懂,咋个整?反序列化回来嘛

2、反序列化对象流

  • 指的是:把字节碎片 还原回 一个完整的对象
  • 直接上实例

      1. // 反序列化
      2.  
      3. // 创建流
      4. ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/test/ObjectOutputStream.txt"));
      5.  
      6. // 读数据
      7. try {
      8.  
      9. Object person1 = ois.readObject(); // 在这里:反序列化的顺序就是前面序列化的顺序,不能把顺序搞乱了,不然反序列化出来的数据不一样 / 出错
      10. System.out.println( person1 ); // 看效果
      11.  
      12. Object person2 = ois.readObject();
      13. System.out.println( person2 );
      14.  
      15. Object person3 = ois.readObject();
      16. System.out.println( person3 );
      17.  
      18. Object person4 = ois.readObject();
      19. System.out.println( person4 );
      20.  
      21. } catch (ClassNotFoundException e) {
      22. e.printStackTrace();
      23. }finally {
      24.  
      25. // 关闭流管道
      26. if (ois != null ){
      27. ois.close();
      28. }
      29. }
    • 效果如下:

至此:需要用的流技术知识已经完毕

后续为装墨水儿知识,知不知道都无所谓

编码与字符集————这里也就来解决乱码的问题

编码

  • 指的是:把字符与数字对应的过程

字符集

  • 指的是:一张记录了对应关系的信息表

    • 这种有很多,如:

      • GBK ———— 我国的国标码
      • ISO-8859-1 ———— 西欧语言
      • Big5 ———— 香港台湾语言(繁体字)
      • Unicode ———— 联合编码(多个国家的语言字符都包含在这张表里面)————里面还分为:UTF-8(三串数字存一个中文字符)、UTF-16.......
  • 理论整起来贼没意思,来上实例

    • 假如:我存了这么一个数据,然后采用了ANSI编码(不懂门道的,可以简单理解为GBK)


    • 然后去读取这个文件

        1. FileInputStream fis = new FileInputStream("d:/test/play.txt");
        2.  
        3. byte[] data = new byte[1024];
        4. int len;
        5. while ( ( len = fis.read(data) ) > 0 ){
        6. System.out.println( new String(data, 0, len) );
        7. }
        8.  
        9. if ( fis != null ){
        10. fis.close();
        11. }
      • 读取出来的效果是这样的————即:发生乱码了————怎么解决?

        •     
      • 只需要把编码格式改一下————因为:保存的时候是使用的ANSI编码,那解码用GBK就可以了( 即:charSet )
        •  
  • 再来了解一下:前面说的UTF-8是三串数字存一个中文字符是不是真的

    • 测试一下

        1. // UTF-8是不是采用三串数字保存的一个中文字符?
        2. String data = "中国太好玩儿了";
        3.  
        4. // 把这个内容采用UTF-8的解码格式读出来看一下
        5. byte[] newData = data.getBytes(); // 这个采用的是系统的默认字符集,而我的字符集就是UTF-8
        6.  
        7. // 打印出来看一下
        8. System.out.println( Arrays.toString(newData) );
        • 我的idea编码解码格式如下:


      • 最后看一下效果

          1. -28, -72, -83 ————
            -27, -101, -67 ————
            -27, -92, -86 ——————
            -27, -91, -67 ——————
            -25, -114, -87 ——————
            -27, -124, -65 ——————
            -28, -70, -122 ——————
        • 再验证一下嘛:拿这串数字反编译一下,看是不是这几个字

            1. // 整体反编译测试
              byte[] data = {-28, -72, -83, -27, -101, -67, -27, -92, -86, -27, -91, -67, -25, -114, -87, -27, -124, -65, -28, -70, -122};
              String chineseData = new String(data, "UTF-8");
              System.out.println( chineseData );
              System.out.println();

              // 单个反编译测试
              byte[] byteText = {-28, -72, -83};
              System.out.println( new String(byteText, "UTF-8") );
            1.  
          • 效果如下:
            •  
                      

其他的那些编码也可以这么玩儿

同时:由以上的测试就得出一个结论:

  • 只要产生了乱码,那么必定是编码格式和解码格式不一致导致的

打印流———printStream(没啥好玩儿的)

这个东西最常见了,一直都在用,只是不知道它具体的名字而已

  • System.out.println()———龟儿嘞舅舅滴,这就是属于打印流^ _ ^,只不过这是属于System下的而已

1、字节打印流

  • 直接看实例

      1. // 字节打印流
      2. PrintStream ps = new PrintStream("d:/test/play.txt");
      3. ps.println("what are you 弄啥嘞?"); // 这是向指定文件打印数据
      4. ps.close();
      5.  
      6. // 字符型打印流
      7. PrintWriter pw = new PrintWriter("d:/test/play.txt");
      8. pw.print("这玩意儿也不好玩儿啊");
      9. pw.close();

任意文件访问类——RandomAcessFile(更没什么好玩儿的)

通过seek(int pos) 方法移动指针——用来规定从什么位置开始写数据,读数据
 

支持三种模式

  • r 只读

    只写

    rw 读写————这个比前面两个用有一点儿

  • 直接看实例咯,懒球整这个类其他的屁东西

      1. // 随机访问文件类
      2. RandomAccessFile raf = new RandomAccessFile("d:/test/play.txt","rw");
      3. // 移动光标到 末尾位置 写数据
      4. raf.seek( raf.length() );
      5. raf.writeBytes( "mysql" );
      6.  
      7. // 移动光标到 开始位置 读操作
      8. raf.seek(0);
      9. String line = raf.readLine();
      10. System.out.println( line );
      11. raf.close();


流技术的东西就搞完了,在这个阶段没什么写的了

javaSE高级篇2 — 流技术 — 更新完毕的更多相关文章

  1. javaSE高级篇3 — 网络编程 — 更新完毕

    网络编程基础知识 先来思考两个问题( 在这里先不解决 ) 如何准确的找到一台 或 多台主机? 找到之后如何进行通讯? 网络编程中的几个要素 IP 和 端口号 网络通讯协议:TCP / UDP 最后一句 ...

  2. 4 - 基于ELK的ElasticSearch 7.8.x技术整理 - 高级篇( 续 ) - 更新完毕

    0.前言 这里面一些理论和前面的知识点挂钩的,所以:建议看一下另外3篇知识内容 基础篇:https://www.cnblogs.com/xiegongzi/p/15684307.html java操作 ...

  3. javaSE高级篇4 — 反射机制( 含类加载器 ) — 更新完毕

    反射机制 1.反射机制是什么?----英文单词是:reflect.在java.lang包下---这才是java最牛逼的技术 首先提前知道一句话----在java中,有了对象,于是有了类,那么有了类之后 ...

  4. javaSE高级篇6 — 注解( 附:注解底层解析 ) —— 更新完毕

    注解 ---- 英文:annotation 1.注解长什么样子? @xxxxxxx( 一些信息 ) ----- 这个信息可有可无 2.注解可以放在什么地方? 类本身的上面.属性的上面.方法的上面.参数 ...

  5. javaSE高级篇5 — java8新特性详解———更新完毕

    java8新特性 在前面已经见过一些东西了,但是:挖得有坑儿 1.lambda表达式 lambda表达式是jdk1.8引入的全新语法特性 它支持的是:只有单个抽象方法的函数式接口.什么意思? 就是说: ...

  6. javaSE高级篇7 — 设计原则和设计模式 — 设计模式慢慢更( 这是思想层次篇 )

    1.什么是设计原则? 设计原则就是面向对象的原则嘛,即:OOP原则 换句话说:就是为了处理类与类之间的关系( 包括接口.类中的方法 ) 2.OOP设计原则有哪些? 1).开闭原则:就是指对拓展开放.对 ...

  7. javaSE高级篇1 — 异常与多线程基础

    1.异常的体系结构  注:Throwable是一个类,不是一个接口,这个类里面是描述的一些Error和Exception的共性,如图所示: 异常 / 错误是什么意思? 定义:指的是程序运行过程中,可能 ...

  8. javaWeb - 1 — servlet — 更新完毕

    1.先来聊一些javaWeb相关的知识 简单了解一下:web的发展史 1).web就是网页的意思嘛 2).web的分类 (1).静态web 使用HTML.CSS技术,主要包括图片和文本 优点:简单,只 ...

  9. Vue2技术整理3 - 高级篇 - 更新完毕

    3.高级篇 前言 基础篇链接:https://www.cnblogs.com/xiegongzi/p/15782921.html 组件化开发篇链接:https://www.cnblogs.com/xi ...

随机推荐

  1. 轻松掌握stm32直流电机驱动与测速

    说实话就现在的市场应用中stm32已经占到了绝对住到的地位,51已经成为过去式,32的功能更加强大,虽然相应的难度有所增加,但是依然阻止不了大家学习32的脚步,不说大话了这些大家都懂要不然也不会学习s ...

  2. 快速了解XML

    1. XML 定义 可扩展标记语言,标准通用标记语言的子集,简称XML.是一种用于标记电子文件使其具有结构性的标记语言. 2. XML 展示 如下是一个xml的标记展示,XML 是不作为的XML 被设 ...

  3. 查看VCS版本的指令

    以本人电脑的安装目录为例:在任意path下打开terminal执行命令行/usr/local/vcs2018/bin/vlogan -ID -full64 /usr/local/vcs2018为VCS ...

  4. php linux yaml 的安装和使用

    安装: 1 下载yaml包 wget http://pyyaml.org/download/libyaml/yaml-0.2.2.tar.gz tar -zxvf yaml-0.2.2.tar.gz ...

  5. cpu内核态与用户态

    1.操作系统需要两种CPU状态 内核态(Kernel Mode):运行操作系统程序,操作硬件 用户态(User Mode):运行用户程序 2.指令划分 特权指令:只能由操作系统使用.用户程序不能使用的 ...

  6. LeetCode -90. 子集 II C++ (回溯法)

    class Solution { public: vector<vector<int>> subsetsWithDup(vector<int>& nums) ...

  7. MAC安装vue.js

    一.下载node node下载地址:https://nodejs.org/en/download/ 下载后点击安装即可. node -v 检查安装是否成功 二.安装 淘宝镜像 (npm) npm in ...

  8. 大一C语言学习笔记(2)---快捷键篇

    大家好,博主呢,是一位刚刚步入大一的软件工程专业的大学生,之所以写博客,是想要与同样刚刚接触程序员一行的朋友们一起讨论,进步,在这里记录我的一些学习笔记及心得,希望通过这些点点滴滴的努力,可以让我们离 ...

  9. Django笔记&教程 0-1 前言

    Django 自学笔记兼学习教程第0章第1节--前言 点击查看教程总目录 1 最初的想法 自学Django已经有一段时间了,自认收获不少,学的还算可以,然而实际去做项目写代码的时候,很多用法记得不清, ...

  10. psutil模块详解

    import psutil#1.系统性能信息模块psutilmem = psutil.virtual_memory()print(mem)#svmem(total=8442675200, availa ...