Java 字节数组替换所有出现的 byte-array/string
Java byte array replace all occurrences of byte-array/string
是否有任何“已经实现”(非手动)的方法来替换字节数组中出现的所有单个 byte-array/string?我有一个案例,我需要创建包含平台相关文本的字节数组(Linux(换行),Windows(回车 return + 换行))。我知道这样的任务可以手动实现,但我正在寻找开箱即用的解决方案。请注意,这些字节数组很大,在我的情况下,解决方案需要在性能方面表现出色。另请注意,我正在处理大量这些字节数组。
我目前的做法:
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 通用语言实用程序包含 ArrayUtils
其中包含方法
byte[] removeAllOccurrences(byte[] array, byte element)
。是否有任何第三方库包含类似的方法来替换字节数组中的 ALL byte-arrays/strings 事件??
编辑:正如@saka1029 在评论中提到的,我的方法不适用于Windows OS 类型。由于这个错误,我需要坚持使用正则表达式如下:
(schemeModel.getOsType() == SystemTypes.LINUX) ? "\r\n" : "[?:^\r]\n",
(schemeModel.getOsType() == SystemTypes.LINUX) ? "\n" : "\r\n")
这样,对于 windows 的情况,只搜索前面没有 '\r' 的 '\n' 并用 '\r\n' 替换(正则表达式被修改为在 ' \n' 不要直接在 [^\r]\n 位置,否则也会提取行中的最后一个字母)。这样的工作流程不能用传统的方法实现,因此这个问题是无效的。
如果您正在阅读文本,则应将其视为文本,而不是字节。使用 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 MB 的内存需求也很小。)
如果您正在“修复”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"
- 您的代码包含
new String(byteArray)
,它假设您的资源字节使用您的程序所在系统的默认字符集 运行。我怀疑这不是你想要的;我已将 StandardCharsets.UTF_8
添加到 InputStreamReader 的构造中以解决此问题。如果您真的想使用默认字符集读取字节,则可以删除第二个构造函数参数。
是否有任何“已经实现”(非手动)的方法来替换字节数组中出现的所有单个 byte-array/string?我有一个案例,我需要创建包含平台相关文本的字节数组(Linux(换行),Windows(回车 return + 换行))。我知道这样的任务可以手动实现,但我正在寻找开箱即用的解决方案。请注意,这些字节数组很大,在我的情况下,解决方案需要在性能方面表现出色。另请注意,我正在处理大量这些字节数组。
我目前的做法:
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 通用语言实用程序包含 ArrayUtils
其中包含方法
byte[] removeAllOccurrences(byte[] array, byte element)
。是否有任何第三方库包含类似的方法来替换字节数组中的 ALL byte-arrays/strings 事件??
编辑:正如@saka1029 在评论中提到的,我的方法不适用于Windows OS 类型。由于这个错误,我需要坚持使用正则表达式如下:
(schemeModel.getOsType() == SystemTypes.LINUX) ? "\r\n" : "[?:^\r]\n",
(schemeModel.getOsType() == SystemTypes.LINUX) ? "\n" : "\r\n")
这样,对于 windows 的情况,只搜索前面没有 '\r' 的 '\n' 并用 '\r\n' 替换(正则表达式被修改为在 ' \n' 不要直接在 [^\r]\n 位置,否则也会提取行中的最后一个字母)。这样的工作流程不能用传统的方法实现,因此这个问题是无效的。
如果您正在阅读文本,则应将其视为文本,而不是字节。使用 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 MB 的内存需求也很小。)
如果您正在“修复”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"
- 您的代码包含
new String(byteArray)
,它假设您的资源字节使用您的程序所在系统的默认字符集 运行。我怀疑这不是你想要的;我已将StandardCharsets.UTF_8
添加到 InputStreamReader 的构造中以解决此问题。如果您真的想使用默认字符集读取字节,则可以删除第二个构造函数参数。