Java InputStream返回意外的-1/空
我的文件似乎总是有一个意想不到的结尾。我的文件首先包含两个字符串,然后是字节数据 该文件包含几个单独的字符串,我的代码可以正确读取这些字符串 但是,当我开始读取字节时,它不会返回任何内容。我很确定这与我使用阅读器有关。BufferedReader是否读取整个流?如果是,我如何解决这个问题 我已经检查了这个文件,它确实在字符串后面包含了大量的数据Java InputStream返回意外的-1/空,java,Java,我的文件似乎总是有一个意想不到的结尾。我的文件首先包含两个字符串,然后是字节数据 该文件包含几个单独的字符串,我的代码可以正确读取这些字符串 但是,当我开始读取字节时,它不会返回任何内容。我很确定这与我使用阅读器有关。BufferedReader是否读取整个流?如果是,我如何解决这个问题 我已经检查了这个文件,它确实在字符串后面包含了大量的数据 InputStreamReader is = new InputStreamReader(in); BufferedReader br = new Bu
InputStreamReader is = new InputStreamReader(in);
BufferedReader br = new BufferedReader(is);
String line;
{
line = br.readLine();
String split[] = line.split(" ");
if (!split[0].equals("#binvox")) {
ErrorHandler.log("Not a binvox file");
return false;
}
ErrorHandler.log("Binvox version: " + split[1]);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead, cnt = 0;
byte[] data = new byte[16384];
while ((nRead = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
cnt += nRead;
}
buffer.flush();
// cnt is always 0
binvox格式如下所示:
#binvox 1
dim 64 40 32
translate -3 0 -2
scale 6.434
data
[byte data]
我基本上是在尝试将以下C代码转换为Java:
您不能将
输入流
包装在缓冲读取器
中并同时使用这两种读取器
顾名思义,BufferedReader
可能会预先读取并缓冲底层InputStream
中的数据,而当直接从底层InputStream
读取时,这些数据将不可用
建议的解决方案是不要在一个文件中混合文本和二进制数据。它们应该存储在两个单独的文件中,然后可以单独读取。如果剩余数据不是二进制数据,则不应通过
InputStream
读取它们,而应像读取第一行一样通过包装器BufferedReader
读取它们。要读取整个字符串,应执行以下操作:
ArrayList<String> lines = new ArrayList<String>();
while ((line = br.readLine();) != null) {
lines.add(line);
}
ArrayList line=new ArrayList();
而((line=br.readLine();)!=null){
行。添加(行);
}
然后你可以做一个循环来分割每一行,或者只是做你在这个循环中必须做的事情。正如icza所写,你不能创建一个InputStream
和一个BufferedReader
和用户。BufferedReader
将从InputStream
读取他想要的数据,然后您就不能从InputStream
访问您的数据
有几种方法可以解决此问题:
不要使用任何读卡器
。自己从InputStream
中读取字节,并在其上调用newString(bytes)
。
存储已编码的数据(例如Base64)。编码数据可以从读取器
读取。我推荐这个解决方案。看起来是这样的:
我建议创建一个预读取一些字节的BinvoxDetectorStream
public class BinvoxDetectorStream extends InputStream {
private InputStream orig;
private byte[] buffer = new byte[4096];
private int buflen;
private int bufpos = 0;
public BinvoxDetectorStream(InputStream in) {
this.orig = new BufferedInputStream(in);
this.buflen = orig.read(this.buffer, 0, this.buffer.length);
}
public BinvoxInfo getBinvoxVersion() {
// creating a reader for the buffered bytes, to read a line, and compare the header
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
BufferedReader rdr = new BufferedReader(new InputStreamReader(bais)));
String line = rdr.readLine();
String split[] = line.split(" ");
if (split[0].equals("#binvox")) {
BinvoxInfo info = new BinvoxInfo();
info.version = split[1];
split = rdr.readLine().split(" ");
[... parse all properties ...]
// seek for "data\r\n" in the buffered data
while(!(bufpos>=6 &&
buffer[bufpos-6] == 'd' &&
buffer[bufpos-5] == 'a' &&
buffer[bufpos-4] == 't' &&
buffer[bufpos-3] == 'a' &&
buffer[bufpos-2] == '\r' &&
buffer[bufpos-1] == '\n') ) {
bufpos++;
}
return info;
}
return null;
}
@Override
public int read() throws IOException {
if(bufpos < buflen) {
return buffer[bufpos++];
}
return orig.read();
}
}
通过这种方式,我们将原始字节保留在bds中,以便以后可以复制。我看到其他人的代码正好解决了这个问题
他/她使用了DataInputStream,它可以执行readLine(尽管已弃用)和readByte。问题是您将文本数据和二进制数据混合在一个文件中。你不应该那样做。如果你没有,你可以单独阅读。但是我没有写文件的说明。不管是谁写的,文件的剩余部分很可能不是二进制的,而是文本。您应该继续使用相同的BufferedReader
读取其余部分,而不是通过底层的InputStream
。文件是否在#binvox
标记后包含二进制或文本数据?我添加了binvox头格式。这里是C的等价物:我能不能只获取字符数据并将其转换为字节?@RobotRock这正是我在那里写的东西——除了它是base64编码的。如果它没有被编码(无论如何),你就不能从不同的平台交换文件,因为它们有不同的编码。我在文件的规范中没有发言权。上面要做的是将字符串获取为base64字节。然而,我想知道,如果我将字符串作为字符数组,是否可以将每个字符转换为字节。@RobotRock这些字符以字节表示,这是正确的,但几乎每个操作系统都使用另一种编码(UTF-8,ISO-8859-15,…),因此在那里存储数据更困难
public class BinvoxDetectorStream extends InputStream {
private InputStream orig;
private byte[] buffer = new byte[4096];
private int buflen;
private int bufpos = 0;
public BinvoxDetectorStream(InputStream in) {
this.orig = new BufferedInputStream(in);
this.buflen = orig.read(this.buffer, 0, this.buffer.length);
}
public BinvoxInfo getBinvoxVersion() {
// creating a reader for the buffered bytes, to read a line, and compare the header
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
BufferedReader rdr = new BufferedReader(new InputStreamReader(bais)));
String line = rdr.readLine();
String split[] = line.split(" ");
if (split[0].equals("#binvox")) {
BinvoxInfo info = new BinvoxInfo();
info.version = split[1];
split = rdr.readLine().split(" ");
[... parse all properties ...]
// seek for "data\r\n" in the buffered data
while(!(bufpos>=6 &&
buffer[bufpos-6] == 'd' &&
buffer[bufpos-5] == 'a' &&
buffer[bufpos-4] == 't' &&
buffer[bufpos-3] == 'a' &&
buffer[bufpos-2] == '\r' &&
buffer[bufpos-1] == '\n') ) {
bufpos++;
}
return info;
}
return null;
}
@Override
public int read() throws IOException {
if(bufpos < buflen) {
return buffer[bufpos++];
}
return orig.read();
}
}
BinvoxDetectorStream bds = new BinvoxDetectorStream(in);
BinvoxInfo info = bds.getBinvoxInfo();
if (info == null) {
return false;
}
...
[moving bytes in the usual way, but using bds!!! ]