Odczyt zmiennej char

0

Witam
Mam pytanie co do odczytu zmiennej char, a mianowicie w poniższej metodzie
public static void lista() w miejscu znak = (char)System.in.read(); program nie zatrzymuje się i nie czeka na wprowadzenie z klawiatury.
Natomiast w konstruktorze public Ewidencja() w miejscu znak = (char)System.in.read(); program zatrzymuje się i po wprowadzeniu z klawiatury zachowuje się poprawnie.
Nie wiem dlaczego tak się dzieje, jeśli mógłby ktoś wytłumaczyć będę wdzięczny za pomoc.
P.S. Może zna ktoś jakiś lepszy sposób odczytu dla typu char ?

public static void lista() {
		Ewidencja tmp = null;
		char znak = 0;
		for(Ewidencja el: Lista)
		{
			if (znak == 'Q')
			{
				el = tmp;
			}
			
			tmp = el;

			System.out.println("[Enter] - zapisz");
			System.out.println("[Q] - cofnij");
			
			
			try {
				znak = (char)System.in.read();
				System.out.println(znak);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(znak == '\r')
			{
				continue;
			}
			else if(znak != 'Q')
			{
				System.exit(-1);
			}
		}
	}
public Ewidencja()
	{
		System.out.println("Dodaj pracownika\n");
		
		System.out.print("[D]yrektor/[H]handlowiec:\t\t");
		
		String string_tmp = odczyt.next();
		char znak = string_tmp.charAt(0);
		
		if(znak == 'D' || znak == 'H')
		{
			if(znak == 'D')
			{
				this.Stanowisko = "Dyrektor";
			}
			else
			{
				this.Stanowisko = "Handlowiec";
			}
		}
		else
		{
			System.exit(-1);
		}
System.out.println("[Enter] - zapisz");
		System.out.println("[Q] - porzuć");
		
		try {
			znak = (char)System.in.read();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(znak == '\r')
		{
			Lista.add(this);
		}
		else if(znak != 'Q')
		{
			System.exit(-1);
		}
	}
0

Może po prostu ta pentelka nie wykonuje się ani razu ?

1

Zainteresuj się klasą Scanner. Może to trochę uprościć Ci życie. Podstawy skanowania - klasa Scanner

0

W klasie ktorej znajduje sie powyzej podana metoda znajdują się pola:

public class Ewidencja implements Menu{
private static Scanner odczyt = new Scanner( System.in );
private static ArrayList<Ewidencja> Lista = new ArrayList<Ewidencja>();

W konstruktorze pierwszy odczyt przebiega z klasy Scanner, lecz kiedy chce odczytać znak enter, czyli pisząc pod Windows jest to '\r' odczyt czeka na kolejny znak. Dlaczego ?

1

Odczyt ze strumienia znakowego przyłączonego do urządzenia takiego jak klawiatura jest bardzo zależny od systemu. Po pierwsze system może konwertować kody klawiatury na wewnętrznie używany kod np. w Windows-1250, który wcale nie musi być (i zwykle nie jest) taki jaki jest używany w maszynie wirtualnej Javy, czyli z tego co wiem UTF-16 LE. Następnym problemem wynikającym z pierwszego jest kolejność kodowania bajtów składających się na kod znaku w JVM - na komputerach z procesorami Intela i AMD (x86, x64) używana jest w pamięci kolejność "little endian" (LE), a na wszystkich innych "big endian" (BE). Dodatkowo nakłada się tu jeszcze typ systemu - większość systemów unixowych, linuksowych używa do składowania kodów liter tekstu w plikach w kolejności BE.
Ma to więc znaczenie jeżeli strumień wejściowy raz jest przyłączony do klawiatury, a raz do pliku tekstowego pochodzącego z nieznanego źródła w nieznanym kodowaniu. Jakby tych problemów było mało dochodzi jeszcze jeden kolejny związany z tym, że na większości systemów kody znaków są jeszcze na etapie obsługi buforowane wierszowo co oznacza, że kolejna porcja znaków jest dostępna dopiero po naciśnięciu klawisza Enter/Return. Na dodatek kod tego klawisza może zostać włączony w strumień (lub nie) w postaci kodu znaków CR, LF, albo CR+LF zależnie od typu systemu, w którym uruchomiono program.
Metoda read nie zwraca kodu znaku, lecz nieprzenośny bajt tego kodu i to o wartości unsigned, czyli 0-255. Kolejność bajtów nie jest określona, kodowanie nie jest określone. W praktyce oznacza to, że trzeba samemu dekodować - w najlepszym wypadku przy pomocy metody Charset.decode, o ile uda się trafnie określić kodowanie oraz poprawnie uwzględniać kody znaków CR i LF w konkretnym środowisku. Na przykład '\r' to szesnastobitowa wartość, w której bardziej znaczący bajt jest równy zero, a mniej znaczący ma wartość dziesiętną 13. Musisz więc wiedzieć kiedy odczytany ze strumienia bajt o wartości 0 reprezentuje znak o kodzie '\0', a kiedy bardziej znaczący bajt tego znaku i kiedy bardziej znaczący bajt każdego innego znaku, który pokrywa się z pierwszymi 256 znakami Unicode i jednocześnie ISO-8859-1. Dlatego porównywanie odczytanego bajtu z wartością '\r' czy '\n' nie jest w zasadzie poprawne, choć może w pewnych warunkach działać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1