Ok, ora il formato di file e il codice sono chiari!
Veniamo al problema della lettura. Il codice chiaramente lo devi modificare un po'. Non hai postato tutto il codice completo però dici che il codice per la lettura lo hai nel main. Innanzitutto ti consiglierei di incapsulare la logica di lettura in una classe apposita che si occupa solo ed esclusivamente della lettura del file (no gestione errori, no input utente, no altro).
Magari con un metodo di istanza che legge 1 "record" (un utente) e restituisce un oggetto Utente, oppure null per indicare end-of-file (concettualmente come readLine() che restituisce la riga o null per eof).
Il fatto che hai messo dei ';' a inizio riga per "taggare" (marcare) il tipo della riga è ovviamente buono e quindi ok. Se dopo i ';' prevedi che ci debba essere sempre uno spazio (come si vede nel tuo esempio), ancora meglio, perché rende la marcatura ancora meno equivocabile.
Il problema quindi non è identificare il tipo della riga, questo è banale e lo risolvi con startsWith() di String. Insomma ... hai solo 3 casi possibili, basta fare 3 test.
La cosa un pelino più problematica è la sequenza delle righe. Quando stai per leggere 1 Utente, innanzitutto leggi una riga e ti aspetti che sia quella del nome, poi leggi la riga seguente e ti aspetti che sia quella del numero. Poi fai un ciclo per leggere gli N casi.
Il punto cruciale è qui. Ora prova a pensare: quando termina la sequenza dei casi? Semplice: quando leggi di nuovo una riga del nome.
La questione è che la nuova riga del nome l'hai appena letta! Quindi non dovrai cercarla di nuovo. Questo vuol dire che devi salvarti da qualche parte (es. variabile di istanza) la riga che dovrai poi usare (invece che fare readLine() ) quando inizierai a leggere il successivo Utente. Questa è per così dire, la rogna principale.
Per il resto, se fai il giusto design come ti ho suggerito all'inizio, anche tuo il main diventerà più semplice e "pulito".


Rispondi quotando