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 文件也可以上传

  • 相关阅读:
    java的几种对象(PO,VO,DAO,BO,POJO)
    建立标准编码规则(四)-C#编码规范分类及实现
    建立标准编码规则(三)-CodeFixProvider 给代码分析器增加修复建议
    建立标准编码规则(二)-DiagnosticAnalyzer 增加诊断分析代码
    建立标准编码规则(一)-自定义C#代码分析器
    领域模型与微服务
    asp.net core 中使用StyleCop.StyleCopAnalyzers
    asp.net core中使用HttpClient实现Post和Get的同步异步方法
    asp.net core 如何集成kindeditor并实现图片上传功能
    一名前端Web架构师的成长之路(转载)
  • 原文地址:https://www.cnblogs.com/moxiaodan/p/13776925.html
Copyright © 2011-2022 走看看