Java 字节数组替换所有出现的字节数组/字符串



是否有任何"已经实现"(非手动)的方法可以替换字节数组内所有出现的单字节数组/字符串?我有一个情况,我需要创建包含平台相关文本的字节数组(Linux(换行)、Windows(回车 + 换行))。我知道这样的任务可以手动实现,但我正在寻找开箱即用的解决方案。请注意,这些字节数组很大,在我的情况下,解决方案需要具有性能智慧。另请注意,我正在处理大量这些字节数组。

我目前的方法:

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

此方法在性能上不明智,因为创建新的字符串并使用正则表达式来查找匹配项。我知道由于Windows编码,手动实现需要查看字节序列。因此,手动实施也需要重新分配(如果需要)。

Appache common lang utils 包含ArrayUtils其中包含 method
byte[] removeAllOccurrences(byte[] array, byte element)。是否有任何第三方库包含类似的方法来替换字节数组内出现的所有字节数组/字符串?

编辑:正如@saka1029评论中提到的,我的方法不适用于Windows操作系统类型。由于这个错误,我需要坚持使用正则表达式,如下所示:

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

这样,对于 Windows 情况,仅搜索没有前面的 '\r' 的 '' 并替换为 '\r'(正则表达式被修改为直接在 '' 而不是 [^\r] 位置查找组,否则也会从行中提取最后一个字母)。这样的工作流程不能使用常规方法实现,因此使这个问题无效。

如果您正在阅读文本,则应将其视为文本,而不是字节。 使用缓冲读取器逐行读取,并插入自己的换行符序列。

String newline = schemeModel.getOsType() == SystemTypes.LINUX ? "n" : "rn";
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);
}
}

不需要字节数组,并且您只使用少量内存 — 保存遇到的最大行所需的内存量。 (我很少看到行长超过一千字节的文本,但即使是一兆字节也是一个相当小的内存需求。

如果您正在"修复"zip条目,则输出流可以是指向新ZipEntry的ZipOutputStream:

String newline = schemeModel.getOsType() == SystemTypes.LINUX ? "n" : "rn";
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 ? "rn" : "n"
  • 代码包含new String(byteArray)假定资源的字节使用运行程序的系统的默认字符集。 我怀疑这不是你的意图; 我已经在InputStreamReader的构造中添加了StandardCharsets.UTF_8来解决这个问题。 如果您确实打算使用默认 Charset 读取字节,则可以删除第二个构造函数参数。

最新更新