zoukankan      html  css  js  c++  java
  • Java 文件 IO 操作

    文件:文本、图片、视频、程序等存储在计算机上

    文件目录:文件夹,管理文件, linux 下有权限、操作符、用户组、用户等

           路径分割符:

       表示 windows 系统文件目录分割符
      / 表示 mac/linux 下的路径分割符

      java 代码在 windows 下写某个文件的话需要下面的方式

      D:\soft\sd.txt  其中一个单斜杠是用来转义的

      java 代码在 linux 或者 Mac 下写某个文件的话需要下面的方式

      usr/local/soft/sd.txt  其中一个单斜杠是用来转义的

      代码和文件目录的关系: 对文件和目录增删改查
      IO,输入和输出 Input/Output
      把持久化设备上的数据读取到内存中的动作称为输入, Input 操作
      内存中的数据持久化到设备上的动作, Output 输出操作
      一般把输入和输出动作称为 IO 操作, IO 分为网络 IO 和文件 IO

     java 文件类 File :  

      主要是对计算机文件目录的操作,对文件和目录的增删改查, File 类表示磁盘中存在的文件和目录
      实现了 Serializable, Comparable 两大接口,可进行序列化和比较
      File.separator 目录分隔符,在不同的系统下不一样, windows 下是 "" , mac/Linux 下是 "/",操作文件时可以用来连接目录的分隔符

      常见的构造函数:
      //路径和文件名的拼接
      public File(String pathname)

      //父路径,子路径
      public File(String parent, String child)

      // 获取带文件名的文件路径,即 new File 构造函数传入的路径
      String getPath()

      String dir = "C:\Users\79466\Desktop\";
      String name = "a.txt";
      File file = new File(dir, name);
      // File file = new File(dir); 目录对象

      System.out.println(file.getPath()); // 打印文件的路径和文件名
      System.out.println(File.separator); // 打印不同系统的文件分隔符

      // 常用的文件操作 api
      file.getPath();  // 获取带文件名的文件路径, C:Users79466Desktopa.txt
      file.getName();  // 获取文件名, a.txt
      file.getAbsolutePath();  // 获取文件的绝对路径 C:Users79466Desktopa.txt
      file.getParent();  // 获取文件的父路径 C:Users79466Desktop
      file.exists();  // 文件或者目录是否存在
      file.isFile();  // 是否是一个文件
      file.isDirectory();  // 是否是一个目录
      file.isAbsolute();  //是否是绝对路径

      // 如果 file 是目录,获取文件目录下所有的文件及目录的名称,操作对象是目录,如果是文件会报错
      String[] arr = file.list();
      for (String temp : arr) {
        System.out.println(temp);
      }

      // 创建指定目录
      File mkdir = new File(dir + "\xd");
      mkdir.mkdir();  //创建一级目录

      File mkdirs = new File(dir + "\xd\aa\bb\cc");  // 或者 dir + "\xd\aa\bb\cc\"
      mkdirs.mkdirs();  //创建多级目录

      File newFile = new File(dir + "\xxxx.txt");
      // 如果 dir 不存在或者创建文件失败需要捕获异常
      try {
        newFile.createFile();
      } catch (IOException e) {
        e.printStackTrace();
      }

      newFile.delete();   //删除操作,当前文件如果是最终的文件才可以删除,如果是目录,里面还有文件,需要先删除文件才能删除该目录

      File 的构造函数只是创建一个 File 实例,即使目录错误也不会报错,因为没有对文件进行操作
      输出流: 程序到外界设备 输入流: 外界设备到程序
      处理数据类型分类
      字符流: 处理字符相关,如文本数据( txt 文件), Reader / Writer
      字节流: 处理字节相关,声音或者图片等二进制, InputStream/OutputStream
      两者区别:
        字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节
        字节流可以处理几乎所有文件,字符流只能处理字符类型的数据,如果文件都是中文文本的话可以使用字符流,速度更快,更省空间
        功能不同,但是具有共性内容,抽象成4个抽象类
        字符流 Reader/Writer
        字节流 InputStream/OutputStream

        使用的时候都不会使用抽象类进行实现,开发使用对应的子类

      字节流:
        InputStream: 实现类及子类有 FileInputStream (这个类用的最多, 可以用 BufferedInputStream 提高性能)、 ObjectInputStream (对象输入流,序列化的时候) 、 ByteArrayInputStream
        OutputStream 和 InputStream 一样

        int read(byte[] buf) // 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf 中,返回实际读取的字节数

        int available() // 返回这个流中有多少个字节数,可以把 buf 数组长度定为这个

        void close() throws IOException // 关闭输入流并释放与该流关联的系统资源

      FileInputStream 字节输入流:

        // 传入文件所在地址
        public FileInputStream(String name) throws FileNotFoundException
        // 传入文件对象
        public FileInputStream(File file) throws FileNotFoundException

        public static void main (String [] args) {
          File file = new File(dir, name);
          InputStream inputStream = new FileInputStream(file);
          // 读取一个字节
          int read = inputStream.read();
          // 字节对应的 ASCII 码
          System.out.println(read);
          // 强转成字符
          System.out.println((char)read);
        }

        inputStream.skip();   // 跳过,从输入流中跳过并丢弃 n 个字节的数据

        byte[] buf = new byte[1024];
        int length;
        // 一次性读取 buf.length 个字节并放到 buf 数组中,返回类型是读取到的字节数
        while ((length = inputStream.read(buf)) != -1) {
          System.out.println(new String(buf, 0, length)); // 从0开始,长度是3
          System.out.println(new String(buf, 0, length, "UTF-8"));
        }

      FileOutputStream 字节输出流:

        构造:
        // 传入输出的文件地址
        public FileOutputStream(String name)

        // 传入目标输出的文件对象
        public FileOutputStream(File file)

        // 传入目标输出的文件对象,是否可以追加内容
        public FileOutputStream(File file, boolean append)

        public static void main(String [] args)  {

          String target = "a.txt";
          InputStream inputStream = new FileInputStream(file);
          // 会创建文件,但是不会创建多级目录
          // OutputStream outputStream = new FileOutputStream(dir + File.separator + target);
          // 不覆盖文件,只追加数据
          OutputStream outputStream = new FileOutputStream(dir + File.separator + target, true);
          byte[] buf = new byte[1024];
          int length;

          // 一次性读取 buf.length 个字节并放到 buf 数组中,返回类型是读取到的字节数
          while ((length = inputStream.read(buf)) != -1) {
            // 按字节数组的长度写出
            outputStream.write(buf, 0, length);
          }

          // 异常处理见下面,此处如果上面出现异常就无法关闭
          inputStream.close();
          outputStream.close();
        }

      缓冲 Buffer :

      内存空间的一部分,在内存空间预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分空间就叫做缓冲区,缓冲区默认大小是8k,使用缓冲区暂存数据,
      可以减少和磁盘的交互,读入时与磁盘连接后读入较多的数据到缓冲区,内存再慢慢去消耗

      BufferInputStream 缓冲字节输入流,读取数据时,与磁盘连接一次读取到内存,缓冲区满时会再读取下一截数据重新填充到缓冲区
        构造函数:
      // 对输入流进行包装,里面默认的缓冲区是8k
      public BufferedInputStream(InputStream in);

      // 对输入流进行包装,创建具有指定缓冲区大小的 Buffer
      public BufferedInputStream(InputStream in, int size);

      常用方法:
      // 从输入流中读取一个字节
      public int read();

      // 从字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中
      public int read(byte[] buf, int off, int len);

      // 关闭资源,关闭这个流即可, InputStream 会在里面被关闭
      void close();

      BufferOutputStream 缓冲字节输出流,当缓冲区满时,会自动写出到磁盘
      构造同  BufferInputStream 
      常用方法:
      // 向输出流中输出一个字节
      public void write(int b);

      // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入缓冲的输出流
      public void write(byte[] buf, int off, int len);

      // 刷新此缓冲的输出流,强制使所有缓冲的输出字节被写出到底层输出流中,当缓冲区的大小未满时,需要手动刷到磁盘
      public void flush();

      // 关闭释放资源, OutputStream 会在里面被关闭, JDK7 新特性 try (在这里声明的 流 会自动关闭){}
      void close();


      缓冲输入输出流进行文件拷贝:
      try {
        FileInputStream fis = new FileInputStream("C:\Users\79466\Desktop\test\a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream("C:\Users\79466\Desktop\test\copy.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int size;
        byte[] buf = new byte[1024];
        

        while (( size = bis.read(buf)) != -1) {
          // 将字节输出流写到缓冲区里面,等缓冲区满后自动写出
          bos.write(buf, 0, size);
        }
        // 刷新此缓冲区的输出流,才可以保证数据全部输出完成,关闭的时候也会进行刷新,写了也不要紧,也就是多刷一次, close 方法的关闭前会先进行刷新
        // bos.flush();

        // 内部会关掉 InputStream 和 OutputStream  异常处理见下面,此处如果上面出现异常就无法关闭
        bis.close();
        // close 源码里面会有 flush ,可以不用单独调用 flush ,jdk7 之后 close 源码里的 try 里面声明了 OutputStream ,会自动关闭 outputStream 流
        bos.close();
      } catch (Exception e) {
        e.printStackTrace();
      }

      流的关闭顺序,后开的先关,如果A依赖B,先关闭B

      IO 的异常处理:
      大部分公司的做法: 在 finally 里面进行关闭
      catch (Exception e) {
        e.printStackTrace();
      } finally {
        if(bis != null) {
          try {
            bis.close();
          }catch () {
            e.printStackTrace();
          }finally {
            if(bos != null) {
              try {
                bos.close();
              }catch (Exception e) {
                e.printStackTrace();
              }
            }
          }
        }
      }

      jdk7 之后的做法: try-with-resource
      try 里面声明的 OutputStream 和 InputStream 会自动关闭, jdk7 之后的 InputStream 都实现了 AutoCloseable
      在 try 里面定义多个资源,关闭的顺序是最后在 try() 定义的资源最先关闭

      try (
        FileInputStream fis = new FileInputStream("C:\Users\79466\Desktop\test\a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream("C:\Users\79466\Desktop\test\copy.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);)  {

        int size;
        byte[] buf = new byte[1024];

        while(( size = bis.read(buf)) != -1 ) {
          bos.write(buf, 0, size);
        }

        // try 结束后自动调用 close 方法(InputStream 等实现了AutoCloseable),这个动做会早于 finally 里调用的方法,不管是否出现异常 try 里面都会调用 close 方法,close 方法里面会调用 flush 
        // bos.flush();

      } catch (Exception e) {
          e.printStackTrace();
      }

    关于字节:

    字节(Byte简写B):作为一个单位来处理的一个二进制数字串,是构成信息的一个小单位。最常用的字节是八位的字节,即它包含八位的二进制数。1B=8bit,1KB=1024B
    一个英文字母(不分大小写)占一个字节的空间。字节作为一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数。换算为十进制,最小值-128,最大值127。如一个ASCII码就是一个字节
    UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。中文标点占三个字节,英文标点占一个字节
    Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。中文标点占两个字节,英文标点占两个字节
    字符串转换为字节数组:byte[] b = string.getBytes();
    字节转换成字符串:String string = new String(byte[] bytes, Charset charset);
    byte[] b="我是一个兵".getBytes("GBK"); GBK编码的字符串转为字节数组
    需要把string保存到文件中,必须把string转换成一个有序的字节流,以便系统在硬盘上做物理保存。String到字节流的转换涉及到使用何种编码,使用不同的编码得到的字节码不同
    存 byte 的方式要优于存 string

    File 文件上传 feign 调用时 MultipartFile 丢失  

      MultipartFile multipartFile = new MockMultipartFile("file", fileName,ContentType.MULTIPART.toString(), new FileInputStream(file));

      return this.fileUploadFeign.handleFileUpload(multipartFile);

    如果是前端传过来的文件,参数里面会直接是 MultipartFile 上传,本地获取到的文件转成 MultipartFile 的话,需要先构造 MultipartFile ,File 文件也可以上传

  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/moxiaodan/p/13776925.html
Copyright © 2011-2022 走看看