欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java文件处理io流

程序员文章站 2022-03-09 21:39:21
...

java文件处理io流

File 文件操作

方法 简介
boolean exists() 判断文件和目录是否存在
boolean isFile() 判断是否是文件
boolean isDirectory() 判断是否是目录
String getPath() 返回当前路径
String getAbsolutePath() 返回此对象的绝对路径
String getName 返回文件名称
String getParent() 返回路径的上一个层路径
long length 返回文件的长度,单位为 字节1024=1KB
String[] list(); 查看当前目录下第一层的所有文件和文件夹名称 返回数组
File[] listFile(); 返回当前目录下第一层所有文件和文件夹的File数组对象
CreateNewFile() 创建文件,
mkdir() 创建目录只能创建一层
mkdirs() 创建多层目录
delete() 删除文件或者文件夹 删除的文件夹必须是空的一次只能删除一层
lastModified() 获取文件最后创建时间
canRead() 获取文件是否可读
canWrite() 获取文件是否可写

演示代码

File f=new File("path");
if (f.exists()) {
    System.out.println(f.getName() + "的属性如下: 文件长度为:" + f.length()+"字节");
    System.out.println(f.isFile() ? "是文件" : "不是文件");
    System.out.println(f.isDirectory() ? "是目录" : "不是目录");
    System.out.println(f.canRead() ? "可读取" : "不");
    System.out.println(f.isHidden() ? "是隐藏文件" : "不是隐藏文件");
    System.out.println("文件夹的最后修改日期为:" + new Date(f.lastModified()));
} else {
    System.out.println(f.getName() + "的属性如下:");
    System.out.println(f.isFile() ? "是文件" : "不是文件");
    System.out.println(f.isDirectory() ? "是目录" : "不是目录");
    System.out.println(f.canRead() ? "可读取" : "不");
    System.out.println(f.canWrite() ? "是可写" : "不");
    System.out.println("文件的最后修改日期为:" + new Date(f.lastModified()));
}

获取各种路径

在java中自己写路径的时候 一定要用下面这代码 否则就会 和linux 系统的路径符 发送冲突 导致找不到路径 或者资源 反正只要让你 写 / 或者 \ 那么 都使用 File.separator

// 系统目录中的间隔符  如:\    自动根据系统适配 
System.out.println(File.separator);  

以下获取路径的方法 随着你的环境的不同 路径也会有所变化最好是自己测试过了没问题在使用

//获取classes路径这个路径一般都是java文件和配置文件 打包后存放的地方     如果在服务里那么一般都是在WEB-INF 下第一层
当前类名.class.getResource("/").getPath().substring(1);
  
 //Springboot获取打包扣后的classes:路径
 String path = ResourceUtils.getURL("classpath:").getPath();

如果想要获取到在服务器端项目的根路径那么  可以这样
 new File(new File(当前类名.class.getResource("/").getPath()).getParent()).getParent()       
        
        
	System.getProperty("user.dir") (会变化的)
    在不在服务器中 那么就是当前项目的根路径       
    如果在服务器Tomcat中是bin目录
将多个路径整合Paths.get()   自动适配 路径符 
        String pat1="C:\\Users\\";
 		 String pat="/aaaa/aaa/a";
        String string = Paths.get(pat1, pat).toString();
        System.out.println(string);
        //C:\Users\aaaa\aaa\a

此方式 适用于 指定文件上传

	//将文件存入当前服务器里
          String filePath = request.getSession().getServletContext().getRealPath(File.separator)+File.separator+"uploadxu"+File.separator;
            File file=new File(filePath);
            if(!file.exists()){
                file.mkdirs();
            }

在Servlet 或者js中

       
		request.getContextPath(); //获取虚拟目录没有那么就是空 而不是null

		//常用
        String ap = request.getServletContext().getRealPath("/");
        System.out.println("项目在服务器里的根路径" + ap);

        //http://localhost:8080/user/path_test
        System.out.println("得到url全地址栏" + request.getRequestURL());


        String ap = request.getServletContext().getRealPath("src/main/java/cn/xh/web/UserController.java");
        System.out.println("将参数路径和当前服务下的项目根目录拼接" + ap);
        String path = request.getContextPath();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
   System.out.println("获取服务器根路径 比如:http://localhost:8080/"+basePath);

在jsp页面里

${pageContext.request.contextPath}      获取当前项目的根目录   这样能确保在不同环境下 路径不会错误

<script src="${pageContext.request.contextPath }/statics/localjs/rollpage.js"></script>

创建目录

“mkdir():只能创建一层目录. mkdirs(): 可以创建多层目录”

File myFolderPath = new File("pathdir");
try {
    if (!myFolderPath.exists()) {
        myFolderPath.mkdir();
    }
}
catch (Exception e) {
    System.out.println("新建目录操作出错");
    e.printStackTrace();
}

创建文件

File myFilePath = new File("path_file");
try {
    if (!myFilePath.exists()) {
        myFilePath.createNewFile();
    }
}
catch (Exception e) {
    System.out.println("新建文件操作出错");
    e.printStackTrace();
}

判断文件或文件夹是否存在

都是使用 exists()
比如文件是否存在: c:xxxx/xx/a.txt
比如目录是否存在: c:xxxx/xx/


File str1 = new File("path");
if (str1.exists()) {
    System.out.println("存在");
}

判断是文件还是文件夹

	File str1=new File("path");
    if(str1.isFile()){
        System.out.println("是文件");
    }
    if(str1.isDirectory()){
        System.out.println("是目录");
    }

判断是否是绝对路径

  public  static boolean isAbsolute( String file){
      File file1=new File(file);
      return file1.isAbsolute();
  }

判断是否是隐藏文件

也就是是文件名是.开头的 或者是手动将文件设置为隐藏文件

那么他就是隐藏文件

  public static boolean isHidden( String file){
      File file1=new File(file);
      return file1.isHidden();
  }

通过相对路径返回绝对路径

    public static String[]  path( String file){
        String string = Paths.get(System.getProperty("user.dir")+File.separator + file).toString();
        File file1=new File(string);
        String[] str={string,String.valueOf(file1.exists())};
        return str;
    }

    public static void main(String[] args) {
        String path= "src/main/test/bv/_decode_.txt";
        String[] path2 = path(path);
        System.out.println("拼接后的绝对路径"+path2[0]);
        System.out.println("路径是否存在"+path2[1]);
    }

删除空文件夹

如果要删除的文件夹不是空的那么 就删除不了

  public static boolean der_empty(String path){
        File delFolderPath = new File(path);
        try {
            if ( delFolderPath.delete()){ //删除空文件夹
                System.out.println("删除文件夹成功");
                return true;
            }else{

                    System.gc();    //回收资源
                    if (delFolderPath.delete()){
                        System.out.println("强制删除文件夹成功");
                        return true;
                    }
                System.out.println("删除文件夹失败 文件夹内有 东西 清空后在 删除");
                    return  false;
             }
       }catch (Exception e) {
            System.out.println("删除文件夹操作出错");
            e.printStackTrace();
            return false;
        }
    }

删除整个文件夹件或清空

包括文件夹下的子文件夹以及文件 全部删除

     public  static boolean der(String path){
        File delfile = new File(path);
        try {
            File[] files=delfile.listFiles();
            for(int i=0;i<files.length;i++){
                if (files[i].isDirectory()){
                    der(files[i].getPath());
                }
                boolean result=files[i].delete();
                if (result){
                    System.out.println("删除成功");
                }
                //如果文件被java占用 导致无法删除 使用强制删除
                if (!result) {
                    System.gc();    //回收资源
                    if (files[i].delete()){
                        System.out.println("强制删除成功");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        //将文件夹也 一起删除        如果只是清空 的话那么 把这一句注释
        delfile.delete();
        return true;
    }

提取文件后缀

不加点 比如 txt js png

  public static String   suffix( String file){
      File str1=new File(file);
//提取扩展名
      String str2=str1.getPath().substring(str1.getPath().lastIndexOf(".")+1);
       return str2;
  }

文件/文件夹 重命名(移动)(复制)

重命名 文件

//想命名的原文件的路径
        File file = new File("src/main/test/bv/a.txt");
//获取源文件路径 不带文件名
      String rootPath = file.getParent();
//拼接成新的路径(重命名)
        String fileName=rootPath + File.separator + "_decode_.txt";
        System.out.println(fileName);
//将原文件更改为  fileName
        file.renameTo(new File( fileName));

重命名文件夹

  //想命名的原文件夹的路径
  File file1 = new File("f:/A");
  //将原文件夹更改为B,   
  file1.renameTo(new File("f:/B"));

移动文件夹

     //原文件路径
             String yuan_path="src\\main\\test\\a.txt";
     //移动到 的地方 以及 移动后文件名
             String xian_path="src\\main\\test\\bv\\a.txt";
             File file = new File(yuan_path);
             file.renameTo(new File(xian_path));
     //移动完成后会自动删除原文件

复制文件

  public static void copyfile(String oldPath,String newPaht ){

      if (!new File(oldPath).exists()){
        System.out.println("文件路径不存在");
          return;
      }
  
      if (new File(oldPath).isFile()) {
          try (
                  FileInputStream fis1=new FileInputStream(oldPath);
                  BufferedInputStream fis=new  BufferedInputStream(fis1);
                  FileOutputStream fos1=new FileOutputStream(newPaht);
                  BufferedOutputStream fos=new BufferedOutputStream(fos1);
          ){
  
              byte[] data = new byte[4096];
              int num;
              while ((num = fis.read(data)) != -1) {
                  fos.write(data, 0, num);//写入数据
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
      }else{
          System.out.println("这不是文件类型 ");
      }
  }
  @Test
  public void main() {
      //原文件
      String oldPath = "path";
      //移动的地方  目标不存在会自动创建
      String newPaht = "path";
      copyfile(oldPath,newPaht);
  }
  

移动文件夹或者复制文件夹

    // 删除某个目录及目录下的所有子目录和文件
    public static boolean deleteDir(File dir) {
        // 如果是文件夹
        if (dir.isDirectory()) {
            // 则读出该文件夹下的的所有文件
            String[] children = dir.list();
            // 递归删除目录中的子目录下
            for (int i = 0; i < children.length; i++) {
                // File f=new File(String parent ,String child)
                // parent抽象路径名用于表示目录,child 路径名字符串用于表示目录或文件。
                // 连起来刚好是文件路径
                boolean isDelete = deleteDir(new File(dir, children[i]));
                // 如果删完了,没东西删,isDelete==false的时候,则跳出此时递归
                if (!isDelete) {
                    return false;
                }
            }
        }
        // 读到的是一个文件或者是一个空目录,则可以直接删除
        return dir.delete();
    }

    // 复制某个目录及目录下的所有子目录和文件到新文件夹
    public static void copyFolder(String oldPath, String newPath) {
        try {
           // 如果文件夹不存在,则建立新文件夹
            File f=   new File(newPath);
            if ( !f.exists()){
                f.mkdirs();
            }
            // 读取整个文件夹的内容到file字符串数组,下面设置一个游标i,不停地向下移开始读这个数组
            File filelist = new File(oldPath);
            String[] file = filelist.list();
            // 要注意,这个temp仅仅是一个临时文件指针
            // 整个程序并没有创建临时文件
            File temp = null;
            for (int i = 0; i < file.length; i++) {
                // 如果oldPath以路径分隔符/或者\结尾,那么则oldPath/文件名就可以了
                // 否则要自己oldPath后面补个路径分隔符再加文件名
                // 谁知道你传递过来的参数是f:/a还是f:/a/啊?
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file[i]);
                } else {
                    temp = new File(oldPath + File.separator + file[i]);
                }

                // 如果遇到文件
                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    // 复制并且改名
                    FileOutputStream output = new FileOutputStream(newPath
                            + File.separator+ (temp.getName()).toString());
                    byte[] bufferarray = new byte[1024 * 64];
                    int prereadlength;
                    while ((prereadlength = input.read(bufferarray)) != -1) {
                        output.write(bufferarray, 0, prereadlength);
                    }
                    output.flush();
                    output.close();
                    input.close();
                }
                // 如果遇到文件夹
                if (temp.isDirectory()) {
                    copyFolder(oldPath + File.separator + file[i], newPath + File.separator + file[i]);
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println("复制整个文件夹内容操作出错");
            new File(newPath).delete();
        }
    }

    public static void moveFolder(String oldPath, String newPath,boolean del) {
        // 先复制文件
        copyFolder(oldPath, newPath);

        // 则删除源文件,以免复制的时候错乱
        if (del){
            deleteDir(new File(oldPath));
        }
    }

    public static void main(String[] args) {
        //原文件
        String oldPath = "src/main/test/bv1";
        //移动的地方 如果文件夹存在那么 就将内容传过去 如果文件夹不存在 那么就先创建文件夹 在将内容传递
        String newPaht = "src/main/test/bv";

        //第三个参数是 是否 删除原文件    如果为true 那么就是移动文件 如果是false那么就是将文件复制到指定地方 原文件保留   如果路径不存在 会自动创建
        moveFolder(oldPath, newPaht,false);
    }

文件随机名称28-34位

public static String Name_tuP(){
    char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    char[] Ch={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
    Calendar cal = Calendar.getInstance();
    Random sun=new Random();

    int num1=sun.nextInt(1000);//0-1000随机数
    StringBuilder time=new StringBuilder();
    time.append(num1+"-");//随机数
    time.append(cal.get(Calendar.YEAR)); //年
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]);
    time.append(cal.get(Calendar.MONTH) + 1);//月
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]);
    time.append(cal.get(Calendar.DAY_OF_MONTH));//日
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]);
    time.append(cal.get(Calendar.HOUR_OF_DAY));//时
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]);
    time.append(cal.get(Calendar.MINUTE));//分
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]);
    time.append(cal.get(Calendar.SECOND));//秒
    time.append(ch[sun.nextInt(ch.length)]);
    time.append(Ch[sun.nextInt(ch.length)]+"-");
    int num=sun.nextInt(1000);//0-1000随机数
    time.append(num);//随机数
    return time.toString();
}

类似于 这种格式 : 833-2020mR6pK7sN17zT54zE56aH-229

2020年 6月 7日 17点 54 分 56 秒

获取文件和文件夹和进行排序功能

是否包含子文件 可以进行控制

排序 可以进行控制

缺点就是不能直接对 盘符进行 扫描 比如C:\ 或者F:\ 只能针对某个文件夹

package org.app.test;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Dir_File_List {

    private List<File>   folder_list=new ArrayList<>();//文件夹
    private List<File> file_list=new ArrayList<>();//文件

    //排序  规则
    //文件夹 按照名称 排序 从短到长
    private   boolean dir_name=false;
    //文件夹 按照大小 排序 从小到大
    private  boolean dir_size=false;
    //文件夹创建时间  排序  从 最近到最远
    private  boolean dir_time=true;

    //文件 按照名称  排序 从短到长
    private  boolean  file_name=false;
    //文件 按照大小  排序 从小到大
    private   boolean file_size=false;
    //文件创建时间  排序  从 最近到最远
    private  boolean file_time=true;

    //可以同时多开 排序规则  不会冲突

    
    // 是否判 包括子文件
    Boolean  pddirZi=true;





    public  void  pathFile(String path){
        File file=new File(path);
        if (!file.exists()){
            System.out.println("找不到路径");
            return;
        }
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()){
                folder_list.add(file1);
                if(pddirZi){
                    pathFile(file1.getPath());
                }

            }
            if (file1.isFile()){
                file_list.add(file1);
            }
        }


    }

    public  void  compare_lis() {
        if (dir_name) {
            //文件夹按文件名称的长度 显示的顺序:  从短到 长
            Collections.sort(folder_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (o11.getName().length() - o22.getName().length());
                }

            });

        }

        if (file_name) {
            //按文件名称的长度 显示的顺序:  从短到 长
            Collections.sort(file_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (o11.getName().length() - o22.getName().length());
                }

            });

        }


        if (dir_size) {
            //按照文件夹大小 再次排序  最大的文件 放在最后
            Collections.sort(folder_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (int) (o11.length() - o22.length());
                }
            });
        }


        if (file_size) {
            //按照文件大小 再次排序  最大的文件 放在最后
            Collections.sort(file_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (int) (o11.length() - o22.length());
                }
            });
        }
        if (dir_time) {
            //然后文件夹创建时间 排序 从近到远
            Collections.sort(folder_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (int) ( o22.lastModified()-o11.lastModified());
                }
            });
        }

        if(file_time){
            //然后文件大小 再次排序  最大的文件 放在最后
            Collections.sort(file_list, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    File o11 = (File) o1;
                    File o22 = (File) o2;
                    return (int) ( o22.lastModified()-o11.lastModified());
                }
            });
        }





    }


    public void dir_file_list(String path,boolean px){
        pathFile(path);
        if (px){
            compare_lis();//排序
        }
    }

    public List<File> getFolder_list() {
        return folder_list;
    }
    public List<File> getFile_list() {
        return file_list;
    }

    public Dir_File_List() {
    }

    /**
     *
     * @param dir_name   文件夹名称排序
     * @param dir_size   文件夹大小
     * @param dir_time  文件夹创建时间
     * @param file_name  文件名称排序
     * @param file_size  文件大小
     * @param file_time   文件创建时间
     */
    public Dir_File_List(boolean dir_name, boolean dir_size, boolean dir_time, boolean file_name, boolean file_size, boolean file_time) {
        this.dir_name = dir_name;
        this.dir_size = dir_size;
        this.dir_time = dir_time;
        this.file_name = file_name;
        this.file_size = file_size;
        this.file_time = file_time;
    }

    //查看C盘中指定路径下所有的文件和文件夹名称,并且指定排序规则进行排序
    public static void main(String[] args) {
        Dir_File_List list=new Dir_File_List();
        String path = "C:\\Users\\12841\\Desktop\\Docker";
        //如何 排序 自己根据构造来 修改
        boolean px=false; //开启排序
        list.dir_file_list(path,px);
        System.out.println("所有的文件夹" + list.getFolder_list()); //排序规则:  创建时间  排序  从 最近到最远
        System.out.println("所有的文件" + list.getFile_list()); //排序规则了:   创建时间  排序  从 最近到最远

    }
}

获取当前时间和文件创建时间差

   /**
     *计算 当前时间和 文件创建时间 差
     * @param file  传入的文件
     * @param num   1.选择时间差毫秒  2.选择时间差天数
     * @return  返回时间差
     */
public long dateFile(String file,int num){
        File file1=new File(file);
    long nd = 1000 * 24 * 60 * 60;
    long  diff=new Date().getTime() - new Date(file1.lastModified()).getTime();
    switch (num){
        case 1:
            // 获得两个时间的毫秒时间差异
            return  diff;
        case 2:
            return diff / nd;
        default:
            return  diff;
    }
}

    @Test
    public  void show()  {
        String path="文件";
        long l = dateFile(path, 2);
        System.out.println(l);
    }

文件读写 (字节流)

每次最少读取8bit 1字节

在写入数据的时候 如果没有在此路径找到 此文件 就会创建一个新文件

有两种 添加 数据 一种 覆盖 一种 追加

覆盖 不加 true , 追加 路径后加true

new FileOutputStream( "path", true) //追加方式

无需关闭流 因为写在try( )内 会自动关闭

自己根据情况 进行 拆分代码 注意使用字节流不要读取过程中进行操作那样会出现 乱码 因为是二进制 所以一次性全部读完后在操作

long startTime = System.currentTimeMillis();
try (FileInputStream fis1=new FileInputStream(path_读);
     BufferedInputStream fis=new  BufferedInputStream(fis1);
     FileOutputStream fos1=new FileOutputStream(path_写);
     BufferedOutputStream fos=new BufferedOutputStream(fos1);
){
    byte[] data=new byte[4096];
    int len;
    while( (len=fis.read(data) )!= -1) {
        fos.write(data,0,len);//写入数据
    }
} catch (IOException e) {
    e.printStackTrace();
    return;
}
long endTime = System.currentTimeMillis();
 System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

文件读写 (字符流)

比字符流慢10倍最少 文件越大差距越大

每次最少读取16bit 2字节

字符流读取文本没有任何限制 可以读取中文

在写入数据的时候 如果没有在此路径找到 此文件 就会创建一个新文件

覆盖 不加 true 追加在 路径后加true

new FileOutputStream(path,true) //追加

追加的话 最好在写入内容 前加一个\n

无需关闭流 因为写在try( )内 会自动关闭

按行读取 (使用的最多)

long startTime = System.currentTimeMillis();
try (
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("path"))));

) {

    String lin = br.readLine();
    while (lin != null) {
        System.out.println(lin);
        lin = br.readLine();
    }
} catch (Exception e) {
    e.printStackTrace();
}
long endTime = System.currentTimeMillis();
 System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

将内容追加到文件中

 		long startTime = System.currentTimeMillis();
        try(

                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
                 new FileOutputStream(new File("path"),true)));
        ) {
                bw.newLine();
                bw.write("哈哈哈哈哈哈asd");
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

字符流 行读写的缓存

  long startTime = System.currentTimeMillis();
        try (
                BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("path"))));
                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("path"))));
        ) {
            StringBuilder builder=new StringBuilder(1024*1024);
            int sizelen=0;
            String lin = br.readLine();
            while (lin != null) {
              	builder.append(lin);
                if(sizelen==20){  //每20行 写入一次    
                    bw.write(builder.toString());
                    sizelen=0;
                     builder=new StringBuilder(1024*1024);//清空缓冲区
                }
                sizelen++;
                lin = br.readLine();
            }
            //将余下 的内容全部写入
           	bw.write(builder.toString());
            builder=new  StringBuilder();
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

字符流 字节缓存读写

        long startTime = System.currentTimeMillis();
        try(
                BufferedReader   br = new BufferedReader(new InputStreamReader(new FileInputStream(
                        new File("path_读"))));
                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(new File("path_写"))));
        ) {

            char[] c = new char[4096];
            int len = 0;
            while ((len = br.read(c)) != -1) {
                bw.write(c, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

编码转换

按照指定编码读取出来 和按照指定编码写入

就拿IDEA来说 正常情况IDEA编码格式是UTF-8而Windows 的文件 有可能是GBK 或者其他 编码 这时候就会出现问题

读取出来的数据 就会乱码 因为IDEA还是按照默认的UTF-8来读取的

解决办法: 我们就需要给他指定读取的编码

BufferedReader   br = new BufferedReader(new InputStreamReader(new FileInputStream(
        new File("path")),"UTF-8"));

这里的UTF-8是文件的编码 如果你的文件是GBK这里就要换成GBK

既然读能指定编码那么我们 写是不是也可以指定编码

BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(new File("path")),"GBK"));

将内存中的内容 转换成 GBK编码格式 写入到文件中

案例 :

        long startTime = System.currentTimeMillis();
        try(
                BufferedReader   br = new BufferedReader(new InputStreamReader(new FileInputStream(
                        new File("path")),"UTF-8"));
                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(new File("path")),"GBK"));
        ) {

            char[] c = new char[4096];
            int len = 0;
            while ((len = br.read(c)) != -1) {
                bw.write(c, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("花费时间为:" + (double)(endTime - startTime)/1000+"秒");

解析: 源文件比如是UTF-8 那么我指定读取编码就是UTF-8 否则读取的内容乱码

目标文件的编码格式是GBK 那么要写入的内容就需要转换成GBK 否则写入的内容乱码

将对象序列化 和反序列化

注意 static 变量 和 被 transient修饰的变量 不能序列化 结果为默认值

Java的序列化机制只序列化对象的属性值,而不会去序列化什么所谓的方法。其实这个问题简单思考一下就可以搞清楚,方法是不带状态的,就是一些指令,指令是不需要序列化的

父类未继承Serializable,子类实现了,序列化子类实例的时候,父类的属性是直接被跳过,值不保存

还有就是 如果序列化类中成员属性是引用类型 并且被赋值了 就比如 public Object obj=new Object(); 那么 Object类必须继承Serializable 或者将 这个变量添加transient修饰 否则序列化报错 NotSerializableException

如果没法继承的Serializable类 比如 Object这个类 是java本身自带的类我们没法操作 那么 可以通过transient修饰 来跳过这个成员变量

抽象类不能被直接序列化 需要通过子类序列化 但是抽象类必须继承Serializable 否则子类无法序列化抽象父类的值 到子类中

  1. 先创建一个对象
import java.io.Serializable;
//必须使用Serializable 序列化 也就是二进制 否则无法读取对象  
public class user implements Serializable {
    private   String name;
    private  int  age;
    public user(String name,int age){

        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "user [name=" + name + ", age=" + age + "]";
    }


}

  1. 使用对象流读写
 //  传入 要写入的对象      ,   写入的文件路径
    public   static  void Obj_file_w(Object object,String path){
        try(
                //写
                ObjectOutputStream  objectOutputStream=new ObjectOutputStream(new FileOutputStream(path));
        ){

        //将对象写入到文本
            objectOutputStream.writeObject(object);



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

        //读取 对象文件 的路径
    public  static  Object Obj_file_r(String path){
        try(
                //读
                ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(path));
        ){
            //将对象内容从文本中读取出来
           return objectInputStream.readObject();
        }catch (Exception e) {
            e.printStackTrace();
            return  null;
        }
    }

测试

    @Test
    public void du(){
        //写入对象
        user user=new user("胡", 13);
        Obj_file_w(user,"a.txt");
    }

    @Test
    public void xie(){
        //  读取对象
        user obj=(user)Obj_file_r("a.txt");
        System.out.println(obj.getName());//胡

    }

如果在 反序列化 之前将 源文件修改了 那么就会出现 java.io.InvalidClassException …这个错误 内容大致就是 serialVersionUID不同

解决办法:

反序列化是必须有该对象的class文件,现在问题是随着项目的升级,系统的class文件也会跟着升级,java如果保证两个class的兼容性?

  • java序列化机制允许为序列化的类提供一个private static final 的serialVersionUID值,该类的变量用于表示java类的序列化版本。也就是说,当一个类升级后,只要该类变量的值没有修改,序列化机制也会把他们当作为同一个序列化版本。
  • 在每个要序列化的类中加入private static final long serialVersionUID=111L ,值可以任意 。这样该类被修改了,该对象也能被序列化.

序列化对象集合

调用上面 案例中的Obj_file_w 和 Obj_file_r 方法

    //序列化 和反序列化 集合对象
    @Test
    public void  list(){

        List<user> list=new ArrayList<>();
        list.add(new user("胡1", 13));
        list.add(new user("胡2", 14));
        list.add(new user("胡3", 15));
        Obj_file_w(list,"a.txt");
    }
    @Test
    public void  list1(){
        List<user> list = (List<user>) Obj_file_r("a.txt");
        System.out.println(list);
    }

单个文件下载

  @GetMapping(value = "/down")
    public void  download(String fileName, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File("C:\\Users\\12841\\IdeaProjects\\FastDFS\\target\\classes\\"+fileName);
            // 取得文件名。
            String filename = file.getName();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
      
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

下载网络文件

    @GetMapping(value = "/down")
    public void downloadNet(String urlpath ,HttpServletResponse response) throws MalformedURLException {

        URL url = new URL("https://pic.cnblogs.com/avatar/463242/20190215125753.png");
        try {
            DataInputStream dataInputStream = new DataInputStream(url.openStream());
            ByteArrayOutputStream output = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];
            int length;

            while ((length = dataInputStream.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            byte[] context=output.toByteArray();

            String file = url.getFile();
            file= file.substring(file.lastIndexOf("/") + 1, file.length());
            // 设置response的Header
            String filenamedisplay = URLEncoder.encode( file,"UTF-8"); //将文件名进行转义 防止中文名称不显示导致文件错误
            response.addHeader("Content-Disposition","attachment;filename=" + filenamedisplay);//展示给用户的

            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(context);

            outputStream.close();
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

批量下载

原理就是 读取本地多个文件然后 将文件添加到压缩包里 通过网络将压缩包下载下来

@GetMapping(value = "/downss")
    public void downloadZipFile( String[] namefiles ,HttpServletResponse response) throws IOException {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        String path = "C:\\Users\\12841\\IdeaProjects\\FastDFS\\target\\classes\\";

        for (int i = 0; i < namefiles.length; i++) {
            FileInputStream in = new FileInputStream(String.valueOf(Paths.get(path,namefiles[i])));
            byte[] bytes1 = new byte[8192];  //读取到的文件 byte
            zip.putNextEntry(new ZipEntry( i+namefiles[i]));
            int len;
            while ((len = in.read(bytes1)) != -1){
                IOUtils.write(bytes1, zip);
            }
            zip.closeEntry();
        }
        IOUtils.closeQuietly(zip);
        byte[] data = outputStream.toByteArray();

        response.reset();
        response.setContentType("application/octet-stream; charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="+ new String(("test" + ".zip").getBytes(), "UTF-8"));

        IOUtils.write(data, response.getOutputStream());
    }

网页文件上传

实现文件上传 涉及到对文件的读写操作 实现起来需要编写大量的 代码 并容易引发异常

幸运的是 目前有很多非常实用的文件上传工具 可以帮助我们实现文件上传的功能

其中应用比较多的是Commons-FileUpload组件 实用该组件可以极大的简化开发人员的编码工作量

Commons-FileUpload组件 介绍

能够全程控制上传的内容 Commons-FileUpload组件 提供了对象及操作方法

可以获得全部上传文件的信息 包括文件名称 类型 大小 等 方便操作

能够对上传文件的大小 类型进行控制 为了避免在上传过程中出现异常数据 在

Commons-FileUpload组件中 专门提供了 相应的方法用于对上传文件进行控制

使用Commons-FileUpload组件需要的maven:

   <dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.3.1</version>

  </dependency>



  <dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.4</version>

  </dependency>

文件上传案例:

上传页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

<form action="doupload.jsp" enctype="multipart/form-data" method="post">
    <p>姓名 <input type="text" name="user"> </p>
    <p>选择图片 <input type="file" name="nfile"></p>
    <p> <input type="submit" value="提交"></p>
</form>

<script src="jquery-3.4.1.js" type="text/javascript"></script>



  </body>
</html>

处理页面jsp , 使用Servlet也行

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.io.File" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Arrays" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%

request.setCharacterEncoding("utf-8");
String  uploadFileName="";//上传文件的文件(名称.后缀)
    List<String> fileType= Arrays.asList("gif","bmp","jpg","png","mp4","docx","txt");  //指定上传文件类型
    //请求信息中的内容是否是multipart/form-data类型
    boolean isMultipart= ServletFileUpload.isMultipartContent(request);
    //客户端将文件存储在服务器的路径  upload/ 下面 (服务器 上的绝对文件夹路径)
    String uploadFilePath=request.getSession().getServletContext().getRealPath("upload/");
    //out.print(uploadFilePath);   可以查看储存的路径
    if(isMultipart){  //判断
        FileItemFactory factory=new DiskFileItemFactory();
        ServletFileUpload upload=new ServletFileUpload(factory);

        try {
            //解析form表单所有文件
            List<FileItem> items=upload.parseRequest(request);
            Iterator<FileItem> iter=items.iterator();   //集合迭代器
            while(iter.hasNext()){    //依次处理每个文件
                FileItem item=(FileItem) iter.next();
                if (item.isFormField()){  //普通表单字段   比如 text  password 等  除了 file表单
                    String fieldName =item.getFieldName();//读取表单字段的name属性
                    if (fieldName.equals("user"));
                    {           //输出表单字段的值  (value)
                        out.print(item.getString("UTF-8")+"上传了文件.<br/>");

                    }
                }else{  //file文件表单字段
                 String file_Name=item.getName();//获取文件名称
            //获取文件名称的后缀  列如 jpg  bng 等
 String ext=file_Name.substring(file_Name.lastIndexOf(".")+1);
        if(!fileType.contains(ext)){   //判断文件后缀 是否符合fileType集合中的某个类型
   out.print("文件上传失败目前只支持gif,bmp,jpg,png,docx,text,mp4");
                    }else {
                        String fileName = item.getName();  //获取表单文件上传的 文件名
                        if (fileName != null && !fileName.equals("")) { //判断是否是空  如果 是空就代表用户没有上传
                            //在服务器内创建一个uploadFilePath路径下的item.getName()的空文件
                            File saveFile = new File(uploadFilePath, item.getName());
                            //item(file)是客户端表单的引用(使用的是multipart/form-data类型提交的内容 是二进制)
                            // 将客户端文件(file表单内容) 写入 服务器指定的 upload 文件夹中item.getName()文件内
                            item.write(saveFile);
                            uploadFileName = item.getName();//获取文件上传的 文件名
                            out.print("上传成功后的文件名是:" + uploadFileName + "字节数是:" + item.getSize() + "(byte)");

                        }
                    }
                }

                }


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


    }


%>

</body>
</html>


				

进阶版 控制文件的 上传大小 以及 上传文件缓存(临时文件)

缓存:

正常的情况是 我上传一个字节 服务器读一个字节然后立马写入到本地 这样非常耗时

设置缓存,就是当文件大小超过你设置的值 那么就不直接写入服务器本地硬盘中 而是先保存在内存中当读取完毕后在一次性写入 ,这样的好处就是 加快了上传的速度

如果开启缓存 那么就尽量设置临时文件 当然你也可以不设置 你对上传的大小进行限制就行了

临时文件:

看到临时文件 有人就蒙了 干嘛的?

文件上传是先将文件上传到服务内存中然后在读取到本地硬盘的

比如你服务器的内存是4g 我上传的文件大小是5g 那么你内存肯定装不下 崩了

为了解决这样的问题就需要临时文件来分批读取 先读取 三分一 然后保存到本地临时文件里 然后在读取…

当文件读取完后 将临时文件整合 这样就可以 不用担心蹦了

上传页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

<form action="doupload.jsp" enctype="multipart/form-data" method="post">
    <p>姓名 <input type="text" name="user"> </p>
    <p>选择图片 <input type="file" name="nfile"></p>
    <p> <input type="submit" value="提交"></p>
</form>

<script src="jquery-3.4.1.js" type="text/javascript"></script>



  </body>
</html>



			

jsp处理页面


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.io.File" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Arrays" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%

request.setCharacterEncoding("utf-8");
String  uploadFileName="";//上传文件的文件(名称.后缀)
    List<String> fileType= Arrays.asList("gif","bmp","jpg","png","docx","txt");  //指定上传文件类型
    //请求信息中的内容是否是multipart/form-data类型
    boolean isMultipart= ServletFileUpload.isMultipartContent(request);
    //客户端将文件存储在服务器的路径  upload/ 下面 (服务器 上的绝对文件夹路径)
    String uploadFilePath=request.getSession().getServletContext().getRealPath("upload/");
    //out.print(uploadFilePath);   可以查看储存的路径

    //创建临时文件目录
    File  tempPatechFile=new File("E:\\apache-tomcat-8.0.53\\temp\\buffer\\");
    if(!tempPatechFile.exists()){  //判断有没有此目录如果没有就创建
                tempPatechFile.mkdirs();//创建指定目录
    }
    if(isMultipart){  //判断表单提交的类型multipart/form-data
       DiskFileItemFactory factory=new DiskFileItemFactory();
       // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
        //也就是如果文件 超过缓冲区这个值 就会把文件读取进缓冲区里如果文件不超过这个大小那么直接写入本地
       factory.setSizeThreshold(9192); //设置缓冲区为9kb   也就是9192字节byte
        //设置上传文件用到临时文件存放路径
        factory.setRepository(tempPatechFile);
        ServletFileUpload upload=new ServletFileUpload(factory);
        //设置上传单个文件的大小的最大值,1024*1024字节,也就是1MB
        //超过这个值就会出现 异常 终止上传
        upload.setFileSizeMax(1024 * 1024*5);  //设置单个文件最大上传5mb
        //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
        // 超过这个值就会出现连接被重置   所以一般不要设置  用户体验差
        //upload.setSizeMax(1024 * 1024 * 10);   //10mb
        try {
            //解析form表单所有文件
            List<FileItem> items=upload.parseRequest(request);
            Iterator<FileItem> iter=items.iterator();   //集合迭代器
            while(iter.hasNext()){    //依次处理每个文件
                FileItem item=(FileItem) iter.next();
                if (item.isFormField()){  //普通表单字段   比如 text  password 等  除了 file表单
                    String fieldName =item.getFieldName();//读取表单字段的name属性
                    if (fieldName.equals("user"));
                    {           //输出表单字段的值  (value)
                        out.print(item.getString("UTF-8")+"上传了文件.<br/>");

                    }
                }else{  //file文件表单字段
                    String file_Name=item.getName();//获取文件名称
                    //获取文件名称的后缀  列如 jpg  bng 等
  String ext=file_Name.substring(file_Name.lastIndexOf(".")+1);
                    if(!fileType.contains(ext)){   //判断文件后缀 是否符合fileType集合中的某个类型
                        out.print("文件上传失败目前只支持gif,bmp,jpg,png,docx,txt");
                    }else {
                        String fileName = item.getName();  //获取表单文件上传的 文件名
                        if (fileName != null && !fileName.equals("")) { //判断是否是空  如果 是空就代表用户没有上传
                            //在服务器内创建一个uploadFilePath路径下的item.getName()的空文件
                            File saveFile = new File(uploadFilePath, item.getName());
                            //item(file)是客户端表单的引用(使用的是multipart/form-data类型提交的内容 是二进制)
                            // 将客户端文件(file表单内容) 写入 服务器指定的 upload 文件夹中item.getName()文件内
                            item.write(saveFile);
                            uploadFileName = item.getName();//获取文件上传的 文件名
                            out.print("上传成功后的文件名是:" + uploadFileName + "字节数是:" + item.getSize() + "(byte)");

                        }
                    }
                }
                }
        }catch (Exception e){
            e.printStackTrace();
            out.print("上传文件失败 ,文件太大了  , 单个文件最大上限是:"+upload.getFileSizeMax());
        }
    }
%>

</body>
</html>


压缩zip

package A;

import org.junit.Test;

import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
 * ZipUtils
 * @author GDL
 * @date 2017年11月20日
 * @version v1.0
 */
public class ZipUtils {
    private static final int BUFFER_SIZE = 2 * 1024;
    /**
     * 压缩成ZIP 方法1
     * @param srcDir 压缩文件夹路径
     * @param out 压缩文件输出流
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     * false:所有文件跑到压缩包根目录***意:不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
            throws RuntimeException{
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null ;
        try {
            zos = new ZipOutputStream(out);
            File sourceFile = new File(srcDir);
            compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
            long end = System.currentTimeMillis();
            System.out.println("压缩完成,耗时:" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils",e);
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 压缩成ZIP 方法2
     * @param srcFiles 需要压缩的文件列表
     * @param out 压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null ;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1){
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            System.out.println("压缩完成,耗时:" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils",e);
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 递归压缩方法
     * @param sourceFile 源文件
     * @param zos zip输出流
     * @param name 压缩后的名称
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     * false:所有文件跑到压缩包根目录***意:不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    private static void compress(File sourceFile, ZipOutputStream zos, String name,
                                 boolean KeepDirStructure) throws Exception{
        byte[] buf = new byte[BUFFER_SIZE];
        if(sourceFile.isFile()){
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1){
                zos.write(buf, 0, len);
            }
// Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if(listFiles == null || listFiles.length == 0){
// 需要保留原来的文件结构时,需要对空文件夹进行处理
                if(KeepDirStructure){
// 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
                    zos.closeEntry();
                }
            }else {
                for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(),KeepDirStructure);
                    }
                }
            }
        }
    }

    @Test
    public void show(){
        /** 测试压缩方法1  直接压缩目录  注意不要将压缩文件放在 要压缩目录里 这样就会赵成无限循环 */
        String yuanwenjian="C:\\hello\\src\\A";    //被压缩的文件夹
        //创建 空压缩文件
        FileOutputStream yaSuopath= null;
        try {
            yaSuopath = new FileOutputStream(new File("C:\\hello\\src\\A\\mytest01.zip"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //将原文件夹 内的东西 添加到压缩文件里
        ZipUtils.toZip(yuanwenjian, yaSuopath,true);

    }

    @Test
    public void show1(){
        /** 测试压缩方法2   压缩指定文件*/
        List<File> fileList = new ArrayList<>();
        fileList.add(new File("C:\\Users\\12841\\Desktop\\hello\\src\\A\\A.java"));  //被压缩文件1
        fileList.add(new File("C:\\Users\\12841\\Desktop\\hello\\src\\A\\B.java"));  //被压缩文件2
        FileOutputStream fos2 = null;
        try {
            //创建压缩文件
            fos2 = new FileOutputStream(new File("C:\\Users\\12841\\Desktop\\hello\\src\\A\\mytest02.zip"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //将List里存放的原文件 添加到压缩文件里
        ZipUtils.toZip(fileList, fos2);
    }
    
}

解压zip

import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
 * Created by wzj on 2016/9/9.
 */
public class UZipFile
{
    /**
     * 解压到指定目录
     */
    public static void unZipFiles(String zipPath,String descDir)throws IOException
    {
        unZipFiles(new File(zipPath), descDir);
    }
    /**
     * 解压文件到指定目录
     */
    @SuppressWarnings("rawtypes")
    public static void unZipFiles(File zipFile,String descDir)throws IOException
    {
        File pathFile = new File(descDir);
        if(!pathFile.exists())
        {
            pathFile.mkdirs();
        }
        //解决zip文件中有中文目录或者中文文件
        ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));

        for(Enumeration entries = zip.entries(); entries.hasMoreElements();)
        {
            ZipEntry entry = (ZipEntry)entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir+zipEntryName).replaceAll("\\*", "/");;

            //判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')+1));
            if(!file.exists())
            {
                file.mkdirs();
            }
            //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if(new File(outPath).isDirectory())
            {
                continue;
            }
            OutputStream out = new FileOutputStream(outPath);
            byte[] buf1 = new byte[1024*8];
            int len;
            while((len=in.read(buf1))>0)
            {
                out.write(buf1,0,len);
            }
            in.close();
            out.close();
        }
        zip.close();
        System.out.println("******************解压完毕********************");

    }
    public static void main(String[] args) throws IOException {

	//原文件
        File zipFile = new File("x\\xxx\\xx.zip");
	//要解压的地方  注意最后必须补上\\
        String path = "xxx\\xxx\\";
        unZipFiles(zipFile, path);
    }
}

点赞 收藏加 关注