字节数组在java文件中没有覆盖,

时间:2016-10-14 20:50:12

标签: java arrays fileoutputstream

下面的代码从HTTP请求中获取一个字节数组并将其保存在bytes []中,最终数据将保存在message []中。

我通过将其转换为String []来检查它是否包含标题,如果我这样做,我会从标题中读取一些信息,然后通过将标题之后的字节保存到message []来将其剪掉。

然后我尝试使用FileOutputStream将message []输出到文件,它稍微有效,但只保存10KB的信息,while循环的一次迭代,(似乎是覆盖),如果我设置了FileOutputStream(文件,真的)附加信息,它工作...一次,然后文件刚刚添加到我下次运行它,这不是我想要的。如何在每次迭代中使用多个字节块写入同一文件,但如果再次运行程序,仍然会完整地覆盖文件?

byte bytes[] = new byte[(10*1024)];
            while (dis.read(bytes) > 0)
            {
                //Set all the bytes to the message
                byte message[] = bytes;
                String string = new String(bytes, "UTF-8");

                //Does bytes contain header?
                if (string.contains("\r\n\r\n")){
                    String theByteString[] = string.split("\r\n\r\n");
                    String theHeader = theByteString[0];
                    String[] lmTemp = theHeader.split("Last-Modified: ");
                    String[] lm = lmTemp[1].split("\r\n");
                    String lastModified = lm[0];
                    //Cut off the header and save the rest of the data after it
                    message = theByteString[1].getBytes("UTF-8");

                    //cache
                    hm.put(url, lastModified);
                }

                //Output message[] to file.
                File f = new File(hostName + path);
                f.getParentFile().mkdirs(); 
                f.createNewFile();
                try (FileOutputStream fos = new FileOutputStream(f)) {
                    fos.write(message);
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }

            }
        }

3 个答案:

答案 0 :(得分:5)

您在循环的每次迭代中打开一个新的FileOutputStream。不要这样做。在外部循环中打开它,然后循环并按原样写入,然后在循环结束时关闭。 (如果您使用带有while循环的try-with-resources语句,那就没问题了。)

这只是问题的一部分 - 你还在循环的每次迭代中也做其他一切,包括检查标题。如果您读取的字节数组包含标题集的 part ,或者标题分隔符的 part ,则这将成为一个真正的问题。

此外,正如EJP所指出的那样,除了使用它来判断你是否完成之外,你忽略了read的返回值。你应该总是使用read的返回值来知道有多少字节数组是实际可用的数据。

从根本上说,您需要将整个响应读入字节数组才能开始 - 这很容易做到,但在内存中可能效率低下 - 或接受您的事实处理流,并编写更复杂的代码来检测标题的结尾。

更好的是,IMO将使用一个HTTP库,已经了解所有这些标头处理,因此您不需要自己完成。除非你自己编写一个低级HTTP库,否则你不应该处理低级HTTP细节,你应该依赖一个好的库。

答案 1 :(得分:1)

在循环之前打开文件。

注意,您需要将read()的结果存储在变量中,并将该变量作为长度传递给new String()。否则,您将缓冲区中的垃圾转换为实际读取的垃圾。

答案 2 :(得分:0)

读取数据存在问题 - 您只读取部分响应(因为此时并非所有数据都转移给您) - 所以您很可能只编写该部分。

检查此答案,了解如何从InputStream中读取完整数据:

Convert InputStream to byte array in Java