簡體   English   中英

Java 字節數組替換所有出現的字節數組/字符串

[英]Java byte array replace all occurrences of byte-array/string

是否有任何“已經實現”(非手動)的方法來替換字節數組中所有出現的單字節數組/字符串? 我有一個案例,我需要創建包含平台相關文本的字節數組(Linux(換行)、Windows(回車+換行))。 我知道這樣的任務可以手動實現,但我正在尋找開箱即用的解決方案。 請注意,這些字節數組很大,在我的情況下,解決方案需要性能方面。 另請注意,我正在處理大量這些字節數組。

我目前的做法:

var byteArray = resourceLoader.getResource("classpath:File.txt").getInputStream().readAllBytes();
byteArray = new String(byteArray)
    .replaceAll((schemeModel.getOsType() == SystemTypes.LINUX) ? "\r\n" : "\n",
                (schemeModel.getOsType() == SystemTypes.LINUX) ? "\n" : "\r\n"
    ).getBytes(StandardCharsets.UTF_8);

由於創建新字符串並使用正則表達式查找事件,這種方法在性能上並不明智。 我知道手動實現需要查看字節序列,因為 Windows 編碼。 因此,手動實施也需要重新分配(如果需要)。

Appache common lang utils包含ArrayUtils ,其中包含方法
byte[] removeAllOccurrences(byte[] array, byte element) 是否有任何第三方庫包含類似的方法來替換字節數組中出現的所有字節數組/字符串?

編輯:正如評論中提到的@saka1029,我的方法不適用於 Windows 操作系統類型。 由於這個錯誤,我需要堅持使用正則表達式,如下所示:

(schemeModel.getOsType() == SystemTypes.LINUX) ? "\\r\\n" : "[?:^\\r]\\n", 
(schemeModel.getOsType() == SystemTypes.LINUX) ? "\n" : "\r\n")

這樣,對於 windows 情況,僅搜索不帶前面 '\r' 的 '\n' 的出現並用 '\r\n' 替換(修改正則表達式以在 '\n' 處而不是 [^\r] 處查找組\n position 直接,否則行中的最后一個字母也會被提取)。 這種工作流程無法使用傳統方法實現,因此使這個問題無效。

如果您正在閱讀文本,則應將其視為文本,而不是字節。 使用BufferedReader 逐行讀取行,並插入您自己的換行符序列。

String newline = schemeModel.getOsType() == SystemTypes.LINUX ? "\n" : "\r\n";

OutputStream out = /* ... */;

try (Writer writer = new BufferedWriter(
        new OutputStreamWriter(out, StandardCharsets.UTF_8));
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            resourceLoader.getResource("classpath:File.txt").getInputStream(),
            StandardCharsets.UTF_8))) {

    String line;
    while ((line = reader.readLine()) != null) {
        writer.write(line);
        writer.write(newline);
    }
}

不需要字節數組,並且您只使用少量內存——容納遇到的最大行所需的內存量。 (我很少看到行長超過 1 KB 的文本,但即使是 1 兆字節也是一個非常小的 memory 要求。)

如果您正在“修復” zip 條目,則 OutputStream 可以是指向新 ZipEntry 的 ZipOutputStream:

String newline = schemeModel.getOsType() == SystemTypes.LINUX ? "\n" : "\r\n";

ZipInputStream oldZip = /* ... */;
ZipOutputStream newZip = /* ... */;

ZipEntry entry;
while ((entry = oldZip.getNextEntry()) != null) {
    newZip.putNextEntry(entry);

    // We only want to fix line endings in text files.
    if (!entry.getName().matches(".*\\." +
        "(?i:txt|x?html?|xml|json|[ch]|cpp|cs|py|java|properties|jsp)")) {

        oldZip.transferTo(newZip);
        continue;
    }

    Writer writer = new BufferedWriter(
        new OutputStreamWriter(newZip, StandardCharsets.UTF_8));

    BufferedReader reader = new BufferedReader(
        new InputStreamReader(oldZip, StandardCharsets.UTF_8));

    String line;
    while ((line = reader.readLine()) != null) {
        writer.write(line);
        writer.write(newline);
    }

    writer.flush();
}
    

一些注意事項:

  • 您是否故意忽略 Mac(以及其他既不是 Windows 也不是 Linux 的操作系統)? 您應該為除 Windows 之外的所有內容假設\n schemeModel.getOsType() == SystemTypes.WINDOWS? "\r\n": "\n" schemeModel.getOsType() == SystemTypes.WINDOWS? "\r\n": "\n"
  • 您的代碼包含new String(byteArray) ,它假定資源的字節使用運行程序的系統的默認字符集。 我懷疑這不是您想要的; 我在 InputStreamReader 的構造中添加了StandardCharsets.UTF_8來解決這個問題。 如果您真的打算使用默認字符集讀取字節,則可以刪除第二個構造函數參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM