
离线 TA的专栏
- 打卡等级:热心大叔
- 打卡总天数:221
- 打卡月天数:0
- 打卡总奖励:3252
- 最近打卡:2025-09-12 09:43:26
|
目录1.背景
因为验证证书的需要,需要把证书文件和公钥给到客户,考虑到多个文件交互的不便性,所以决定将2个文件合并成一个文件交互给客户。刚开始采用字符串拼接2个文件内容,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,最后采用基于二进制流拆分和合并文件,效果不错!
2.代码工程
实验目的
合并代码
- ByteBuffer.allocate(4).putInt(publicCertsContent.length).array()
复制代码的作用是将 (公钥证书内容)的长度转换为 4 个字节的整数,并写入到字节缓冲区中。具体作用如下:
- : 创建一个大小为 4 字节的,因为 Java 中的整数()是 4 个字节。
- putInt(publicCertsContent.length)
复制代码 : 将的字节数组长度(即证书文件的字节长度)存入。这样就把证书内容的长度存储为一个 4 字节的整数。- : 将转换为字节数组。这个数组包含了公钥证书内容长度的 4 字节表示形式。
这个表达式的作用是将 数组的长度转换为二进制的 4 字节表示形式,并写入输出流( )中。这样在以后读取合并文件时,代码可以知道该读取多少字节属于 。
有小伙伴这里可能有疑问,4字节够存多大数字呢?
4 个字节(即 32 位)在计算机中用于存储整数,能表示的整数范围如下:
- 有符号整数(类型):
- 范围是:-2,147,483,648 到 2,147,483,647
- 其中 1 位用于符号(正负),31 位用于数值。
- 无符号整数(,Java 中没有直接支持,但可以通过转换处理):
通常 Java 中的 类型是 有符号的,因此 4 个字节可以存储的整数范围为 -2^31 到 2^31 - 1,即 -2,147,483,648 到 2,147,483,647。所以只要不超过这个限制都能存下来
- package com.et;
-
-
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.nio.ByteBuffer;
-
-
- public class FileMerger {
-
- public static void main(String[] args) {
- String privateKeys = "D:/IdeaProjects/Java-demo/file/src/main/resources/privateKeys.keystore";
- String publicCerts = "D:/IdeaProjects/Java-demo/file/src/main/resources/publicCerts.keystore";
- merger(privateKeys,publicCerts);
-
- }
- public static String merger(String privateKeys, String publicCerts) {
- String directoryPath = FileUtils.extractDirectoryPath(privateKeys);
- String mergedFile =directoryPath+"merge.keystore";
-
- try {
- byte[] privateKeysContent = FileUtils.readBinaryFile(privateKeys);
- byte[] publicCertsContent = FileUtils.readBinaryFile(publicCerts);
-
-
- // create outputStream
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
- // write keystore length(4 byte)
- outputStream.write(ByteBuffer.allocate(4).putInt(privateKeysContent.length).array());
-
- // write keystore content
- outputStream.write(privateKeysContent);
-
- // witer license content(4 byte int )
- outputStream.write(ByteBuffer.allocate(4).putInt(publicCertsContent.length).array());
-
- // write license content
- outputStream.write(publicCertsContent);
-
- // write merge content to file
- FileUtils.writeBinaryFile(mergedFile, outputStream.toByteArray());
-
- System.out.println("merge success " + mergedFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return mergedFile;
- }
-
-
-
- }
复制代码
拆分代码
拆分逻辑就很简单了,先读取4字节,获取文件大小,然后依次获取文件内容就可以了 可以正确读取文件中的大小信息。具体来说,它会从 中读取 4 个字节,并将这些字节解释为一个整数。 如果你按照之前的代码将文件内容合并时,将文件大小以 4 字节整数形式写入到文件中,那么你可以使用 来读取这个大小。例如,假设你在合并文件时使用了如下方式写入大小:
- outputStream.write(ByteBuffer.allocate(4).putInt(content.length).array());
复制代码
在读取合并文件时,你可以这样做:
- ByteBuffer buffer = ByteBuffer.wrap(fileContent); // 假设 fileContent 是读取的字节数组
- int size = buffer.getInt(); // 读取前 4 个字节,获取文件大小
复制代码
这里的 会正确读取到前 4 个字节,并将其转换为整数,这样你就得到了文件内容的大小。 请确保在读取文件时,字节顺序(字节序)与写入时一致,默认情况下是大端序(Big Endian)。如果你的应用需要小端序(Little Endian),你可以使用 - buffer.order(ByteOrder.LITTLE_ENDIAN)
复制代码来设置字节序。
- package com.et;
-
-
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Collectors;
-
-
- public class FileSplitter {
-
- public static void main(String[] args) {
- String mergedFile = "D:/IdeaProjects/Java-demo/file/src/main/resources/merge.keystore";
- split(mergedFile);
-
- }
- private static void debugContent(byte[] content, String fileName) {
- System.out.printf("File: %s%n", fileName);
- System.out.printf("Length: %d%n", content.length);
- System.out.print("Content: ");
- for (byte b : content) {
- System.out.printf("%02X ", b);
- }
- System.out.println();
- }
- static String[] split(String mergedFile) {
- String directoryPath = FileUtils.extractDirectoryPath(mergedFile);
- String privateKeysFile = directoryPath + ".privateKeys.keystore";
- String publicCertsFile = directoryPath + ".publicCerts.keystore";
- String[] filePaths = new String[]{privateKeysFile, publicCertsFile};
-
- try {
- // read merge content
- byte[] mergedContent = FileUtils.readBinaryFile(mergedFile);
-
- // use ByteBuffer parse
- ByteBuffer buffer = ByteBuffer.wrap(mergedContent);
-
- // read privateKeys content length
- int privateKeysLength = buffer.getInt();
-
- // read privateKeys content
- byte[] privateKeysContent = new byte[privateKeysLength];
- buffer.get(privateKeysContent);
-
- // read publicCerts content length
- int publicCertsLength = buffer.getInt();
-
- // read publicCerts content
- byte[] publicCertsContent = new byte[publicCertsLength];
- buffer.get(publicCertsContent);
-
- // write privateKeys and publicCerts content to file
- FileUtils.writeBinaryFile(privateKeysFile, privateKeysContent);
- FileUtils.writeBinaryFile(publicCertsFile, publicCertsContent);
-
- System.out.println("merge file split " + privateKeysFile + " and " + publicCertsFile);
-
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- return filePaths;
- }
-
-
-
-
-
-
- private static byte[] extractContent(byte[] mergedContent, byte[] beginMarker, byte[] endMarker) {
- int beginIndex = indexOf(mergedContent, beginMarker);
- int endIndex = indexOf(mergedContent, endMarker, beginIndex);
-
- if (beginIndex != -1 && endIndex != -1) {
- // Move past the start marker
- beginIndex += beginMarker.length;
-
- // Adjust endIndex to exclude the end marker
- int adjustedEndIndex = endIndex;
-
- // Extract content
- return Arrays.copyOfRange(mergedContent, beginIndex, adjustedEndIndex);
- } else {
- return new byte[0]; // Return empty array if markers are not found
- }
- }
-
-
- private static byte[] removeEmptyLines(byte[] content) {
- // Convert byte array to list of lines
- List<byte[]> lines = splitIntoLines(content);
-
- // Filter out empty lines
- lines = lines.stream()
- .filter(line -> line.length > 0)
- .collect(Collectors.toList());
-
- // Reassemble content
- return mergeLines(lines);
- }
-
- private static List<byte[]> splitIntoLines(byte[] content) {
- List<byte[]> lines = new ArrayList<>();
- int start = 0;
-
- for (int i = 0; i < content.length; i++) {
- if (content[i] == '\n') { // Line break
- lines.add(Arrays.copyOfRange(content, start, i));
- start = i + 1;
- }
- }
-
- if (start < content.length) {
- lines.add(Arrays.copyOfRange(content, start, content.length));
- }
-
- return lines;
- }
-
- private static byte[] mergeLines(List<byte[]> lines) {
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- for (byte[] line : lines) {
- try {
- outputStream.write(line);
- outputStream.write('\n'); // Re-add line break
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return outputStream.toByteArray();
- }
-
- private static int indexOf(byte[] array, byte[] target) {
- return indexOf(array, target, 0);
- }
-
- private static int indexOf(byte[] array, byte[] target, int start) {
- for (int i = start; i <= array.length - target.length; i++) {
- if (Arrays.equals(Arrays.copyOfRange(array, i, i + target.length), target)) {
- return i;
- }
- }
- return -1; // Return -1 if target not found
- }
-
-
-
-
-
-
- }
复制代码
工具类
- package com.et;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
-
- public class FileUtils {
-
- static byte[] readBinaryFile(String filePath) throws IOException {
- File file = new File(filePath);
- try (FileInputStream fis = new FileInputStream(file)) {
- byte[] fileBytes = new byte[(int) file.length()];
- fis.read(fileBytes);
- return fileBytes;
- }
- }
- public static String extractDirectoryPath(String filePath) {
- File file = new File(filePath);
- return file.getParent()+File.separator; // 获取文件所在的目录
- }
- static void writeBinaryFile(String filePath, byte[] content) throws IOException {
- try (FileOutputStream fos = new FileOutputStream(filePath)) {
- fos.write(content);
- }
- }
- }
复制代码
以上只是一些关键代码,所有代码请参见下面代码仓库
代码仓库
- https://github.com/Harries/Java-demo(file)
3.测试
测试类
- package com.et;
-
- public class Main {
- public static void main(String[] args) {
- System.out.println("Hello world!");
- String privateKeys = "D:/IdeaProjects/Java-demo/file/src/main/resources/privateKeys.keystore";
- String publicCerts = "D:/IdeaProjects/Java-demo/file/src/main/resources/publicCerts.keystore";
- FileMerger.merger(privateKeys,publicCerts);
- String mergedFile = "D:/IdeaProjects/Java-demo/file/src/main/resources/merge.keystore";
- FileSplitter.split(mergedFile);
- }
- }
复制代码
运行main方法,日志显示如下
- merge success D:\IdeaProjects\Java-demo\file\src\main\resources\merge.keystore
- merge file split D:\IdeaProjects\Java-demo\file\src\main\resources\.privateKeys.keystore and D:\IdeaProjects\Java-demo\file\src\main\resources\.publicCerts.keystore
复制代码
拆分后文件于原文件大小一模一样
以上就是Java使用ByteBuffer进行多文件合并和拆分的代码实现的详细内容,更多关于Java ByteBuffer文件合并和拆分的资料请关注晓枫资讯其它相关文章! 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|