欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用ByteBuffer進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)

 更新時(shí)間:2024年09月22日 08:44:28   作者:HBLOG  
因?yàn)轵?yàn)證證書的需要,需要把證書文件和公鑰給到客戶,考慮到多個(gè)文件交互的不便性,所以決定將2個(gè)文件合并成一個(gè)文件交互給客戶,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,本文給大家介紹了Java使用ByteBuffer進(jìn)行多文件合并和拆分,需要的朋友可以參考下

1.背景

因?yàn)轵?yàn)證證書的需要,需要把證書文件和公鑰給到客戶,考慮到多個(gè)文件交互的不便性,所以決定將2個(gè)文件合并成一個(gè)文件交互給客戶。剛開始采用字符串拼接2個(gè)文件內(nèi)容,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,最后采用基于二進(jìn)制流拆分和合并文件,效果不錯(cuò)!

2.代碼工程

實(shí)驗(yàn)?zāi)康?/h3>

對(duì)文件進(jìn)行二進(jìn)制流合并和拆分

合并代碼

ByteBuffer.allocate(4).putInt(publicCertsContent.length).array() 的作用是將 publicCertsContent(公鑰證書內(nèi)容)的長(zhǎng)度轉(zhuǎn)換為 4 個(gè)字節(jié)的整數(shù),并寫入到字節(jié)緩沖區(qū)中。具體作用如下:

  • ByteBuffer.allocate(4): 創(chuàng)建一個(gè)大小為 4 字節(jié)的 ByteBuffer,因?yàn)?Java 中的整數(shù)(int)是 4 個(gè)字節(jié)。
  • putInt(publicCertsContent.length): 將 publicCertsContent 的字節(jié)數(shù)組長(zhǎng)度(即證書文件的字節(jié)長(zhǎng)度)存入 ByteBuffer。這樣就把證書內(nèi)容的長(zhǎng)度存儲(chǔ)為一個(gè) 4 字節(jié)的整數(shù)。
  • array(): 將 ByteBuffer 轉(zhuǎn)換為字節(jié)數(shù)組。這個(gè)數(shù)組包含了公鑰證書內(nèi)容長(zhǎng)度的 4 字節(jié)表示形式。

這個(gè)表達(dá)式的作用是將 publicCertsContent 數(shù)組的長(zhǎng)度轉(zhuǎn)換為二進(jìn)制的 4 字節(jié)表示形式,并寫入輸出流(outputStream)中。這樣在以后讀取合并文件時(shí),代碼可以知道該讀取多少字節(jié)屬于 publicCertsContent

有小伙伴這里可能有疑問(wèn),4字節(jié)夠存多大數(shù)字呢?

4 個(gè)字節(jié)(即 32 位)在計(jì)算機(jī)中用于存儲(chǔ)整數(shù),能表示的整數(shù)范圍如下:

  • 有符號(hào)整數(shù)(int 類型)
    • 范圍是:-2,147,483,6482,147,483,647
    • 其中 1 位用于符號(hào)(正負(fù)),31 位用于數(shù)值。
  • 無(wú)符號(hào)整數(shù)unsigned int,Java 中沒有直接支持,但可以通過(guò)轉(zhuǎn)換處理):
    • 范圍是:04,294,967,295

通常 Java 中的 int 類型是有符號(hào)的,因此 4 個(gè)字節(jié)可以存儲(chǔ)的整數(shù)范圍為 -2^31 到 2^31 - 1,即 -2,147,483,648 到 2,147,483,647。所以只要不超過(guò)這個(gè)限制都能存下來(lái)

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;
    }



}

拆分代碼

拆分邏輯就很簡(jiǎn)單了,先讀取4字節(jié),獲取文件大小,然后依次獲取文件內(nèi)容就可以了 buffer.getInt() 可以正確讀取文件中的大小信息。具體來(lái)說(shuō),它會(huì)從 ByteBuffer 中讀取 4 個(gè)字節(jié),并將這些字節(jié)解釋為一個(gè)整數(shù)。 如果你按照之前的代碼將文件內(nèi)容合并時(shí),將文件大小以 4 字節(jié)整數(shù)形式寫入到文件中,那么你可以使用 buffer.getInt() 來(lái)讀取這個(gè)大小。例如,假設(shè)你在合并文件時(shí)使用了如下方式寫入大?。?/p>

outputStream.write(ByteBuffer.allocate(4).putInt(content.length).array());

在讀取合并文件時(shí),你可以這樣做:

ByteBuffer buffer = ByteBuffer.wrap(fileContent); // 假設(shè) fileContent 是讀取的字節(jié)數(shù)組
int size = buffer.getInt(); // 讀取前 4 個(gè)字節(jié),獲取文件大小

這里的 buffer.getInt() 會(huì)正確讀取到前 4 個(gè)字節(jié),并將其轉(zhuǎn)換為整數(shù),這樣你就得到了文件內(nèi)容的大小。 請(qǐng)確保在讀取文件時(shí),字節(jié)順序(字節(jié)序)與寫入時(shí)一致,默認(rèn)情況下是大端序(Big Endian)。如果你的應(yīng)用需要小端序(Little Endian),你可以使用 buffer.order(ByteOrder.LITTLE_ENDIAN) 來(lái)設(shè)置字節(jié)序。

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);
        }
    }
}

以上只是一些關(guān)鍵代碼,所有代碼請(qǐng)參見下面代碼倉(cāng)庫(kù)

代碼倉(cāng)庫(kù)

3.測(cè)試

測(cè)試類

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);
    }
}

運(yùn)行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進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Java ByteBuffer文件合并和拆分的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot應(yīng)用訪問(wèn)zookeeper的流程

    springboot應(yīng)用訪問(wèn)zookeeper的流程

    這篇文章主要介紹了springboot應(yīng)用訪問(wèn)zookeeper的流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • spring無(wú)法讀取properties文件數(shù)據(jù)問(wèn)題詳解

    spring無(wú)法讀取properties文件數(shù)據(jù)問(wèn)題詳解

    這篇文章主要介紹了spring無(wú)法讀取properties文件數(shù)據(jù)問(wèn)題詳解,需要的朋友可以參考下
    2020-02-02
  • Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Security是一個(gè)功能強(qiáng)大且高度可定制的身份驗(yàn)證和訪問(wèn)控制框架。它實(shí)際上是保護(hù)基于spring的應(yīng)用程序的標(biāo)準(zhǔn)Spring Security是一個(gè)框架,側(cè)重于為Java應(yīng)用程序提供身份驗(yàn)證和授權(quán),這篇文章主要介紹了Spring Boot中的SpringSecurity學(xué)習(xí),需要的朋友可以參考下
    2023-01-01
  • Mac電腦安裝多個(gè)JDK版本的詳細(xì)圖文教程

    Mac電腦安裝多個(gè)JDK版本的詳細(xì)圖文教程

    目前使用的主流版本還是JDK 8,但偶爾會(huì)想體驗(yàn)下新版本(或者舊版本),如果能裝多個(gè)版本的JDK,而且很方便的切換就好了,這篇文章主要給大家介紹了關(guān)于Mac電腦安裝多個(gè)JDK版本的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Spring Boot Admin實(shí)踐詳解

    Spring Boot Admin實(shí)踐詳解

    在本篇文章里小編給大家整理了關(guān)于Spring Boot Admin實(shí)踐的相關(guān)知識(shí)點(diǎn),有需要的朋友們可以學(xué)習(xí)下。
    2019-12-12
  • SpringBoot通過(guò)自定義注解實(shí)現(xiàn)配置類的自動(dòng)注入的實(shí)現(xiàn)

    SpringBoot通過(guò)自定義注解實(shí)現(xiàn)配置類的自動(dòng)注入的實(shí)現(xiàn)

    本文主要介紹了SpringBoot通過(guò)自定義注解實(shí)現(xiàn)配置類的自動(dòng)注入的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 解決JMap抓取heap使用統(tǒng)計(jì)信息報(bào)錯(cuò)的問(wèn)題

    解決JMap抓取heap使用統(tǒng)計(jì)信息報(bào)錯(cuò)的問(wèn)題

    這篇文章主要介紹了解決JMap抓取heap使用統(tǒng)計(jì)信息報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • spring @AfterReturning返回值問(wèn)題

    spring @AfterReturning返回值問(wèn)題

    這篇文章主要介紹了spring @AfterReturning返回值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 如何用Netty實(shí)現(xiàn)高效的HTTP服務(wù)器

    如何用Netty實(shí)現(xiàn)高效的HTTP服務(wù)器

    這篇文章主要介紹了如何用Netty實(shí)現(xiàn)高效的HTTP服務(wù)器,對(duì)HTTP感興趣的同學(xué)可以參考一下
    2021-04-04
  • 簡(jiǎn)單探索 Java 中的惰性計(jì)算

    簡(jiǎn)單探索 Java 中的惰性計(jì)算

    這篇文章主要介紹了簡(jiǎn)單探索 Java 中的惰性計(jì)算,惰性計(jì)算(盡可能延遲表達(dá)式求值)是許多函數(shù)式編程語(yǔ)言的特性。惰性集合在需要時(shí)提供其元素,無(wú)需預(yù)先計(jì)算它們,這帶來(lái)了一些好處。,需要的朋友可以參考下
    2019-06-06

最新評(píng)論