3

我下面的代码只解析一次数据文件。我试图让它解析整个文件。每次找到标记时,解析数据并将其附加到输出文件中。目前它成功解析数据一次然后停止。无法弄清楚如何让它循环直到 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();
 }
 }
4

3 回答 3

6
markerFound = true;

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

for (int offset = 0; !markerFound && offset < 4; offset++)
于 2013-06-06T17:31:16.870 回答
1

第一件事

您正在打开文件中的文件for,因此,读取总是从文件的开头开始。先把它打开for

第二

由于 test !markerFound && offset < 4,您的循环最多会发生 4 次。

第三

这段代码对我没有意义:

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

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

第四

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

于 2013-06-11T13:37:38.643 回答
0

正如我在之前对您的问题Java 的回答中发布的那样,需要一个 while 循环才能到达 eof。iewhile !eof,继续解析我想再次声明DataInputStream.read()(与其他 readXxX() 方法不同)不会抛出 EOFExcepion.

来自JavaDocs:(继承_DataInputStreamread()FilterInputStream

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

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

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
于 2013-06-14T20:44:44.910 回答