如何将存储BigInteger的文件拆分为大小相等的两个部分
错误原因
- 结构化数据硬切字节破坏完整性:你通过
BigIntegerIO.writeBigInteger写入的每个BigInteger都是带有固定序列化结构的独立单元,直接按文件总字节数对半切,大概率会将单个BigInteger的序列化数据截断到两个文件中,导致拆分后的文件无法正常读取BigInteger。 - 变量类型使用不合理:文件长度
fileSize是long类型,除以2后用double接收完全没有必要,若文件大小超过2G,强制转int还会发生溢出错误。 - 资源管理不规范:输入流
FileInputStream、DataInputStream没有放在try-with-resources的声明块中,无法自动关闭,会存在文件句柄泄漏的风险。
修正方案
如果要求拆分后的两个文件都可以独立读取完整的BigInteger,可参考如下代码实现:
public void splitFile() throws IOException { long fileSize = file.length(); long halfSize = fileSize / 2; // 拆分文件名和后缀 String fullName = file.getName(); String baseName = fullName; String ext = ""; int dotIndex = fullName.lastIndexOf('.'); if (dotIndex > 0) { baseName = fullName.substring(0, dotIndex); ext = fullName.substring(dotIndex); } long currentPartSize = 0; int partCounter = 1; DataOutputStream currentOutput = null; // 输入流放入try-with-resources自动关闭 try (FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis)) { // 初始化第一个拆分文件 currentOutput = new DataOutputStream(new FileOutputStream(baseName + "_part" + partCounter + ext)); while (dis.available() > 0) { // 先读取完整的BigInteger单元 BigInteger num = BigIntegerIO.readBigInteger(dis); // 第一个文件写入大小接近半长时切换到第二个文件 if (partCounter == 1 && currentPartSize > halfSize) { currentOutput.close(); partCounter++; currentOutput = new DataOutputStream(new FileOutputStream(baseName + "_part" + partCounter + ext)); currentPartSize = 0; } // 写入当前BigInteger并更新已写入大小 BigIntegerIO.writeBigInteger(num, currentOutput); currentPartSize = new File(baseName + "_part" + partCounter + ext).length(); } } catch (IOException e) { e.printStackTrace(); } finally { if (currentOutput != null) { try { currentOutput.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("文件拆分完成"); }
如果你只需要纯字节对半拆分、不需要考虑拆分后的文件可以独立读取BigInteger,仅修正原代码的小问题即可:
public void splitFile() throws IOException { long fileSize = file.length(); int halfSize = (int) (fileSize / 2) + 1; byte[] buffer = new byte[halfSize]; String fileName = file.getName(); int partCounter = 1; int readBytes; // 输入流放入try-with-resources自动关闭 try (FileInputStream fis = new FileInputStream(file); DataInputStream bis = new DataInputStream(fis)) { while ((readBytes = bis.read(buffer)) > 0) { String partFileName = String.format("%s.%d", fileName, partCounter++); File newFile = new File(partFileName); try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(newFile))) { dos.write(buffer, 0, readBytes); } } } catch (IOException e) { e.printStackTrace(); } System.out.println("文件拆分完成"); }
内容的提问来源于stack exchange,提问作者Khammal Mousaab
相关产品推荐
相关产品推荐

