设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间18 现在时间18 缓存数据 从头到尾 我要的只有感情 可没人能给我

从头到尾 我要的只有感情 可没人能给我 -- 情深深雨濛濛

查看: 1364|回复: 2

Java使用ByteBuffer进行多文件合并和拆分的代码实现

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:221
  • 打卡月天数:0
  • 打卡总奖励:3252
  • 最近打卡:2025-09-12 09:43:26
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
450
主题
439
精华
0
金钱
4628
积分
935
注册时间
2023-1-7
最后登录
2025-9-12

发表于 2024-9-26 21:03:26 | 显示全部楼层 |阅读模式
目录
  • 1.背景
  • 2.代码工程
    • 实验目的
    • 合并代码
    • 拆分代码
    • 工具类
    • 代码仓库
  • 3.测试

    1.背景

    因为验证证书的需要,需要把证书文件和公钥给到客户,考虑到多个文件交互的不便性,所以决定将2个文件合并成一个文件交互给客户。刚开始采用字符串拼接2个文件内容,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,最后采用基于二进制流拆分和合并文件,效果不错!

    2.代码工程

    实验目的

    1. 对文件进行二进制流合并和拆分
    复制代码

    合并代码

    1. ByteBuffer.allocate(4).putInt(publicCertsContent.length).array()
    复制代码
    的作用是将
    1. publicCertsContent
    复制代码
    (公钥证书内容)的长度转换为 4 个字节的整数,并写入到字节缓冲区中。具体作用如下:

      1. ByteBuffer.allocate(4)
      复制代码
      : 创建一个大小为 4 字节的
      1. ByteBuffer
      复制代码
      ,因为 Java 中的整数(
      1. int
      复制代码
      )是 4 个字节。
      1. putInt(publicCertsContent.length)
      复制代码
      : 将
      1. publicCertsContent
      复制代码
      的字节数组长度(即证书文件的字节长度)存入
      1. ByteBuffer
      复制代码
      。这样就把证书内容的长度存储为一个 4 字节的整数。
      1. array()
      复制代码
      : 将
      1. ByteBuffer
      复制代码
      转换为字节数组。这个数组包含了公钥证书内容长度的 4 字节表示形式。

    这个表达式的作用是将

    1. publicCertsContent
    复制代码
    数组的长度转换为二进制的 4 字节表示形式,并写入输出流(
    1. outputStream
    复制代码
    )中。这样在以后读取合并文件时,代码可以知道该读取多少字节属于
    1. publicCertsContent
    复制代码

    有小伙伴这里可能有疑问,4字节够存多大数字呢?

    4 个字节(即 32 位)在计算机中用于存储整数,能表示的整数范围如下:

    • 有符号整数(
      1. int
      复制代码
      类型)
      • 范围是:-2,147,483,6482,147,483,647
      • 其中 1 位用于符号(正负),31 位用于数值。
    • 无符号整数
      1. unsigned int
      复制代码
      ,Java 中没有直接支持,但可以通过转换处理):
      • 范围是:04,294,967,295

    通常 Java 中的

    1. int
    复制代码
    类型是有符号的,因此 4 个字节可以存储的整数范围为 -2^31 到 2^31 - 1,即 -2,147,483,648 到 2,147,483,647。所以只要不超过这个限制都能存下来

    1. package com.et;
    2. import java.io.ByteArrayOutputStream;
    3. import java.io.IOException;
    4. import java.nio.ByteBuffer;
    5. public class FileMerger {
    6. public static void main(String[] args) {
    7. String privateKeys = "D:/IdeaProjects/Java-demo/file/src/main/resources/privateKeys.keystore";
    8. String publicCerts = "D:/IdeaProjects/Java-demo/file/src/main/resources/publicCerts.keystore";
    9. merger(privateKeys,publicCerts);
    10. }
    11. public static String merger(String privateKeys, String publicCerts) {
    12. String directoryPath = FileUtils.extractDirectoryPath(privateKeys);
    13. String mergedFile =directoryPath+"merge.keystore";
    14. try {
    15. byte[] privateKeysContent = FileUtils.readBinaryFile(privateKeys);
    16. byte[] publicCertsContent = FileUtils.readBinaryFile(publicCerts);
    17. // create outputStream
    18. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    19. // write keystore length(4 byte)
    20. outputStream.write(ByteBuffer.allocate(4).putInt(privateKeysContent.length).array());
    21. // write keystore content
    22. outputStream.write(privateKeysContent);
    23. // witer license content(4 byte int )
    24. outputStream.write(ByteBuffer.allocate(4).putInt(publicCertsContent.length).array());
    25. // write license content
    26. outputStream.write(publicCertsContent);
    27. // write merge content to file
    28. FileUtils.writeBinaryFile(mergedFile, outputStream.toByteArray());
    29. System.out.println("merge success " + mergedFile);
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. }
    33. return mergedFile;
    34. }
    35. }
    复制代码

    拆分代码

    拆分逻辑就很简单了,先读取4字节,获取文件大小,然后依次获取文件内容就可以了

    1. buffer.getInt()
    复制代码
    可以正确读取文件中的大小信息。具体来说,它会从
    1. ByteBuffer
    复制代码
    中读取 4 个字节,并将这些字节解释为一个整数。 如果你按照之前的代码将文件内容合并时,将文件大小以 4 字节整数形式写入到文件中,那么你可以使用
    1. buffer.getInt()
    复制代码
    来读取这个大小。例如,假设你在合并文件时使用了如下方式写入大小:

    1. outputStream.write(ByteBuffer.allocate(4).putInt(content.length).array());
    复制代码

    在读取合并文件时,你可以这样做:

    1. ByteBuffer buffer = ByteBuffer.wrap(fileContent); // 假设 fileContent 是读取的字节数组
    2. int size = buffer.getInt(); // 读取前 4 个字节,获取文件大小
    复制代码

    这里的

    1. buffer.getInt()
    复制代码
    会正确读取到前 4 个字节,并将其转换为整数,这样你就得到了文件内容的大小。 请确保在读取文件时,字节顺序(字节序)与写入时一致,默认情况下是大端序(Big Endian)。如果你的应用需要小端序(Little Endian),你可以使用
    1. buffer.order(ByteOrder.LITTLE_ENDIAN)
    复制代码
    来设置字节序。

    1. package com.et;
    2. import java.io.ByteArrayOutputStream;
    3. import java.io.IOException;
    4. import java.nio.ByteBuffer;
    5. import java.util.ArrayList;
    6. import java.util.Arrays;
    7. import java.util.List;
    8. import java.util.stream.Collectors;
    9. public class FileSplitter {
    10. public static void main(String[] args) {
    11. String mergedFile = "D:/IdeaProjects/Java-demo/file/src/main/resources/merge.keystore";
    12. split(mergedFile);
    13. }
    14. private static void debugContent(byte[] content, String fileName) {
    15. System.out.printf("File: %s%n", fileName);
    16. System.out.printf("Length: %d%n", content.length);
    17. System.out.print("Content: ");
    18. for (byte b : content) {
    19. System.out.printf("%02X ", b);
    20. }
    21. System.out.println();
    22. }
    23. static String[] split(String mergedFile) {
    24. String directoryPath = FileUtils.extractDirectoryPath(mergedFile);
    25. String privateKeysFile = directoryPath + ".privateKeys.keystore";
    26. String publicCertsFile = directoryPath + ".publicCerts.keystore";
    27. String[] filePaths = new String[]{privateKeysFile, publicCertsFile};
    28. try {
    29. // read merge content
    30. byte[] mergedContent = FileUtils.readBinaryFile(mergedFile);
    31. // use ByteBuffer parse
    32. ByteBuffer buffer = ByteBuffer.wrap(mergedContent);
    33. // read privateKeys content length
    34. int privateKeysLength = buffer.getInt();
    35. // read privateKeys content
    36. byte[] privateKeysContent = new byte[privateKeysLength];
    37. buffer.get(privateKeysContent);
    38. // read publicCerts content length
    39. int publicCertsLength = buffer.getInt();
    40. // read publicCerts content
    41. byte[] publicCertsContent = new byte[publicCertsLength];
    42. buffer.get(publicCertsContent);
    43. // write privateKeys and publicCerts content to file
    44. FileUtils.writeBinaryFile(privateKeysFile, privateKeysContent);
    45. FileUtils.writeBinaryFile(publicCertsFile, publicCertsContent);
    46. System.out.println("merge file split " + privateKeysFile + " and " + publicCertsFile);
    47. } catch (IOException e) {
    48. e.printStackTrace();
    49. }
    50. return filePaths;
    51. }
    52. private static byte[] extractContent(byte[] mergedContent, byte[] beginMarker, byte[] endMarker) {
    53. int beginIndex = indexOf(mergedContent, beginMarker);
    54. int endIndex = indexOf(mergedContent, endMarker, beginIndex);
    55. if (beginIndex != -1 && endIndex != -1) {
    56. // Move past the start marker
    57. beginIndex += beginMarker.length;
    58. // Adjust endIndex to exclude the end marker
    59. int adjustedEndIndex = endIndex;
    60. // Extract content
    61. return Arrays.copyOfRange(mergedContent, beginIndex, adjustedEndIndex);
    62. } else {
    63. return new byte[0]; // Return empty array if markers are not found
    64. }
    65. }
    66. private static byte[] removeEmptyLines(byte[] content) {
    67. // Convert byte array to list of lines
    68. List<byte[]> lines = splitIntoLines(content);
    69. // Filter out empty lines
    70. lines = lines.stream()
    71. .filter(line -> line.length > 0)
    72. .collect(Collectors.toList());
    73. // Reassemble content
    74. return mergeLines(lines);
    75. }
    76. private static List<byte[]> splitIntoLines(byte[] content) {
    77. List<byte[]> lines = new ArrayList<>();
    78. int start = 0;
    79. for (int i = 0; i < content.length; i++) {
    80. if (content[i] == '\n') { // Line break
    81. lines.add(Arrays.copyOfRange(content, start, i));
    82. start = i + 1;
    83. }
    84. }
    85. if (start < content.length) {
    86. lines.add(Arrays.copyOfRange(content, start, content.length));
    87. }
    88. return lines;
    89. }
    90. private static byte[] mergeLines(List<byte[]> lines) {
    91. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    92. for (byte[] line : lines) {
    93. try {
    94. outputStream.write(line);
    95. outputStream.write('\n'); // Re-add line break
    96. } catch (IOException e) {
    97. e.printStackTrace();
    98. }
    99. }
    100. return outputStream.toByteArray();
    101. }
    102. private static int indexOf(byte[] array, byte[] target) {
    103. return indexOf(array, target, 0);
    104. }
    105. private static int indexOf(byte[] array, byte[] target, int start) {
    106. for (int i = start; i <= array.length - target.length; i++) {
    107. if (Arrays.equals(Arrays.copyOfRange(array, i, i + target.length), target)) {
    108. return i;
    109. }
    110. }
    111. return -1; // Return -1 if target not found
    112. }
    113. }
    复制代码

    工具类

    1. package com.et;
    2. import java.io.File;
    3. import java.io.FileInputStream;
    4. import java.io.FileOutputStream;
    5. import java.io.IOException;
    6. public class FileUtils {
    7. static byte[] readBinaryFile(String filePath) throws IOException {
    8. File file = new File(filePath);
    9. try (FileInputStream fis = new FileInputStream(file)) {
    10. byte[] fileBytes = new byte[(int) file.length()];
    11. fis.read(fileBytes);
    12. return fileBytes;
    13. }
    14. }
    15. public static String extractDirectoryPath(String filePath) {
    16. File file = new File(filePath);
    17. return file.getParent()+File.separator; // 获取文件所在的目录
    18. }
    19. static void writeBinaryFile(String filePath, byte[] content) throws IOException {
    20. try (FileOutputStream fos = new FileOutputStream(filePath)) {
    21. fos.write(content);
    22. }
    23. }
    24. }
    复制代码

    以上只是一些关键代码,所有代码请参见下面代码仓库

    代码仓库

    • https://github.com/Harries/Java-demo(file)

    3.测试

    测试类

    1. package com.et;
    2. public class Main {
    3. public static void main(String[] args) {
    4. System.out.println("Hello world!");
    5. String privateKeys = "D:/IdeaProjects/Java-demo/file/src/main/resources/privateKeys.keystore";
    6. String publicCerts = "D:/IdeaProjects/Java-demo/file/src/main/resources/publicCerts.keystore";
    7. FileMerger.merger(privateKeys,publicCerts);
    8. String mergedFile = "D:/IdeaProjects/Java-demo/file/src/main/resources/merge.keystore";
    9. FileSplitter.split(mergedFile);
    10. }
    11. }
    复制代码

    运行main方法,日志显示如下

    1. merge success D:\IdeaProjects\Java-demo\file\src\main\resources\merge.keystore
    2. merge file split D:\IdeaProjects\Java-demo\file\src\main\resources\.privateKeys.keystore and D:\IdeaProjects\Java-demo\file\src\main\resources\.publicCerts.keystore
    复制代码

    拆分后文件于原文件大小一模一样

    1.webp

    以上就是Java使用ByteBuffer进行多文件合并和拆分的代码实现的详细内容,更多关于Java ByteBuffer文件合并和拆分的资料请关注晓枫资讯其它相关文章!


    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
    晓枫资讯-科技资讯社区-免责声明
    免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
          1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
          2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
          3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
          4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
          5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
    http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

      离线 

    TA的专栏

    等级头衔

    等級:晓枫资讯-列兵

    在线时间
    0 小时

    积分成就
    威望
    0
    贡献
    0
    主题
    0
    精华
    0
    金钱
    12
    积分
    4
    注册时间
    2025-1-7
    最后登录
    2025-1-7

    发表于 2025-1-23 18:12:31 | 显示全部楼层
    感谢楼主分享。
    http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

      离线 

    TA的专栏

    等级头衔

    等級:晓枫资讯-列兵

    在线时间
    0 小时

    积分成就
    威望
    0
    贡献
    0
    主题
    0
    精华
    0
    金钱
    11
    积分
    2
    注册时间
    2024-10-29
    最后登录
    2024-10-29

    发表于 3 天前 | 显示全部楼层
    路过,支持一下
    http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
    严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    1楼
    2楼
    3楼

    手机版|晓枫资讯--科技资讯社区 本站已运行

    CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

    晓枫资讯--科技资讯社区

    本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

    如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

    Powered by Discuz! X3.5

    快速回复 返回顶部 返回列表