Anzitutto, il compilatore (javac) serve a compilare (ottenere i file .class), mentre l'esecutore (java, la JVM) serve ad eseguire.
Chi lancia una NullPointerException non è il compilatore, ma l'esecutore.
E' bene avere chiaro fin da subito la differenza fra le due fasi: compilazione ed esecuzione.
In secondo luogo, lo StringTokenizer può andare benissimo... ma va usato secondo logica (premetto che non ho guardato cosa vi fai con lo StringTokenizer, mi sono solo occupato della NullPointerException).
Tu hai un ciclo for che cicla sulle righe del file... legge ciascuna riga finchè la lettura non produce una stringa nulla. Quando viene "letta" una riga nulla significa che il file è finito ed il ciclo for esce... e tu a questo punto crei uno StringTokenizer... passandogli proprio la stringa nulla (è nulla, altrimenti saresti ancora dento il ciclo for). Questo, ovviamente, non va bene. La logica va rivista: lo StringTokenizer va usato dentro il ciclo for (cioè per ciascuna riga), non fuori, quando il file ormai è già stato letto tutto e la riga è nulla.
Ciao.![]()