我有一个由“\ n \ n”分成两部分的文件 - 第一部分不是太长字符串,第二部分是字节数组,可能很长。
我正在尝试按如下方式阅读该文件:
byte[] result;
try (final FileInputStream fis = new FileInputStream(file)) {
final InputStreamReader isr = new InputStreamReader(fis);
final BufferedReader reader = new BufferedReader(isr);
String line;
// reading until \n\n
while (!(line = reader.readLine()).trim().isEmpty()){
// processing the line
}
// copying the rest of the byte array
result = IOUtils.toByteArray(reader);
reader.close();
}
即使生成的数组应该是它的大小,它的内容也会被破坏。如果我尝试直接在toByteArray
或fis
上使用isr
,则结果内容为空。
如何正确有效地阅读文件的其余部分?
谢谢!
答案 0 :(得分:1)
您的内容被破坏的原因是因为IOUtils.toByteArray(...)
函数将您的数据作为默认字符编码中的字符串读取,即它使用您的默认编码规定的任何逻辑将8位二进制值转换为文本字符。这通常会导致许多二进制值被破坏。
根据字符集的确切实现方式,这可能会有一些可能:
result = IOUtils.toByteArray(reader, "ISO-8859-1");
ISO-8859-1每个字符仅使用一个字节。并非所有字符值都已定义,但许多实现仍会传递它们。也许你很幸运。
但更清晰的解决方案是首先将二进制数据首先读取为二进制数据,然后通过new String(bytes)
将其转换为文本,而不是将结尾处的二进制数据作为字符串读取然后转换它回来。
但这可能意味着您需要为性能目的实现自己版本的BufferedReader。
您可以通过明显的Google搜索找到标准BufferedReader的源代码,这将(例如)引导您到这里:
http://www.docjar.com/html/api/java/io/BufferedReader.java.html
它有点长,但在概念上并不太难理解,所以希望它可以作为参考。
答案 1 :(得分:1)
或者,您可以将文件读入字节数组,找到\ n \ n位置并将数组拆分为行和字节
byte[] a = Files.readAllBytes(Paths.get("file"));
String line = "";
byte[] result = a;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] == '\n' && a[i + 1] == '\n') {
line = new String(a, 0, i);
int len = a.length - i - 1;
result = new byte[len];
System.arraycopy(a, i + 1, result, 0, len);
break;
}
}
答案 2 :(得分:0)
感谢所有评论 - 最终实施以这种方式完成:
try (final FileInputStream fis = new FileInputStream(file)) {
ByteBuffer buffer = ByteBuffer.allocate(64);
boolean wasLast = false;
String headerValue = null, headerKey = null;
byte[] result = null;
while (true) {
byte current = (byte) fis.read();
if (current == '\n') {
if (wasLast) {
// this is \n\n
break;
} else {
// just a new line in header
wasLast = true;
headerValue = new String(buffer.array(), 0, buffer.position()));
buffer.clear();
}
} else if (current == '\t') {
// headerKey\theaderValue\n
headerKey = new String(buffer.array(), 0, buffer.position());
buffer.clear();
} else {
buffer.put(current);
wasLast = false;
}
}
// reading the rest
result = IOUtils.toByteArray(fis);
}