VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • javaSE高级篇2 — 流技术 — 更新完毕

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、创建File对象
          File file = new File( "D:\\InatallationPackage\\Mybatis\\Resources" ); // 当然这里的 \\,也可以写成 /       

 

 

  • File类中的一些常用方法(完整的方法集可以直接看API)
    • length()————获取文件的字节大小
      • File file = new File("D:\\InatallationPackage\\Mybatis\\Resources");
        
        System.out.println( file.length() );

         

 

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

         

 

    • boolean = CanWrite()————查看文件是否可写
      • // 3、查看文件是否可写
        System.out.println( file.canWrite() );

         

 

    • boolean = CreatNewFile()————创建一个新文件————相比其他这个方法更常用
      • 复制代码
        // 4、创建一个新文件
         try {
        
           System.out.println( new File("D:/IntallationList/creatNewFile.txt").createNewFile() );
        
           System.out.println( new File("d:/creatNewFile.txt").createNewFile() ); // 这两种创建都行
           /*
             注:
                1、这个方法需要处理异常————抛出或捕获都行
        
                2、创建的文件前面的路径必须是真实有效的,否则:无法创建
        
           */
        
          } catch (IOException e) {
                    e.printStackTrace();
         }
        复制代码

         

 

    • boolean = delete()————删除一个文件 / 文件夹————如果删除的文件夹中还有文件 / 文件夹,则:无法删除   
      • // 5、删除一个文件
        System.out.println( new File("D:\\test\\hit-me.txt").delete() );

 

    • boolean = exists()————查看一个文件是否存在——这个在开发中还有点用
      • // 6、查看一个文件是否存在
        System.out.println( new File("d:/test/aaa.txt").exists() );

 

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

 

    • String = getName()————获取文件的名字————也有点用
      • // 8、获取文件的名字————本例子中结果为:MaveIntallationList
         System.out.println( new File("D:\\IntallationList\\MaveIntallationList").getName() ); 

 

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

 

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

 

    • String[ ] = list()————返回指定文件夹中的所有文件 / 文件夹名 的 String类型数组————还是没多大用
      • 复制代码
        // 11、返回一个文件夹中的所有文件 / 文件夹 名的 String数组
        String[] fileList = new File("D:\\IntallationList").list();
        
        for (String list : fileList) {
        
          System.out.println( list );
        }
        复制代码

 

    • File[] = listFiles()————返回指定文件夹中的所有文件 / 文件夹 的全路径的 File对象数组————这个才是有用的
      • 复制代码
        // 12、返回指定文件夹中的所有文件 / 文件夹 的 全路径的 File对象数组
        File[] files = new File("D:\\IntallationList").listFiles();
        for (File f : files) {
        
           System.out.println( f );
        }
        复制代码

 

    • mkdir()————创建文件夹,是文件夹,不是前面说的文件————但是:这个方法创建,必须保证要创的文件夹外面那一层文件夹是真实存在的,否则:创建不了————但是这个方法也没什么卵用
      • // 13、创建文件夹
        System.out.println( new File("d:/test/demo").mkdir() ); // 这种好使,因为demo的上一级test是存在的
        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关键字创建,但是需要传参,参数有三种方式————最常用的是下图中的前两种
        • 复制代码
                  try {
          
                      // 1、直接利用String类型的有参构造————注意:处理异常,可以抛出,也可以捕获
                      FileInputStream fis = new FileInputStream( "D:\\IntallationList" );
          
                      // 2、通过套个儿子的方式创建
                      FileInputStream fis2 = new FileInputStream( new File("D:\\IntallationList") );
          
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                  }
          复制代码

 

    • 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流技术的操作流程的三步骤(死流程)————三板斧^ _ ^
    • 创建流
    • 读数据
    • 关闭流管道

 

  • 实例
    • 复制代码
      import java.io.FileInputStream;
      import java.io.IOException;
      
      public class Test {
      
          public static void main(String[] args) {
      
              // 1、创建流
              FileInputStream fis = null;
              try {
                  fis = new FileInputStream("D:\\InatallationPackage\\Maven\\pom.xml");
      
                  // 2、读数据
                  // 准备一个容器————用来装读取出来的数据
                  byte[] data = new byte[1024];  // 大小可以任意取,建议用这个大小
                  int len;  // 这len是为了给read()读取的int结果 同时为了判断————注:别把这个len放在while那个判断力,会出问题
                  while ( ( len = fis.read( data ) ) != -1 ){ // read()读取文件 
          // 同时把读取出来的结果放到新建的data数组容器里。另外:这里的判断可以不写成 != -1,还可以写成 > 0 
      
                      System.out.println( new String( data , 0,len ) ); // 这里可以看需求弄成其他方式,我只是为了看效果,所以打印了而已
                  }
      
              } catch (IOException e) {
      
                  e.printStackTrace();
      
              }finally {
      
                  // 关闭流管道
      
      
                  // 保证代码健壮性
                  if ( fis != null ){ // 判断一手儿,为什么是 != nul才关闭流管道?看起来应该是fis中为null了,才说明没有内容需要读写了涩
      
                                     // 别忘了 真正去进行映射操作文件的是哪个吊毛————File对象,所以这里的fis只是一个对象,它指向的是File
                                    // 所以要是fis为null了,那不就说明fis没有引用了吗,这不就没有一个指向者了————最后也就会导致空指针异常
      
                                   // 后续另外的流也是这么一个原因
      
      
                      try {
      
                          fis.close();  // 再关闭流管道
      
                      } catch (IOException e) {
                          
                          e.printStackTrace();
                      }
                  }
              }
      
          }
      }
      复制代码

 

 

 

  • 2、字节型文件输出流——FileOutputStream
    • 将一些数据写入到一个指定的文件中
    • 在java.io包下
    • FileOutputStream继承了OutputStream

 

    • FileOutputStream怎么创建对象?
      • 和FileInputStream一样

 

      • 只是有一个地方需要注意:就是这个输出流是可以操控 是否可以追加内容的,即:上图中的第2和第4种创建方式,参数中有一个boolean类型的参数,这个参数就是表示:是否需要追加,默认是false
        • 追加是什么意思? 
          • 就是下一次添加内容到同一个文件的时候,可以追加的话,就表示:从文件的后面接着添加内容。不可以追加的话,就表示:系统把原文件删了,然后重新创建一个和原文件名字一模一样的文件,最后再添加本次的内容

 

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

 

 

  • FileOutputStream的使用流程是怎么样的?——还是三板斧
    • 创建流
    • 写数据
    • 关闭流管道

 

实例:

  • 复制代码
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    // 字节型文件输出流
    public class TestFileOutputStream {
    
        public static void main(String[] args) {
    
            // 1、创建流
            FileOutputStream fos = null;
            try {
    
                fos = new FileOutputStream("d:/test/demo.txt",true); // true为:可以追加内容
    
                // 2、写数据————想要向上面的文件中写入什么内容————利用write()方法————但是这个方法的参数是int 或 byte[]
                fos.write( "这是想要写入的String类型的内容".getBytes() );  // 利用String中的getBytes()方法就把String转为 byte[]字节数组了
    
    
                // 也可以在这里加上flush()————即:把2中的数据从流管道中推入文件中
                fos.flush(); // 但是:不用加也可以,因为:close()在这里面有关闭流管道、刷新文件中数据的功能
            } catch (IOException e) {
    
                e.printStackTrace();
            }finally {
    
                // 3、关闭流管道
                if ( fos != null ){ // 为了代码的健壮性,严谨判断一手儿
                    try {
    
                        fos.close(); // 关闭流管道
    
                    } catch (IOException e) {
    
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    复制代码

     

 

  • 利用FileInputStream 和 FileOutputStream实操一手儿
复制代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Scanner;

/**
 * 有这么一个需求:
 *      1、从控制台输入

 *          日记标题
 *          输入正文
 *          然后保存到一个文件中————要求每一篇的日记名字都不一样

 *
 *       2、从日记文件中读取指定名字的日记,从而在控制台显示出对应的日记内容

 */
public class Note {

    public static void main(String[] args) {

        writeNote();
        readNote();
    }

    // 录入日记
    public static void writeNote() {

        System.out.println("请输入日记的标题:");
        Scanner input = new Scanner(System.in);
        String title = input.next();

        System.out.println("请输入日记的正文:");
        String text = input.next();

        // 把控制台输入的东西 放到指定文件中去

        // 1、创建输出流
        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream("d:/test/note/" + new Date().getTime() + ".txt");

        // 2、写数据
            // 把标题写入文件中去
            fos.write( "标题:".getBytes() );
            fos.write(title.getBytes() );
            fos.write( "\n".getBytes() );   // 换行


            // 把输入的正文写入到文件中去
            fos.write( "正文:".getBytes() );
            fos.write( text.getBytes() );

        } catch (IOException e) {
            e.printStackTrace();
        }finally {

       // 3、关闭流管道
            if ( fos != null ){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

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

        }
    }

    // 读取指定名字的日记
    public static void readNote() {

        System.out.println("请输入你想要查看的日记名:");
        Scanner input = new Scanner(System.in);
        String noteName = input.next();
        String realName = noteName + ".txt";

        // 创建输入流
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("d:/test/note/" + realName);

            // 读数据
            byte[] text = new byte[1024];
            int len;
            while ( ( len = fis.read(text) ) != -1 ){

                System.out.println( new String( text,0,len ) );
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

            // 关闭流管道
            if ( fis != null ){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码

 

效果图如下:

 

 

 

2、字符型文件流

 

  • 1、字符型文件流——以字符的形式读取文件,通常是纯文本文件(如:txt文件)——excel、doc这种不是纯文本,它是一种软件
    • 为什么要有字符型文件流?
      • 假设有这么一个文件————里面有中文和英文
      • 如果想要去读取这个文件,而用来装读取内容的容器大小刚好是16呢?————即:大小位置为“你”这个字哪里,“你"之前的 , 逗号那里为15,空格也是一个字符
        • 这种情况继续用字节型文件流来读取会怎么样?———— 一个中文占2个字节
          • 那这样,想要把“你”字完全读出来,理论上应该是容器大小为17,这样才可以装得下“你”这个字涩
          • 但是:容器大小是16————所以会导致:中文读取失败( 即:无法完整读取 )
          • 同时:以字符的形式读取 比 字节的形式更快一点
          • 因此:有了字符型文件流

 

 

  • 字符型文件流的分类
    • FileReader     字符输入流————核心方法就:read()
    • FileWriter       字符输出流————核心方法就:write()

 

  • 怎么创建对象?
    •  

 

 

  • 实例使用——三板斧———流的使用都是这样,后续不再说明了
    • 复制代码
      package cn.xieGongZi.testFileReaderAndFileWriter;
      
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.IOException;
      
      public class Demo {
      
          public static void main(String[] args) throws IOException {
      
              readData();
              writeData();
          }
      
          // 读数据
          public static void readData() throws IOException {
      
              // 创建流管道
              FileReader fr = new FileReader("D:\\InatallationPackage\\Maven\\pom.xml");
      
              // 读数据
              char[] data = new char[1024];
              int len;
              while ( (len = fr.read(data)) != -1 ){
      
                  System.out.println( new String( data,0,len) );
              }
      
              if ( fr != null ){
      
                  fr.close();
              }
          }
      
      
      
          // 写数据
          public static void writeData() throws IOException {
      
              // 创建流管道
              FileWriter fw = new FileWriter("d:/test/play.txt", true);
      
              // 写数据
              fw.write("天王盖地fu,宝塔镇huo妖");
      
              // 关闭流管道
              if ( fw != null ){
                  fw.close();
                  System.out.println("数据写入完毕");
              }
          }
      }
      复制代码

 

 

 

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

 

 

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

 

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

 

 

 

 

1、字节型缓冲流

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

 

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

 

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

 

 

 2、字符型缓冲流

  •  字符输入流——BufferedReader————对照FileReader
    • 但是:这个有一个需要注意的地方————BufferedReader的一个方法
      • nextLine()————读取纯文本中一行的内容——很重要啊,用这个流读数据就用这个方法,不再用read()

 

 

 

 

  •  字符输出流——BufferedWriter———对照FileWriter
    • 这个流也有一个特殊的地方————BufferedWriter的一个方法
      • newLine()————这个方法就相当于是换行

 

 

 

 

 实操一手儿

  • 复制代码
    package cn.xieGongZi.buffer;
    
    import java.io.*;
    
    public class Demo {
    
        public static void main(String[] args) throws IOException {
    
            readData();
            writeData();
    
        }
    
        // 读数据
        public static void readData() throws IOException {
    
            BufferedReader br = new BufferedReader(new FileReader("D:\\IntallationPackage\\Maven\\pom.xml"));
    
            String data = null;
    
            while ( ( data = br.readLine()) != null ){  // readline()一行一行的读取内容
    
                System.out.println(data);
            }
    
        }
    
    
        // 写数据
        public static void writeData() throws IOException {
    
            // 创建输出流
            BufferedWriter bw = new BufferedWriter(new FileWriter("d:/test/play.txt",true));
    
            // 写要录入文件的数据
            bw.newLine(); // 换行————在新的一行中开始添加内容
            bw.write("老衲来自西方极乐世界,到南方来享受金乌施主的温柔阳光");
    
            // 关闭流管道
            if ( bw != null ){
    
                bw.close();
                System.out.println("数据写入成功");
            }
    
    
        }
    }
    复制代码

     

 

 

 

 

转换流(重点)

 

转换流的作用:

  • 有时读写文件的时候,用字节的方式来读写太慢了,利用字符的形式读写要快得多涩,所以这个时候就需要把字节型流 转换为 字符型流,这样读写的效率就快得多了
    • 根据上面的理论,好像也可以套儿子嘛,因为是字节型转为字符型,所以直接在字符型中再套一个字节型就可以了涩( 因为字符流 就是 基于字节流实现的嘛 )。如下所示(字节文件输入 转 字符文件输入):
FileReader fr = new FileReader( new FileInputStream("d:/test/play.txt") );  // 这样看起来貌似就是想要的效果嘛

 

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

 

 

 

 

 

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

 

 

 

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

 

 

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

  • 复制代码
    // 字节型输出流——————>字符型输出流
            
    // 创建流
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/test/play.txt",true)));
    
    // 写数据
    bw.newLine();   // 换行再录入数据
    bw.write("贫道突然不知道录入个啥子数据进去好了");
    
    // 关闭流管道
    if ( bw != null ){
         bw.close();
         System.out.println("数据录入成功");
    }
    复制代码

 

 

 

对象流(重点)——ObjectStream

 

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

  • 在面向对象编程篇的特征修饰符中见过一个修饰符了涩————transient,即:瞬时的(通俗讲就是:不把对象序列化)
    • 这个猫玩意儿就需要用到这里来了

 

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

 

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

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

 

  • ObjectOutputStream流如何创建对象?
    • ObjectOutputStream = new ObjectOutputStream( OutputStream os )

 

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

 

  • 实例走起
    • 创建一个对象————先创建一个类(用其他对象也可以)
      • 复制代码
        package cn.xieGongZi.objectStream.test;
        
        import java.io.Serializable;
        
        public class Person implements Serializable { // 让这个类实现Serializable接口,表明这个类是可序列化的
        
            private String name;
            private char sex;
            private Integer age;
        
            @Override
            public String toString() {
                return "Person{" +
                        "name='" + name + '\'' +
                        ", sex=" + sex +
                        ", age=" + age +
                        '}';
            }
        
            public Person() {
            }
        
            public Person(String name, char sex, Integer age) {
                this.name = name;
                this.sex = sex;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public char getSex() {
                return sex;
            }
        
            public void setSex(char sex) {
                this.sex = sex;
            }
        
            public Integer getAge() {
                return age;
            }
        
            public void setAge(Integer age) {
                this.age = age;
            }
        }
        复制代码
    • 进行序列化
      • 复制代码
        // 序列化流
        
        // 创建流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/test/ObjectOutputStream.txt"));
        
        // 写数据
        oos.writeObject(new Person("邪公子", '女', 18));  // 注意:这里是使用WriteObject()
        oos.writeObject(new Person("紫邪情", '女', 30));
        oos.writeObject(new Person("小紫", '女', 150));
        oos.writeObject(new Person("韩非", '男', 100));
        
        // 关闭流管道
        if (oos != null ){
            oos.close();
            System.out.println("对象序列化完毕");
        }
        复制代码
      • 效果如下:看不懂就对了,这就是字节碎片,是计算机底层的东西,这个内容是计算机强行显示出来的内容,在底层也就是二进制存储的

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

 

2、反序列化对象流

  • 指的是:把字节碎片 还原回 一个完整的对象

 

  • 直接上实例
    • 复制代码
              // 反序列化
      
              // 创建流
              ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/test/ObjectOutputStream.txt"));
      
              // 读数据
              try {
      
                  Object person1 = ois.readObject();  // 在这里:反序列化的顺序就是前面序列化的顺序,不能把顺序搞乱了,不然反序列化出来的数据不一样 / 出错
                  System.out.println( person1 );  // 看效果
      
                  Object person2 = ois.readObject();
                  System.out.println( person2 );
      
                  Object person3 = ois.readObject();
                  System.out.println( person3 );
      
                  Object person4 = ois.readObject();
                  System.out.println( person4 );
      
              } catch (ClassNotFoundException e) {
                  e.printStackTrace();
              }finally {
      
                  // 关闭流管道
                  if (ois != null ){
                      ois.close();
                  }
              }
      复制代码
    • 效果如下:

 

 

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

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

 

 

 

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

 

编码

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

 

字符集

  • 指的是:一张记录了对应关系的信息表
    • 这种有很多,如:
      • GBK ———— 我国的国标码
      • ISO-8859-1 ———— 西欧语言
      • Big5 ———— 香港台湾语言(繁体字)
      • Unicode ———— 联合编码(多个国家的语言字符都包含在这张表里面)————里面还分为:UTF-8(三串数字存一个中文字符)、UTF-16.......

 

  • 理论整起来贼没意思,来上实例
    • 假如:我存了这么一个数据,然后采用了ANSI编码(不懂门道的,可以简单理解为GBK)

 

    • 然后去读取这个文件
      • 复制代码
        FileInputStream fis = new FileInputStream("d:/test/play.txt");
        
        byte[] data = new byte[1024];
        int len;
        while ( ( len = fis.read(data) ) > 0 ){
                System.out.println( new String(data, 0, len) );
              }
        
        if ( fis != null ){
              fis.close();
        }
        复制代码
      • 读取出来的效果是这样的————即:发生乱码了————怎么解决?

        •     
      • 只需要把编码格式改一下————因为:保存的时候是使用的ANSI编码,那解码用GBK就可以了( 即:charSet )
        •  

 

  • 再来了解一下:前面说的UTF-8是三串数字存一个中文字符是不是真的
    • 测试一下
      • 复制代码
        // UTF-8是不是采用三串数字保存的一个中文字符?
        String data = "中国太好玩儿了";
        
        // 把这个内容采用UTF-8的解码格式读出来看一下
        byte[] newData = data.getBytes();  // 这个采用的是系统的默认字符集,而我的字符集就是UTF-8
        
        // 打印出来看一下
        System.out.println( Arrays.toString(newData) );
        复制代码
        • 我的idea编码解码格式如下:
      • 最后看一下效果
        • 复制代码
          -28, -72, -83 ———— 中
          
          -27, -101, -67 ———— 国
          
          -27, -92, -86 —————— 太
          
          -27, -91, -67 —————— 好
          
          -25, -114, -87 —————— 玩
          
          -27, -124, -65 —————— 儿
          
          -28, -70, -122 —————— 了
          复制代码

 

        • 再验证一下嘛:拿这串数字反编译一下,看是不是这几个字
          • 复制代码
            // 整体反编译测试
            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") );
             
            复制代码
          • 效果如下:
            •  
                      

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

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

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

 

 

 

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

 

 

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

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

 

1、字节打印流

  • 直接看实例
    • 复制代码
      // 字节打印流
      PrintStream ps = new PrintStream("d:/test/play.txt");
      ps.println("what are you 弄啥嘞?");   // 这是向指定文件打印数据
      ps.close();
      
      // 字符型打印流
      PrintWriter pw = new PrintWriter("d:/test/play.txt");
      pw.print("这玩意儿也不好玩儿啊");
      pw.close();
      复制代码

 

 

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

 

 

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

 

 

支持三种模式

  • r 只读

    只写

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

 

  • 直接看实例咯,懒球整这个类其他的屁东西
    • 复制代码
      // 随机访问文件类
      RandomAccessFile raf = new RandomAccessFile("d:/test/play.txt","rw");
      // 移动光标到 末尾位置 写数据
      raf.seek( raf.length() );
      raf.writeBytes( "mysql" );
      
      // 移动光标到 开始位置 读操作
      raf.seek(0);
      String line = raf.readLine();
      System.out.println( line );
      raf.close();
      复制代码

       

 

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

 

作者:紫邪情

出  处:
https://www.cnblogs.com/xiegongzi/p/15132575.html



相关教程