【问题标题】:Java - Want to parse through eof. Code only parses onceJava - 想要通过 eof 解析。代码只解析一次
【发布时间】:2013-06-02 20:01:08
【问题描述】:

我下面的代码只解析一次数据文件。我试图让它解析整个文件。每次找到标记时,解析数据并将其附加到输出文件中。目前它成功解析数据一次然后停止。无法弄清楚如何让它循环直到 eof。数据是 4 字节对齐的,并且在输入二进制文件中。

 private static void startParse(File inFile) throws IOException {
      boolean markerFound = false;
      for (int offset = 0; !markerFound && offset < 4; offset++){
         DataInputStream dis = new DataInputStream(new FileInputStream(inFile));
         for (int i = 0; i < offset; i++){
             dis.read();
         }
         try {
             int integer;
             long l;
             while((l = (integer = dis.readInt())) != MARKER) {
                 //Don't do anything
             }
             markerFound = true;
             for (int i = 0; i < 11; i++){
                 dis.read();
             }

     // ********************** data **********************          
             byte[] data = new byte[1016];
             for(int i = 0; i < 1016; i++){
             data[i] = (byte) dis.read();
             }

             for (int i = 0; i < 4; i++){
                 dis.read();
             }

     // ***************** output data ********************
             if (checksumCheck(checksum) && fecfCheck(fecf)){
                 FileOutputStream output = new FileOutputStream("ParsedData", true);
            try{
                output.write(data);
            } 
            finally{
                output.close();
            }
        }

    }               
    catch (EOFException eof) {
    }
    dis.close();
 }
 }

【问题讨论】:

  • 你的意思是直到数据结束才解析?
  • 顺便说一句,我建议你使用FileChannel.map()来完成这种工作
  • 是的,文件里面有一段数据,它只解析第一个标记段的数据,文件里大概有50个。我说的是“数据”,因为其余的只是我不关心的垃圾,正在解析我想要的实际“数据”。
  • 您确定标记存在、4 字节对齐且字节顺序正确(小/大端)? markerFound = integer == MARKER;
  • 请附上文件格式的描述。没有它,你的问题没有多大意义。

标签: java parsing eof datainputstream


【解决方案1】:
markerFound = true;

此行不在条件内,将在任何循环出现时执行。
这当然会关闭你的循环,因为:

for (int offset = 0; !markerFound && offset < 4; offset++)

【讨论】:

  • 但是只有找到了标记,它才能退出上面的while循环。否则它会得到一个 eof 异常。如果不是这种情况,那么我可能需要进一步解释,因为我会感到困惑。
【解决方案2】:

第一件事

您在for 中打开文件,因此,读取总是从文件的开头开始。在第一个for之前打开它。

第二

由于测试!markerFound &amp;&amp; offset &lt; 4,您的循环最多会发生 4 次。

第三

这段代码对我来说没有意义:

for (int i = 0; i < offset; i++){
    dis.read();
}

因为offset,在第一次迭代中为0,下一次为1,以此类推。并且该循环不是必需的,您正在使用另一个循环来读取字节,直到到达 MARKER。

第四个

如果您的文件具有固定长度的“记录”并且标记出现在可预测的位置,请使用 DataInputStream skipBytes method 前进到下一个标记。

【讨论】:

    【解决方案3】:

    正如我在之前的 answer 中针对您的问题 Java, need a while loop to reach eof. i.e.while !eof, keep parsing 发布的那样,我想再次声明 DataInputStream.read()(与其他 readXxX() 方法不同)不会抛出 em> EOFExcepion.

    来自JavaDocsDataInputStreamFilterInputStream 继承read()

    如果由于到达流的末尾而没有可用的字节,则返回值 -1

    因此,为了正确检查 EOF,通常在 while 循环中使用 read(byte[]),如下所示:

    int read = 0;
    byte[] b = new byte[1024];
    while ((read = dis.read(b)) != -1) { // returns numOfBytesRead or -1 at EOF
      // fos = FileOutputStream
      fos.write(b, 0, read); // (byte[], offset, numOfBytesToWrite)
    }
    

    回答

    现在,回到您当前的问题;因为,您还没有共享您的二进制文件格式,所以很难提出更好的解析方法。因此,从对嵌套循环当前解析文件方式的有限理解来看;您需要另一个while 循环(如上所述)来读取/解析和复制您的“数据”,直到您找到标记后到达EOF

    markerFound = true;
    for (int i = 0; i < 11; i++){ // move this loop inside while IF
        dis.read(); // these 11 bytes need to be skipped every time
    }
    
    // Open the file just ONCE (outside the loop)
    FileOutputStream output = new FileOutputStream("ParsedData", true);
    
    // ********************** data **********************
    int read = 0;
    byte[] data = new byte[1016]; // set byte buffer size
    
    while ((read = dis.read(data)) != -1) { // read and check for EOF
    
        // ***************** output data ********************
        if (checksumCheck(checksum) && fecfCheck(fecf)) { // if checksum is valid
            output.write(data, 0, read); // write the number of bytes read before
        }
    
        // SKIP four bytes
        for (int i = 0; i < 4; i++) { // or, dis.skipBytes(4); instead of the loop
            dis.read();
        }
     }
    
    // Close the file AFTER input stream reaches EOF
    output.close(); // i.e. all the data has been written
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 2016-04-04
      • 2023-03-17
      相关资源
      最近更新 更多