前言
我需要把一个大文件上传到网盘上,由于网盘禁止上传大于4G的文件,所以我想通过Java程序来把大文件分割为小文件后,再上传,等需要的时候,通过程序把文件进行合并即可。
一、废话少说,直接上代码
代码如下:
1 package com.xm.file; 2 3 import java.io.*; 4 import java.util.Arrays; 5 import java.util.Date; 6 import java.util.List; 7 import java.util.stream.Collectors; 8 9 /** 10 * 1.把大文件按照指定大小分割成多个小文件 11 * 2.把多个小文件分割为大文件 12 * 测试用例@com.xm.FileSplitAndCombineTest 13 */ 14 public class FileSplitAndCombine { 15 16 private static int THOUSAND_TWENTY_FOUR= 1024; // one thousand and twenty-four 17 18 19 20 /** 21 * 把大文件拆分为多个小文件 22 * 23 * @param sourcePath 需要被拆分的文件路径 24 * @param desPath 拆分后的文件应该存放的文件路径 25 * @param newName 每一个小文件名 26 */ 27 public static void splitFile(String sourcePath, String desPath, String newName) { 28 29 try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(sourcePath)))) { 30 for (int i = 0; ; i++) { 31 String filePath = desPath + File.separatorChar +newName+"_" +i; 32 if (singleSplitFile(bis, filePath, THOUSAND_TWENTY_FOUR)) break; 33 } 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 } 38 39 40 /** 41 * @param bis 输入流 42 * @param filePath 新文件存储的文件夹路径 43 * @param partitionSize 每个文件的大小 单位MB 44 * @throws IOException 45 */ 46 private static boolean singleSplitFile(BufferedInputStream bis, String filePath,int partitionSize) throws IOException { 47 int length = partitionSize * THOUSAND_TWENTY_FOUR * THOUSAND_TWENTY_FOUR; 48 byte[] buffer = new byte[THOUSAND_TWENTY_FOUR]; 49 int tempLength; 50 51 System.out.println(nowTime() + "----->>>> begin split " + filePath); 52 try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)))) { 53 while ((tempLength = bis.read(buffer)) != -1) { 54 bos.write(buffer, 0, tempLength); 55 if ((length = length - tempLength) <= 0) break; 56 } 57 } 58 System.out.println(nowTime() + "<<<<----- yet finish split" + filePath); 59 60 return tempLength < 0; 61 } 62 63 /** 64 * 把指定文件夹内的文件合并为一个文件 65 * 66 * @param sourcePath 需要被合并的文件所在的文件中路径 67 * @param desPath 合并后的文件存放位置 68 */ 69 public static void combineFile(String sourcePath, String desPath) { 70 71 List<String> sortedFileNames = sortFilesName(sourcePath); 72 if (sortedFileNames == null) { 73 System.out.println(sourcePath+"路径下不存在文件夹"); 74 return; 75 } 76 77 try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(desPath)))) { 78 for (String sortedFileName : sortedFileNames) { 79 copyFile(bos, sourcePath + File.separatorChar + sortedFileName); 80 } 81 System.out.println("all finish..."); 82 } catch (IOException e) { 83 e.printStackTrace(); 84 } 85 } 86 87 /** 88 * 把目标文件合并到输出流中 89 * 90 * @param bos 缓冲输出流 91 * @param des 目标文件路径 92 * @throws IOException 93 */ 94 private static void copyFile(BufferedOutputStream bos, String des) throws IOException { 95 96 try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(des)))) { 97 System.out.println(nowTime()+ "------>>>>"+des + "开始合并"); 98 byte[] bytes = new byte[1024]; 99 int length; 100 while ((length = bis.read(bytes)) != -1) { 101 bos.write(bytes, 0, length); 102 } 103 System.out.println(nowTime()+ "<<<<------"+des + "合并完成"); 104 } 105 } 106 107 /** 108 * 对指定文件夹内的文件名进行排序 (增序) 109 * 110 * @param fileDir 111 * @return 112 */ 113 private static List<String> sortFilesName(String fileDir) { 114 File file = new File(fileDir); 115 File[] files = file.listFiles(); 116 if (null == files || files.length == 0) { 117 return null; 118 } 119 Pattern compile = Pattern.compile("^.+_\\d+$"); 120 return Arrays.stream(files).filter(file1 -> { 121 if (file1.isDirectory()){ 122 System.out.println("waring: "+ file1.getName() +"不是一个文件"); 123 return false; 124 } 125 String file1Name = file1.getName(); 126 Matcher matcher = compile.matcher(file1Name); 127 if (!matcher.find()){ 128 System.out.println("waring:文件名 "+file1Name+"不符合 文件名_数字的命名规范"); 129 return false; 130 } 131 return true; 132 }).map(File::getName) 133 .sorted((fileName1,fileName2)->{ 134 String[] split1 = fileName1.split("_"); 135 String[] split2 = fileName2.split("_"); 136 return Integer.parseInt(split1[split1.length - 1])-Integer.parseInt(split2[split2.length - 1]); 137 }).collect(Collectors.toList()); 138 } 139 140 private static String nowTime(){ 141 return new Date().toLocaleString(); 142 } 143 }
二.测试用例
代码如下:
1 package com.xm; 2 3 import com.xm.file.FileSplitAndCombine; 4 5 6 public class FileSplitAndCombineTest { 7 public static void main(String[] args) { 8 //文件分割 9 splitTest(); 10 //文件合并 11 combineTest(); 12 } 13 14 private static void splitTest() { 15 String sourcePath = "E:\\fileSplitTest\\source.zip"; 16 String desPath = "E:\\fileSplitTest"; 17 String newName = "split"; 18 19 FileSplitAndCombine.splitFile(sourcePath, desPath, newName); 20 } 21 22 private static void combineTest() { 23 String desPath = "E:\\fileSplitTest\\combine.zip"; 24 String sourcePath = "E:\\fileSplitTest"; 25 26 FileSplitAndCombine.combineFile(sourcePath, desPath); 27 } 28 }
当切割的文件个数大于10的时候会出现文件损害的问题。原因时因为没有按照原来分割的顺序切割文件,出错代码在sortFilesName(String fileDir)方法中。可通过如下方式修改
1 private static List<String> sortFilesName(String fileDir) { 2 File file = new File(fileDir); 3 File[] files = file.listFiles(); 4 if (null == files || files.length == 0) { 5 return null; 6 } 7 Pattern compile = Pattern.compile("^.+_\\d+[csdnCommentCode]quot;); 8 return Arrays.stream(files).map(File::getName) 9 .sorted((fileName1,fileName2)->{ 10 String[] split1 = fileName1.split("_"); 11 String[] split2 = fileName2.split("_"); 12 return Integer.parseInt(split1[split1.length - 1])-Integer.parseInt(split2[split2.length - 1]); 13 }).collect(Collectors.toList()); 14 }
标签:文件,java,String,合并,return,拆分,length,File,new From: https://www.cnblogs.com/mingruifeng/p/16586671.html