Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java InputStream返回意外的-1/空_Java - Fatal编程技术网

Java InputStream返回意外的-1/空

Java InputStream返回意外的-1/空,java,Java,我的文件似乎总是有一个意想不到的结尾。我的文件首先包含两个字符串,然后是字节数据 该文件包含几个单独的字符串,我的代码可以正确读取这些字符串 但是,当我开始读取字节时,它不会返回任何内容。我很确定这与我使用阅读器有关。BufferedReader是否读取整个流?如果是,我如何解决这个问题 我已经检查了这个文件,它确实在字符串后面包含了大量的数据 InputStreamReader is = new InputStreamReader(in); BufferedReader br = new Bu

我的文件似乎总是有一个意想不到的结尾。我的文件首先包含两个字符串,然后是字节数据

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

但是,当我开始读取字节时,它不会返回任何内容。我很确定这与我使用阅读器有关。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:

您不能将
输入流
包装在
缓冲读取器
中并同时使用这两种读取器

顾名思义,
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!!! ]