InputStream返回意外的-1 /空

时间:2014-08-08 14:05:10

标签: java

我似乎正在意外结束我的档案。我的文件首先包含几个字符串,然后是字节数据。

该文件包含一些单独的字符串,我的代码可以正确读取。

然而,当我开始读取字节时,它什么都不返回。我很确定它与我使用读者有关。 BufferedReader是否读取整个流?如果是这样,我该如何解决?

我已检查过该文件,并且在字符串后确实包含大量数据。

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: http://www.cs.princeton.edu/~min/binvox/read_binvox.html

5 个答案:

答案 0 :(得分:1)

要阅读整个String,您应该这样做:

ArrayList<String> lines = new ArrayList<String>();
while ((line = br.readLine();) != null) {
    lines.add(line);
}

然后你可以做一个循环来分割每一行,或者只是做你在循环中你必须做的事情。

答案 1 :(得分:1)

正如 icza 已经写了alraedy,你不能创建InputStreamBufferedReader以及用户。 BufferedReader会尽可能多地从InputStream读取,然后您无法从InputStream访问您的数据。

你有几种方法可以解决它:

     
  1. 不要使用任何Reader。自己从InputStream读取字节并在其上调用new String(bytes)。  
  2. 存储您编码的数据(例如Base64)。可以从Reader读取编码数据。我会推荐这个解决方案。这看起来像那样:
public byte[] readBytes (Reader in) throws IOException
{
    String base64 = in.readLine(); // Note that a Base64-representation never contains \n
    byte[] data = Base64.getDecoder().decode(base64);
    return data
}

答案 2 :(得分:0)

您无法将InputStream包裹在BufferedReader中并使用它们。

正如其名称提示的那样,BufferedReader可能会提前读取并缓冲来自基础InputStream的数据,这些数据在直接从基础InputStream读取时将无法使用。

建议的解决方案不是在一个文件中混合文本和二进制数据。它们应存储在2个单独的文件中,然后可以单独阅读。如果剩余数据不是二进制数据,则不应通过InputStream读取它们,而应通过包装器BufferedReader读取它们,就像读取第一行一样。

答案 3 :(得分:0)

我建议创建预先读取一些字节的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();
    }
}

然后,您可以在不触及原始流的情况下检测Binvox版本:

BinvoxDetectorStream bds = new BinvoxDetectorStream(in);
BinvoxInfo info = bds.getBinvoxInfo();
if (info == null) {
    return false;
}
...
[moving bytes in the usual way, but using bds!!! ]

这样我们就可以保留bds中的原始字节,以便我们以后能够复制它。

答案 4 :(得分:0)

我看到别人的代码解决了这个问题。

他/她使用 DataInputStream ,它可以执行 readLine (虽然已弃用)和 readByte