2012-11-02 14 views
11

W jaki sposób metody mark() i reset() działają dokładnie (w kodzie poniżej), krok po kroku? Próbowałem napisać własny przykład, ale zaczyna się wyrzucać wyjątek z niewłaściwego znaku lub podobny do tego i nie mogę zrozumieć, jaki jest sens umieszczania znaczników i resetowania metod w tym kodzie, ponieważ nie widzę różnicy w tym czy nie.InputStream, mark(), reset()

import java.io.*; 

class BufferedInputStreamDemo { 
    public static void main(String args[]) { 
     String s = "© is a copyright symbol, " 
       + "however &copy isn't.\n"; 
     byte buf[] = s.getBytes(); 

     ByteArrayInputStream in = new ByteArrayInputStream(buf); 
     int c; 
     boolean marked = false; 

     //try_with_resources 
     try (BufferedInputStream f = new BufferedInputStream(in)) { 
      while ((c = f.read()) != -1) { 
       switch (c) { 
        case '&': 
         if (!marked) { 
          f.mark(32); 
          marked = true; 
         } else { 
          marked = false; 
         } 
         break; 
        case ';': 
         if (marked) { 
          marked = false; 
          System.out.print("(c)"); 
         } else 
          System.out.print((char) c); 
         break; 
        case ' ': 
         if (marked) { 
          marked = false; 
          f.reset(); 
          System.out.print("&"); 
         } else 
          System.out.print((char) c); 
         break; 
        default: 
         if (!marked) 
          System.out.print((char) c); 
         break; 
       } 
      } 
     } catch (IOException e) { 
      System.out.println("I/O Error: " + e); 
     } 
    } 
} 
+1

Jaki wyjątek jest zgłaszany? Czy masz ślad stosu? Proszę, bądź dokładny na swoje pytanie. – Lion

+0

Wyrzucanym wyjątkiem jest 'Błąd we/wy: java.io.IOException: Resetting to invalid mark', ale napisałem, że wyjątek jest zgłaszany w innym przykładzie. Głównie pytam, co to jest znak (32) i resetowanie w ** tym przykładzie **. – ashur

+0

@ user1165499 Zobacz moją odpowiedź, aby dowiedzieć się, jak działa ten kod i podejrzewam, że problem występuje w twoim drugim przykładzie. – dan

Odpowiedz

6

Kiedy f.mark(32); jest dotrzeć ed kursor odczytu jest już po &, a znacznik jest ustawiony na reset, aby wiedzieć, gdzie odskoczyć. Po wykryciu, że brakuje elementu ; w celu zamknięcia elementu, należy ręcznie wydrukować & i przesunąć kursor odczytu z powrotem do tyłu (po &, gdzie umieszczono znacznik, używając wywołania mark(32)), używając metody reset. Podczas następnego odczytu, ponieważ zmienna marked nie jest ustawiona, wydrukuje znaki.

mark(32) oznacza, że ​​automatycznie usuwa znacznik, jeśli kursor czytający przesunie się o więcej niż 32 znaki. Może to być problem z innym kodem, który powoduje błąd, ponieważ znacznik został już unieważniony.

4

Zobacz dokumentację API:

mark(int)

Marks the current position in this input stream. A subsequent call to the reset method repositions this stream at the last marked position so that subsequent reads re-read the same bytes.

The readlimit argument tells this input stream to allow that many bytes to be read before the mark position gets invalidated.

This method simply performs in.mark(readlimit).

reset()

Repositions this stream to the position at the time the mark method was last called on this input stream.

This method simply performs in.reset().

Stream marks are intended to be used in situations where you need to read ahead a little to see what's in the stream. Often this is most easily done by invoking some general parser. If the stream is of the type handled by the parse, it just chugs along happily. If the stream is not of that type, the parser should toss an exception when it fails. If this happens within readlimit bytes, it allows the outer code to reset the stream and try another parser.