wczytywanie liczb z pliku

0

W skrócie zadanie polega na wczytaniu liczb z pliku tekstowego (a następnie wykonaniu na nich jakichś operacji - co jest tutaj nieistotne). Pytanie czego lepiej używać do takiego wczytywania - Scannera czy FileReadera?
Kod dla Scannera mam taki:

Scanner scan = new Scanner (new File("liczby.txt"));
String dane = "";
while (scan.hasNextLine()) dane = dane + scan.nextLine() + " ";
StringTokenizer st = new StringTokenizer (dane)

a dla FileReadera taki:

String wczytaj;
BufferedReader br = new BufferedReader(new FileReader("liczby.txt"));
StringBuffer sb = new StringBuffer();
while ((wczytaj = br.readLine()) != null) {
sb.append(wczytaj).append(" ");
}
StringTokenizer st = new StringTokenizer (sb.toString());

Efekt końcowy jest taki sam, więc nie wiem czy wybór metody ma jakieś logiczne przesłanki?

0

Przy użyciu Scannera prościej odczytywać liczby. Jak duży jest plik? Operator konkatenacji jest bardzo niewydajny, nie powinieneś go używać. Analizuj każdy odczytany wiersz lub zmień kod.

Scanner scan = new Scanner (new File("liczby.txt"));
StringBuffer dane = new StringBuffer("");
while (scan.hasNextLine()) dane.append(scan.nextLine()) + " ";
Scanner scanner = new Scanner(dane.toString());

Liczby odczytuj metodą nextInt(), nextFloat(), nextDouble(),... bez konieczności parsowania.
Przy wykorzystaniu Scannera w ogóle nie musisz czytać pliku, tylko od razu liczby.

0

Ani jedno ani drugie. Files.lines() + flatMap() + String::split + map() + Integer::new + collect() + Collectors.toList()
i voila, masz listę wszystkich liczb z pliku

0

@Shalom, jak techniką Javy 8 wczytać plik, w którym każdy wiersz zawiera 13 liczb. Pierwsza ma być typu int (rok), kolejne 12 mają być typu float (średnie miesięczne). Należy uzyskać kolekcję obiektów pewnej klasy z polami int i float[12].

0

@bogdans a gdzie widzisz problem? Files.lines da ci strumień linii, piszesz sobie metodę która dla linii zwraca obiekt tej twojej klasy, robisz .map() z tą metodą na strumieniu a potem collect() i Collectors.toList()

0

@Shalom, już nigdzie nie widzę problemu. Ale mam jeszcze jedno pytanie:

Files.lines(path).map(line -> {return new MojaKlasa(line);}).filter(obj -> obj.isOk()).collect(Collectors.toList());

Co się dzieje z obiektami, które zostały utworzone, ale odrzucone przez filtr. Siedzą w pamięci czekając na GC?

0

Sprawdź ;)
Idea strumieni jest taka że mogą być nieskończone. Twój plik mółby mieć gigabajty (w tym tylko kilka linii spełniajacych warunek) a ten kod mimo to bez problemu by się wykonał, bo dopiero collect() zbiera elementy w pamieci. Wszystkie pozostałe operacje są aplikowane jako złożenie funkcji po kolei na elementach strumienia a filtr będzie je automatycznie odrzucał.
BTW kwestie kosmetyki, Java 8 ma method references:

Files.lines(path).map(MojaKlasa::new).filter(MojaKlasa::isOk).collect(Collectors.toList());

No i warto też pamiętać że masz coś takiego jak .paralellStream() jeśli danych jest bardzo dużo a kolejność nie jest dla ciebie istotna. Wtedy JVM będzie dzielił wejściowy strumień na fragmenty i operował na każdym równolegle.

0

Ja niedawno wczytywałem dane z pliku i mapowałem do obiektu. Przy pomocy javy8 wygląda to mniej więcej tak:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(st));
        List<StockFiveMinutesDetails>stockFiveMinutesDetailsList = bufferedReader.lines().map(mapToStockFiveMinutesDetails).collect(Collectors.toList());

teraz funkcja map:

public Function<String, StockFiveMinutesDetails> mapToStockFiveMinutesDetails = (line) -> {
        String[] splitLine = line.split(",");
        StockFiveMinutesDetails stockFiveMinutesDetails = new StockFiveMinutesDetails();
        LocalDate dateDetail = dateAndTimeParserService.parseLocalDateFromString(splitLine[0]);
        LocalTime timeDetail = dateAndTimeParserService.parseLocalTimeFromString(splitLine[1]);
        stockFiveMinutesDetails.setDate(LocalDateTime.of(dateDetail, timeDetail));
        stockFiveMinutesDetails.setTime(timeDetail);
        stockFiveMinutesDetails.setCumulatedVolume(0l);
        stockFiveMinutesDetails.setVolume(Long.valueOf(splitLine[6]));
        return stockFiveMinutesDetails;
    };

Akurat plik był csv i oddzielany przecinkami, ale idea pozostaje ta sama.

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