流和文件

流结构基础梳理

java 的io体系概念较多,相应的读写的类较为复杂,有必要根据种类进行分类梳理,以便记忆

字节流 字符流

字节流

  • super class: InputStream && OutputStream
  • 读写的基本长度是8bit
  • 可以处理任意类型的文件

字符流

  • super class : Reader && Writer
  • 读写的基本长度是一个字符 16bit
  • 一般用来处理带有编码格式的文本

节点流,处理流

节点流

  • 节点流职级操作文件,或者网络数据 ,FileInputStream,FileOutputStream

处理流

  • 对节点流进行进一步包装,例如提供缓冲功能,数据过滤功能,对数据的读写的报装
    常见处理流又包含 缓冲流,转换流,数据流,对象流

缓冲流

  • BufferedInputStream / BufferedOutputStream
  • 数据会缓冲到内存里面,流关闭之前,需要进行flush的操作,将数据写入磁盘,避免数据的丢失

转换流

  • 只有InputStreamReader / OutputStreamWriter
  • 字节到字符的转换

    数据流

  • 提供java 基本类型数据的读写
  • DataInputStream / DataOutputStream

Object 流

  • 对象的序列化
  • readObject() / writeObject()
  • jvm原生的序列化对象按自定义固定的格式(基于二进制)
  • 对于不可序列化的域,可以使用transient 标示

使用总结

读写文本数据

  • 文本输出PrintWriter,文本读入Scanner 或者BufferedReader
  • nio 的File类可以方便的读写中等长度的文本文件

读写二进制数据

  • DataInputStream 读入二进制数据并转化为java数据类型 , DataOutputStream 将java的数据以二进制写入,这两个流分别实现接口DataInput 和DataOutput 接口

java对象的读写

  • ObjectInputStream ObjectOutputStream

java 对象的序列化

java 文件目录操作

  • File 、Path 对系统文件目录进行操作
  • 操作的文件系统默认是用户所在的磁盘,Paths 也可以操作其他的文件系统,例如一个zip压缩包

java 里面的内存映射

  • 关于四种文件读入的方式的性能比较
    • 四种方式分别为:普通输入流,带缓冲的输入流,随机访问文件,内存映射文件
    • 性能测试代码
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      public class ReadSpeedTest {
      public interface Command {
      public long execute(Object data);
      }
      public static class TestInputStream implements Command {
      public long execute(Object data) {
      try{
      InputStream in = Files.newInputStream((Path)data);
      CRC32 crc32 = new CRC32();
      int c;
      while ((c = in.read()) != -1) {
      crc32.update(c);
      }
      return crc32.getValue();
      } catch (Exception e) {
      return -1;
      }
      }
      }
      public static class TestBufferInputStream implements Command {
      public long execute(Object data) {
      try {
      BufferedInputStream bufferedInputStream = new BufferedInputStream(Files.newInputStream((Path)data));
      CRC32 crc32 = new CRC32();
      int c ;
      while ((c = bufferedInputStream.read()) != -1) {
      crc32.update(c);
      }
      return crc32.getValue();
      } catch (Exception e) {
      return -1;
      }
      }
      }
      public static class TestRandomAccessFile implements Command {
      public long execute(Object file) {
      try {
      RandomAccessFile randomAccessFile = new RandomAccessFile(((Path)file).toFile(),"r");
      long fileLength = randomAccessFile.length();
      CRC32 crc32 = new CRC32();
      for (int i = 0; i < fileLength; i++) {
      randomAccessFile.seek(i);
      int c = randomAccessFile.read();
      crc32.update(c);
      }
      return crc32.getValue();
      } catch (Exception e) {
      return -1;
      }
      }
      }
      public static class TestMappedFile implements Command {
      public long execute(Object file) {
      try {
      FileChannel fileChannel = FileChannel.open((Path)file);
      CRC32 crc32 = new CRC32();
      long length = fileChannel.size();
      MappedByteBuffer memBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,0,length);
      for (int i = 0; i < length; i++) {
      int c = memBuffer.get(i);
      crc32.update(c);
      }
      return crc32.getValue();
      } catch (Exception e) {
      return -1;
      }
      }
      }
      public static long time(String fileName,Command c) {
      long startTime = System.currentTimeMillis();
      long crcValues = c.execute(Paths.get(fileName));
      long endTime = System.currentTimeMillis();
      System.out.println(endTime - startTime);
      return 0;
      }
      public static void main(String[] args) {
      time(args[0],new TestInputStream());
      time(args[0],new TestBufferInputStream());
      time(args[0],new TestRandomAccessFile());
      time(args[0],new TestMappedFile());
      }

ps: 上面的代码一个一个字节读数据,能代表的数据很有限,可以尝试读取一个大文件,感受性能差异

文件锁

  • 获得文件锁使用FileChannel类 ,lock() or trylock()

    • api

      1
      2
      FileLock lock (long start , long size,boolean shared)
      FileLock tryLock (long start , long size,boolean shared)
    • java中的锁

正则表达式

  • Pattern && Matcher
  • Pattern.compile(regexString) ,then User Matcher to get the taget

参考链接