精华内容
下载资源
问答
  • 主要为大家详细介绍了java实现从网络下载多个文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Java一次下载多个文件

    千次阅读 2019-09-12 15:46:08
    最近项目遇到一个需求,需要一次性导出全部数据-,而且是按照500条数据一个文件。 话不说,开始。 新增Excel工具类 可以直接复制 import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util....

    最近项目遇到一个需求,需要一次性导出全部数据-,而且是按照500条数据一个文件。
    话不多说,开始。

    新增Excel工具类

    可以直接复制

    
    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.hssf.util.HSSFColor;
    import org.apache.poi.ss.util.CellRangeAddress;
    //关于下面这两个包,可以直接用Java自带的,也可以导入
    //我这里是导入的,可以进行一个编码的设置,不过我是没有设置成功,反而乱码
    //建议里面的文件名什么的都用英文,不用担心乱码,哈哈
    import org.apache.tools.zip.ZipEntry;
    import org.apache.tools.zip.ZipOutputStream;
    
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    public class ExportExcel {
    
        // 显示的导出表的标题
        private String title;
        // 导出表的列名
        private String[] rowName;
        private List<Object[]> dataList = new ArrayList<Object[]>();
    
        public ExportExcel() {
        }
    
        // 构造函数,传入要导出的数据
        public ExportExcel(String title, String[] rowName, List<Object[]> dataList) {
            this.dataList = dataList;
            this.rowName = rowName;
            this.title = title;
        }
    
        // 导出数据
        public void export(OutputStream out) throws Exception {
            try {
                HSSFWorkbook workbook = new HSSFWorkbook();
                HSSFSheet sheet = workbook.createSheet(title);
    
                // 产生表格标题行
                HSSFRow rowm = sheet.createRow(0);
                HSSFCell cellTitle = rowm.createCell(0);
    
    
                //sheet样式定义【】
                HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
                HSSFCellStyle style = this.getStyle(workbook);
                sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
                cellTitle.setCellStyle(columnTopStyle);
                cellTitle.setCellValue(title);
    
                // 定义所需列数
                int columnNum = rowName.length;
                HSSFRow rowRowName = sheet.createRow(2);
    
                // 将列头设置到sheet的单元格中
                for (int n = 0; n < columnNum; n++) {
                    HSSFCell cellRowName = rowRowName.createCell(n);
                    cellRowName.setCellType(HSSFCell.CELL_TYPE_STRING);
                    HSSFRichTextString text = new HSSFRichTextString(rowName[n]);
                    cellRowName.setCellValue(text);
                    cellRowName.setCellStyle(columnTopStyle);
    
                }
                // 将查询到的数据设置到sheet对应的单元格中
                for (int i = 0; i < dataList.size(); i++) {
                    Object[] obj = dataList.get(i);// 遍历每个对象
                    HSSFRow row = sheet.createRow(i + 3);// 创建所需的行数
    
                    for (int j = 0; j < obj.length; j++) {
                        HSSFCell cell = null;
                        //这几行被注释掉的代码,是给表格第一列进行一个赋值起一个编号的效果,不过我认为没必要
    //                    if (j == 0) {
    //                        cell = row.createCell(j, HSSFCell.CELL_TYPE_NUMERIC);
    //                        cell.setCellValue(i + 1);
    //                    } else {
                            cell = row.createCell(j, HSSFCell.CELL_TYPE_STRING);
                            if (!"".equals(obj[j]) && obj[j] != null) {
                                cell.setCellValue(obj[j].toString());
                            }
    //                    }
                        cell.setCellStyle(style);
    
                    }
    
                }
    
                // 让列宽随着导出的列长自动适应
                for (int colNum = 0; colNum < columnNum; colNum++) {
                    int columnWidth = sheet.getColumnWidth(colNum) / 256;
                    for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
                        HSSFRow currentRow;
                        if (sheet.getRow(rowNum) == null) {
                            currentRow = sheet.createRow(rowNum);
                        } else {
                            currentRow = sheet.getRow(rowNum);
                        }
                        if (currentRow.getCell(colNum) != null) {
                            HSSFCell currentCell = currentRow.getCell(colNum);
                            if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                                int length = currentCell.getStringCellValue().getBytes().length;
                                if (columnWidth < length) {
                                    columnWidth = length;
                                }
                            }
                        }
                    }
                    if (colNum == 0) {
                        sheet.setColumnWidth(colNum, (columnWidth - 2) * 256);
                    } else {
                        sheet.setColumnWidth(colNum, (columnWidth + 4) * 256);
                    }
                }
    
                if (workbook != null) {
                    try {
    
                        workbook.write(out);
    
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
    
            } catch (Exception e) {
    
            }
    
    
        }
    
        /**
                * 列头单元格样式
       */
        public HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {
            // 设置字体
            HSSFFont font = workbook.createFont();
    
            // 设置字体大小
            font.setFontHeightInPoints((short) 11);
            // 字体加粗
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            // 设置字体名字
            font.setFontName("Courier New");
            // 设置样式
            HSSFCellStyle style = workbook.createCellStyle();
            // 设置低边框
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            // 设置低边框颜色
            style.setBottomBorderColor(HSSFColor.BLACK.index);
            // 设置右边框
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            // 设置顶边框
            style.setTopBorderColor(HSSFColor.BLACK.index);
            // 设置顶边框颜色
            style.setTopBorderColor(HSSFColor.BLACK.index);
            // 在样式中应用设置的字体
            style.setFont(font);
            // 设置自动换行
            style.setWrapText(false);
            // 设置水平对齐的样式为居中对齐;
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            return style;
    
        }
    
        public HSSFCellStyle getStyle(HSSFWorkbook workbook) {
            // 设置字体
            HSSFFont font = workbook.createFont();
            // 设置字体大小
            font.setFontHeightInPoints((short) 10);
            // 字体加粗
            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
            // 设置字体名字
            font.setFontName("Courier New");
            // 设置样式;
            HSSFCellStyle style = workbook.createCellStyle();
            // 设置底边框;
            style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
            // 设置底边框颜色;
            style.setBottomBorderColor(HSSFColor.BLACK.index);
            // 设置左边框;
            style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
            // 设置左边框颜色;
            style.setLeftBorderColor(HSSFColor.BLACK.index);
            // 设置右边框;
            style.setBorderRight(HSSFCellStyle.BORDER_THIN);
            // 设置右边框颜色;
            style.setRightBorderColor(HSSFColor.BLACK.index);
            // 设置顶边框;
            style.setBorderTop(HSSFCellStyle.BORDER_THIN);
            // 设置顶边框颜色;
            style.setTopBorderColor(HSSFColor.BLACK.index);
            // 在样式用应用设置的字体;
            style.setFont(font);
            // 设置自动换行;
            style.setWrapText(false);
            // 设置水平对齐的样式为居中对齐;
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            // 设置垂直对齐的样式为居中对齐;
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            return style;
        }
    
        //压缩文件
        public void ZipFiles(File[] srcfile, File zipfile) {
            ZipOutputStream out = null;
    
            byte[] buf = new byte[1024];
            try {
                out = new ZipOutputStream(new FileOutputStream(
                        zipfile));
    //            out.setEncoding("UTF-8");
                for (int i = 0; i < srcfile.length; i++) {
                    FileInputStream in = new FileInputStream(srcfile[i]);
                    out.putNextEntry(new ZipEntry(srcfile[i].getName()));
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    out.closeEntry();
                    in.close();
                }
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /***
         * 删除指定文件夹下所有文件
         *
         * @param path 文件夹完整绝对路径
         * @return
         */
        public static boolean delAllFile(String path) {
            boolean flag = false;
            File file = new File(path);
            if (!file.exists()) {
                return flag;
            }
            if (!file.isDirectory()) {
                return flag;
            }
            String[] tempList = file.list();
            File temp = null;
            for (int i = 0; i < tempList.length; i++) {
                if (path.endsWith(File.separator)) {
                    temp = new File(path + tempList[i]);
                } else {
                    temp = new File(path + File.separator + tempList[i]);
                }
                if (temp.isFile()) {
                    temp.delete();
                }
                if (temp.isDirectory()) {
                    delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
                    flag = true;
                }
            }
            return flag;
        }
    
    }
    
    

    具体业务代码

    注:
    1、对数据预处理

     		String title = "业主信息表";//这个是表格的标题,不是文件名
     		//每个单元格的标题,具体内容自己设置
            String[] rowsName = {"业主id", "姓名","身份证号","楼栋号", "单元号", "楼层号", "房间号", "电话号码"};
            //存放需要的数据
            ArrayList<Object[]> dataList = new ArrayList<>();
            Object[] objs = null;
            //根据业务需求,查询出要导出的数据
            List<CitRoomMaster> list = citRoomMasterService.getList();
            //将全部数据按需加载到dataList中
            //对null值进行一个处理,因为如果是空的导入文件中会造成整个文件损坏,读取不到任何数据
            for (CitRoomMaster c :list) {
                objs = new Object[rowsName.length];
                objs[0] = c.getId();
                objs[1] = c.getUsername() == null?"未录入":c.getUsername();
                objs[2] = c.getIdCard() == null?"未录入":c.getIdCard();
                objs[3] = c.getBuilding() == null?"未录入":c.getBuilding();
                objs[4] = c.getUnit() == null?"未录入":c.getUnit();
                objs[5] = c.getRoomLevel() == null?"未录入":c.getRoomLevel();
                objs[6] = c.getRoomNum() == null?"未录入":c.getRoomNum();
                objs[7] = c.getTel() == null?"未录入":c.getTel();
                dataList.add(objs);
            }
    

    2、按500条数据进行Excel文件生成

    // 将excel导出的文件位置,临时文件,注意,一定是一个不存在的文件,因为后面会把这个文件夹删完
            String filePath = "C:\\小区业主信息"+ File.separator;
            // 得到此路径下文件
            File fileDir = new File(filePath);
            //创建文件夹
            if (!fileDir.exists() && !fileDir.isDirectory()) {
                fileDir.mkdirs();
            }
            // 用于存放生成的excel文件名称
            List<String> fileNames = new ArrayList<String>();
            // 导出Excel文件的路径
            String fullFilePath = "";
            //输出流
            FileOutputStream os = null;
    //拿到整个需要循环导出的次数
            int length = list.size()%500 == 0 ? list.size()/500 : (list.size()/500)+1;
            for (int i = 0; i < length; i++) {
                //给文件命名。随机命名 自定义
                String fileName = "OwnerInformation-" + String.valueOf(System.currentTimeMillis()).substring(4, 13) + ".xls";
    //生成Excel文件导出的路径
                fullFilePath = filePath + File.separator + fileName;
                fileNames.add(fullFilePath);
                os = new FileOutputStream(fullFilePath);
                //调用poi的工具类
                int end = 0;
                //对list进行截取,每500条数据
                ExportExcel ex = new ExportExcel(title, rowsName, dataList.subList(i*500,end = (i+1)*500<=list.size()?(i+1)*500:list.size()));
                try {
                    ex.export(os);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                os.flush();
                os.close();
                os = null;
            }
    

    3、将存放Excel的文件夹压缩导出,就完成需求了

    //告诉浏览器数据格式,将头和数据传到前台
            String headStr = "attachment; filename=\"" + zip.getName() + "\"";
            response.setContentType("APPLICATION/zip");
    //        response.setHeader("Location",zip.getName());
            response.setHeader("Content-Disposition", headStr);
            OutputStream out = response.getOutputStream();
            InputStream in = new FileInputStream(zipFilePath);
            byte[] buffer = new byte[1024];
            int i = -1;
            while ((i = in.read(buffer)) != -1) {
                out.write(buffer, 0, i);
            }
            out.flush();
            out.close();
            in.close();
            out = null;
            try {
                excelUtil.delAllFile(filePath); // 删除完里面所有内容
                filePath = filePath.toString();
                java.io.File myFilePath = new java.io.File(filePath);
                myFilePath.delete(); // 删除空文件夹
            } catch (Exception e) {
                e.printStackTrace();
            }
    

    最后再说一点,还是关于中文乱码的问题,本来最开始的我是用的中文写文件名,并且在自己电脑上测试的时候是么有乱码的。但是部署到公司服务器上,就乱码了,怀疑是编码不一致问题导致的,因为时间问题,也没有去调试了。所以,如果有小伙伴能够解决这个问题,希望不吝赐教。

    展开全文
  • JAVA 如何一次下载多个文件

    万次阅读 2016-11-17 17:16:01
    https://zhidao.baidu.com/question/1446055057527183940.html import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j

    https://zhidao.baidu.com/question/1446055057527183940.html


    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLDecoder;
    import java.util.Vector;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
     
    /**
     * 本例使用的是基于JDK HttpURLConnection的同步下载,即按顺序下载
     * 如果同时下载多个任务,可以使用多线程
     * @author aK1ng
     *
     */
    public class Demo1 {
        public static void main(String[] args) {
            // 下载列表
            Vector<String> downloadList = new Vector<String>();
            // 添加下载地址
            downloadList.add("
    );
            downloadList.add("
    );
            download(downloadList);
        }
         
        /**
         * 下载
         */
        static void download(Vector<String> downloadList){
            // 线程池
            ExecutorService pool = null;
            HttpURLConnection connection = null;
            //循环下载
            try {
                for (int i = 0; i < downloadList.size(); i++) {
                    pool = Executors.newCachedThreadPool();
                    final String url = downloadList.get(i);
                    String filename = getFilename(downloadList.get(i));
                    System.out.println("正在下载第" + (i+1) + "个文件,地址:" + url);
                    Future<HttpURLConnection> future = pool.submit(new Callable<HttpURLConnection>(){
                        @Override
                        public HttpURLConnection call() throws Exception {
                            HttpURLConnection connection = null;
                            connection = (HttpURLConnection) new URL(url).openConnection(); 
                            connection.setConnectTimeout(10000);//连接超时时间
                            connection.setReadTimeout(10000);// 读取超时时间
                            connection.setDoInput(true);
                            connection.setDoOutput(true);
                            connection.setRequestMethod("GET");
                            //断点续连,每次要算出range的范围,请参考Http 1.1协议
                            //connection.setRequestProperty("Range", "bytes=0");
                            connection.connect();
                            return connection;
                        }
                    });
                    connection = future.get();
                    System.out.println("下载完成.响应码:"+ connection.getResponseCode());
                    // 写入文件
                    writeFile(new BufferedInputStream(connection.getInputStream()), URLDecoder.decode(filename,"UTF-8"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != connection)
                    connection.disconnect();
                if (null != pool) 
                    pool.shutdown();
            }
        }
         
        /**
         * 通过截取URL地址获得文件名
         * 注意:还有一种下载地址是没有文件后缀的,这个需要通过响应头中的
         * Content-Disposition字段 获得filename,一般格式为:"attachment; filename=\xxx.exe\"
         * @param url
         * @return
         */
        static String getFilename(String url){
            return ("".equals(url) || null == url) ? "" : url.substring(url.lastIndexOf("/") + 1,url.length());
        }
         
        /**
         * 写入文件
         * @param inputStream
         */
        static void writeFile(BufferedInputStream bufferedInputStream,String filename){
            //创建本地文件
            File destfileFile = new File("d:\\temp\\download\\"+ filename);
            if (destfileFile.exists()) {
                destfileFile.delete();
            }
            if (!destfileFile.getParentFile().exists()) {
                destfileFile.getParentFile().mkdir();
            }
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(destfileFile);
                byte[] b = new byte[1024];
                int len = 0;
                // 写入文件
                System.out.println("开始写入本地文件.");
                while ((len = bufferedInputStream.read(b, 0, b.length)) != -1) {
                    System.out.println("正在写入字节:" + len);
                    fileOutputStream.write(b, 0, len);
                }
                System.out.println("写入本地文件完成.");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != fileOutputStream) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                    if (null != bufferedInputStream)
                        bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    展开全文
  • java实现服务器上多个文件先打包,然后下载下载完成后删除包!
  • java 如何一次导出多个 excel 或者 pdf 文件
  • java 多个线程同时写同一个文件

    千次阅读 2019-10-11 17:00:17
    话不说,先直接上代码: 主方法: import java.util.concurrent.CountDownLatch; /** * @ProjectName: emp_customer * @Package: PACKAGE_NAME * @ClassName: Test * @Author: Administrator * @...

    话不多说,先直接上代码:

    主方法:

    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: Test
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 14:10
     * @Version: 1.0
     */
    public class Test {
         public static void main(String args[]){
    
             //线程数
             int threadSize=4;
             //源文件地址
             String sourcePath = "E:\\1\\4.txt";
             //目标文件地址
             String destnationPath = "E:\\2\\4.txt";
             //
             CountDownLatch latch = new CountDownLatch(threadSize);
             MultiDownloadFileThread m = new MultiDownloadFileThread(threadSize, sourcePath, destnationPath, latch);
             long startTime = System.currentTimeMillis();
             try {
                 m.excute();
                 latch.await();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             long endTime = System.currentTimeMillis();
             System.out.println("全部下载结束,共耗时" + (endTime - startTime) / 1000 + "s");
         }
    
    }
    

     

    线程类:

    import java.io.*;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileLock;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: MultiDownloadFileThread
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 15:03
     * @Version: 1.0
     */
    public class MultiDownloadFileThread {
    
        private int threadCount;
        private String sourcePath;
        private String targetPath;
        private CountDownLatch latch;
    
        public MultiDownloadFileThread(int threadCount, String sourcePath, String targetPath, CountDownLatch latch) {
            this.threadCount = threadCount;
            this.sourcePath = sourcePath;
            this.targetPath = targetPath;
            this.latch = latch;
        }
    
        public void excute() {
            File file = new File(sourcePath);
            int fileLength = (int) file.length();
            //分割文件
            int blockSize = fileLength / threadCount;
            for (int i = 1; i <= threadCount; i++) {
                //第一个线程下载的开始位置
                int startIndex = (i - 1) * blockSize;
                int endIndex = startIndex + blockSize - 1;
                if (i == threadCount) {
                    //最后一个线程下载的长度稍微长一点
                    endIndex = fileLength;
                }
                System.out.println("线程" + i + "下载:" + startIndex + "字节~" + endIndex + "字节");
                new DownLoadThread(i, startIndex, endIndex).start();
            }
        }
    
    
        public class DownLoadThread extends Thread {
            private int i;
            private int startIndex;
            private int endIndex;
    
            public DownLoadThread(int i, int startIndex, int endIndex) {
                this.i = i;
                this.startIndex = startIndex;
                this.endIndex = endIndex;
            }
    
            @Override
            public void run() {
                File file = new File(sourcePath);
                FileInputStream in = null;
                RandomAccessFile raFile = null;
                FileChannel fcin = null;
                FileLock flin = null;
                try {
                    in = new FileInputStream(file);
                    in.skip(startIndex);
                    //给要写的文件加锁
                    raFile = new RandomAccessFile(targetPath, "rwd");
                    fcin =raFile.getChannel();
                    while(true){
                        try {
                            flin = fcin.tryLock();
                            break;
                        } catch (Exception e) {
                            System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒,当前进入的线程为:"+i);
                            sleep(1000);
                        }
                    }
                    //随机写文件的时候从哪个位置开始写
                    raFile.seek(startIndex);
                    int len = 0;
                    byte[] arr = new byte[1024];
                    //获取文件片段长度
                    int segLength = endIndex - startIndex + 1;
                    while ((len = in.read(arr)) != -1) {
                        if (segLength > len) {
                            segLength = segLength - len;
                            raFile.write(arr, 0, len);
                        } else {
                            raFile.write(arr, 0, segLength);
                            break;
                        }
                    }
                    System.out.println("线程" + i + "下载完毕");
                    //计数值减一
                    latch.countDown();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (in != null) {
                            in.close();
                        }
                        if (raFile != null) {
                            raFile.close();
                        }
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    运行结果:

     

    涉及到的相关知识点:

    1.CountDownLatch 

    2.RandomAccessFile

    3.FileLock

    下面我们具体讲解下

    一、FileLock :文件锁

    FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w)加锁,保证同时只有一个进程可以拿到文件的锁,这个进程从而可以对文件做访问;而其它拿不到锁的进程要么选择被挂起等待,要么选择去做一些其它的事情, 这样的机制保证了众进程可以顺序访问该文件。

    1. 概念

    • 共享锁: 共享读操作,但只能一个写(读可以同时,但写不能)。共享锁防止其他正在运行的程序获得重复的独占锁,但是允许他们获得重复的共享锁。
    • 独占锁: 只有一个读或一个写(读和写都不能同时)。独占锁防止其他程序获得任何类型的锁。

    2. lock()和tryLock()的区别:

    lock()阻塞的方法,锁定范围可以随着文件的增大而增加。无参lock()默认为独占锁;有参lock(0L, Long.MAX_VALUE, true)为共享锁。
    tryLock()非阻塞,当未获得锁时,返回null.
    3. FileLock的生命周期:在调用FileLock.release(),或者Channel.close(),或者JVM关闭

    4. FileLock是线程安全的
     

    二、RandomAccessFile

    java除了File类之外,还提供了专门处理文件的类,即RandomAccessFile(随机访问文件)类。该类是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,这里“随机”是指可以跳转到文件的任意位置处读写数据。在访问一个文件的时候,不必把文件从头读到尾,而是希望像访问一个数据库一样“随心所欲”地访问一个文件的某个部分,这时使用RandomAccessFile类就是最佳选择。

    RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当前读写n个字节后,文件指示器将指向这n个字节后面的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。RandomAccessFile类在数据等长记录格式文件的随机(相对顺序而言)读取时有很大的优势,但该类仅限于操作文件,不能访问其他的I/O设备,如网络、内存映像等。RandomAccessFile类的构造方法如下所示:

    RandomAccessFile(File file ,  String mode)
    //创建随机存储文件流,文件属性由参数File对象指定

    RandomAccessFile(String name ,  String mode)
    //创建随机存储文件流,文件名由参数name指定

    这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:

    “r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
    “rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
    “rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
    “rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作

     

    三、CountDownLatch

    1.概念

    • countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
    • 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

    2.源码

    • countDownLatch类中只提供了一个构造器:
    //参数count为计数值
    public CountDownLatch(int count) {  };  
    
    • 类中有三个方法是最重要的:
    //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
    public void await() throws InterruptedException { };   
    //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
    //将count值减1
    public void countDown() { };  

    假如在我们的代码里面,我们把main方法里面的

    latch.await();

    注释掉

    如下所示:

    我们可以看到跟之前的输出结果相比,我们的主方法里面输出的:全部下载结束的输出信息,已经打印到我们执行文件下载的线程输出信息的前面了,说明主线程先执行完。这从而说明,await() 方法具有阻塞作用

     我们在把latch.await();放开,把文件下载线程里的latch.countDown();注释掉,

    如下:

    我们可以看到,主程序里的的输出;全部下载结束的输出信息,一直未输出,程序也一直未结束,由此可得,countDown() 方法具有唤醒阻塞线程的作用。

    那么如何让 CountdownLatch 尽早结束

    假如我们的程序执行到countDown()之前就抛出异常,这就可能导致一整情况,CountdownLatch 计数永远不会达到零并且 await() 永远不会终止。

    为了解决这个问题,我们在调用 await() 时添加一个超时参数。

     

    CountDownLatch总结:

        1、CountDownLatch end = new CountDownLatch(N); //构造对象时候 需要传入参数N

      2、end.await()  能够阻塞线程 直到调用N次end.countDown() 方法才释放线程,最好设置超时参数

      3、end.countDown() 可以在多个线程中调用  计算调用次数是所有线程调用次数的总和

     

    对于,本demo而言,加不加文件锁的意义不大,因为在进入线程写的时候,就已经告诉单个线程需要写的内容是哪一块到哪一块,不加锁,也会正常写入,切经本人测试无误,但若是对同一个文件,即要写,又要读话,就必须加锁,不然程序执行可能不完整,具体情况可以查看下面的这个博客:https://blog.csdn.net/gxy3509394/article/details/7435993

    展开全文
  • //普通java文件下载方法,适用于所有框架 public String downloadFilesTest(HttpServletRequest request,HttpServletResponse res) throws IOException { //获取文件根目录,不同框架获取的方式不一样,可自由...
    //普通java文件下载方法,适用于所有框架  
        public String downloadFilesTest(HttpServletRequest request,HttpServletResponse res) throws IOException {
            //获取文件根目录,不同框架获取的方式不一样,可自由切换  
            String basePath = request.getSession().getServletContext().getRealPath("/upload/fileDir");  
    
            //获取文件名称(包括文件格式)  
            String fileName = "1.jpg";  
    
            //组合成完整的文件路径  
            String targetPath = basePath+File.separator+fileName;  
    
            //模拟多一个文件,用于测试多文件批量下载  
            String targetPath1 = basePath+File.separator+"2.jpg";  
            //模拟文件路径下再添加个文件夹,验证穷举
            String targetPath2 = basePath+File.separator+"test";
    
            System.out.println("文件名:"+fileName);  
            System.out.println("文件路径:"+targetPath);  
    
            //方法1:IO流实现下载的功能  
            res.setContentType("text/html; charset=UTF-8"); //设置编码字符  
            res.setContentType("application/octet-stream"); //设置内容类型为下载类型  
            res.setHeader("Content-disposition", "attachment;filename="+fileName);//设置下载的文件名称  
            OutputStream out = res.getOutputStream();   //创建页面返回方式为输出流,会自动弹出下载框   
    
    /*    //方法1-1:IO字节流下载,用于小文件  
            System.out.println("字节流下载");  
            InputStream is = new FileInputStream(targetPath);  //创建文件输入流  
            byte[] Buffer = new byte[2048];  //设置每次读取数据大小,即缓存大小  
            int size = 0;  //用于计算缓存数据是否已经读取完毕,如果数据已经读取完了,则会返回-1  
            while((size=is.read(Buffer)) != -1){  //循环读取数据,如果数据读取完毕则返回-1  
                out.write(Buffer, 0, size); //将每次读取到的数据写入客户端  
            }
            is.close();
            */  
    
    
    /*    //方法1-2:IO字符流下载,用于大文件  
            System.out.println("字符流");  
            File file = new File(targetPath);  //创建文件  
            FileInputStream fis=new FileInputStream(file);  //创建文件字节输入流  
            BufferedInputStream bis=new BufferedInputStream(fis); //创建文件缓冲输入流  
            byte[] buffer = new byte[bis.available()];//从输入流中读取不受阻塞
            bis.read(buffer);//读取数据文件
            bis.close();
            out.write(buffer);//输出数据文件
            out.flush();//释放缓存
            out.close();//关闭输出流
    */   
    
    /*    //方法1-3:将附件中多个文件进行压缩,批量打包下载文件  
            //创建压缩文件需要的空的zip包  
            String zipBasePath=request.getSession().getServletContext().getRealPath("/upload/zip");  
            String zipName = "temp.zip";
            String zipFilePath = zipBasePath+File.separator+zipName;  
    
            //创建需要下载的文件路径的集合
            List<String> filePaths = new ArrayList<String>();  
            filePaths.add(targetPath);  
            filePaths.add(targetPath1); 
            filePaths.add(targetPath2);
    
            //压缩文件
            File zip = new File(zipFilePath);  
            if (!zip.exists()){     
                zip.createNewFile();     
            }
            //创建zip文件输出流  
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
            this.zipFile(zipBasePath,zipName, zipFilePath,filePaths,zos);
            zos.close();
            res.setHeader("Content-disposition", "attachment;filename="+zipName);//设置下载的压缩文件名称
    
            //将打包后的文件写到客户端,输出的方法同上,使用缓冲流输出  
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));  
            byte[] buff = new byte[bis.available()];  
            bis.read(buff);
            bis.close();
            out.write(buff);//输出数据文件
            out.flush();//释放缓存
            out.close();//关闭输出流
    */
            return null;
        }
    
        /**
         * 压缩文件
         * @param zipBasePath 临时压缩文件基础路径
         * @param zipName 临时压缩文件名称
         * @param zipFilePath 临时压缩文件完整路径
         * @param filePaths 需要压缩的文件路径集合
         * @throws IOException
         */
        private String zipFile(String zipBasePath, String zipName, String zipFilePath, List<String> filePaths,ZipOutputStream zos) throws IOException {
    
            //循环读取文件路径集合,获取每一个文件的路径  
            for(String filePath : filePaths){  
                File inputFile = new File(filePath);  //根据文件路径创建文件  
                if(inputFile.exists()) { //判断文件是否存在  
                    if (inputFile.isFile()) {  //判断是否属于文件,还是文件夹  
                        //创建输入流读取文件  
                        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));  
    
                        //将文件写入zip内,即将文件进行打包  
                        zos.putNextEntry(new ZipEntry(inputFile.getName()));  
    
                        //写入文件的方法,同上                  
                        int size = 0;  
                        byte[] buffer = new byte[1024];  //设置读取数据缓存大小
                        while ((size = bis.read(buffer)) > 0) {  
                            zos.write(buffer, 0, size);  
                        }  
                        //关闭输入输出流  
                        zos.closeEntry();  
                        bis.close(); 
    
                    } else {  //如果是文件夹,则使用穷举的方法获取文件,写入zip  
                        try {  
                            File[] files = inputFile.listFiles();  
                            List<String> filePathsTem = new ArrayList<String>();  
                            for (File fileTem:files) {  
                                filePathsTem.add(fileTem.toString());
                            }  
                            return zipFile(zipBasePath, zipName, zipFilePath, filePathsTem,zos);
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                    }  
                }  
            }  
            return null;
        } 
    
    
    
    
    展开全文
  • java socket 多线程网络传输多个文件

    热门讨论 2013-07-14 13:17:18
    java socket 多线程网络传输多个文件
  • JAVA项目同时上传多个文件和多个内容   首先这俩问题是由个功能引发的,最近项目中有这样的要求,前端要上传多个文件用于地图描绘那些东西,但只是为了拼到地图上查看一下,并不做保存,这就引发了我的纠结,...
  • Java实现zip压缩多个文件下载

    千次阅读 2017-10-23 18:08:26
    转载http://www.cnblogs.com/yzuzhang/p/4763606.html package com.javaweb.entity... import java.io.Serializable; /** * 文件实体类*/ public class FileBean implements Serializable{ private static fi
  • Java生成多个pdf文件,压缩包zip下载

    千次阅读 热门讨论 2019-06-06 19:09:04
    // 把excel拷贝到同个文件目录下 ZipUtil.createZip(newResPath, zipPath); // 打包改目录成.zip包 //下载 try (InputStream inputStream = new FileInputStream(new File(zipPath )); OutputStream outputStream =...
  • java的ftp线程下载

    热门讨论 2014-10-02 20:42:47
    本程序是在原有基础上逐步完善的,第版:http://download.csdn.net/detail/zpwmhx/4342943 ...详细文档请看: ...本程序很适合在主机间批量传输文件和目录,参数可控
  • 个.java文件中存在多个main方法

    千次阅读 2020-06-16 10:54:17
    看上面的代码,个.java文件中存在多个类 而且每个类中都存在个main方法,大家都知道main方法是JVM运行程序的入口,那在个.java文件中的多个类中的多个main方法是如何运行的呢? 首先: 我们要先了解 如何能...
  • 这里需要修改controller,将循环生成的word下载到指定文件夹下,然后将完全限定名放入list中,最后将list中所有文件打成zip包下载 package com.example.demo.controller; import ch.qos.logback.core.util.FileUtil...
  • import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.zip.Zip...
  • 说明:这是一新的系列,定下一目标,只要不忙,每天都会进行一次更新 验证 public class ClassD { ClassB b; public static void main(String[] args) { System.out.println("xxx"); } class ClassE { ...
  • Java之对象操作流一次读取多个对象的问题

    千次阅读 多人点赞 2020-01-30 08:29:26
    问题描述:在操作对象流的时候应该有很小伙伴遇到在读取对象时不知文件内对象的具体数,所以读取时不知末尾结束判断标志,或者以为返回的是对象所以末尾结束标志就会是null,导致每次读取程序都会报错,针对此种...
  • Java目录监视器源程序 9目标文件 内容索引:JAVA源码,综合应用,目录监视 用JAVA开发的一小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。...
  • word文档批量下载(单个、多个)以zip形式下载
  • java 多线程读取多个文件

    千次阅读 2019-01-02 10:49:34
    package ... import java.io.*; import java.util.List; import java.util.concurrent.CountDownLatch; ... * 多线程读取多个文件 */ public class FileThread extends Thread{ p...
  • Java实现上传(支持多个文件同时上传)和下载

    万次阅读 多人点赞 2018-05-08 17:38:41
    文件上传一直是Web项目中必不可少的项功能。项目结构如下:(这是我之前创建的SSM整合的框架项目,在这上面添加文件上传与下载)主要的是FileUploadController,doupload.jsp,up.jsp,springmvc.xml1.先编写up.jsp&...
  • // 导出,此处只封装了浏览器下载方式 // 调用downloadExcel,返回输出流给客户端 String fileName = (String) map2.get("name") + ".xlsx"; excel.downloadExcel(response, fileName); } } public void download...
  • 假如1000w数据,分10查询出来写入到10CSV文件里面,怎么实现?
  • Java多线程下载文件

    万次阅读 热门讨论 2017-08-03 10:03:08
    Java多线程下载文件优化:合理利用服务器资源...当有很多个文件需要下载的时候,调用某个方法,有个线程池,线程池大小假定是10,当有10个文件过来的时候,每个线程去下载一个文件即可 多线程如果只知道Thread和Runnab
  • 有时候会遇到需要在后台批量生成Excel并导出的应用场景,为了方便导出下载,通常会采用Zip打包成一个文件然后下载导出的方式实现。 1.导出Excel 之前写过篇 POI 通用导出Excel(.xls,.xlsx), 所以此处不会再重复写...
  • java 同时创建多个文件夹和文件

    千次阅读 2018-10-23 17:07:06
    //获取文件的绝对路径 } //读写文件 FileInputStream fis = new FileInputStream("aaaa.txt"); BufferedInputStream bufis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream...
  • JAVA 批量下载文件

    千次阅读 2019-07-04 14:47:07
    最近项目有需求,用户想对挂有附件的数据记录 实现一键下载全部附件(目前项目仅支持每次点击单条记录进行附件下载),下面记录我实现的解决方案。 项目框架基于SSM service业务实现层(impl): //获取配置的...
  •   程序员在做web等项目的时候,往往都需要添加文件上传、下载、删除的功能,有时是单... 这篇博文主要是讲如何将多个文件压缩并下载下来: 主要有以下几个步骤:1。 首先先遍历出某个文件夹所含有的所有文件im...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,111,930
精华内容 444,772
关键字:

java一次下载多个文件

java 订阅