Kurs Java Podstawy - rozszerzony

Rozwiązanie 1.16

Rozwiązanie do zadania 1.16 o treści:

Korzystając z własnego buforowania przekopiuj dane znajdujące się w pliku binarnie.txt do przekopiowane.txt. Dodatkowo zlicz ilość skopiowanych bajtów.

W tym zadaniu korzystać można z dowolnego strumienia opisanego w lekcji. Dla przykładu użyłem tutaj DataInputStream i DataOutputStream.

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class KopiowanieBinarne {

	public static void main(String[] args) {
		DataInputStream strumieńWejściowy = null;
		DataOutputStream strumieńWyjściowy = null;

		try {
			strumieńWejściowy = new DataInputStream(new FileInputStream("binarnie.txt"));
			strumieńWyjściowy = new DataOutputStream(new FileOutputStream("przekopiowane.txt"));
		} catch (FileNotFoundException e) {
			System.out.println("Nie znaleziono takiego pliku");
		}

		int ilośćSczytanychBajtów = 0;
		int całkowitaIlośćBajtów = 0;
		byte[] bufor = new byte[1024];

		try {
			while ((ilośćSczytanychBajtów = strumieńWejściowy.read(bufor)) != -1) {
				strumieńWyjściowy.write(bufor, 0, ilośćSczytanychBajtów);
				całkowitaIlośćBajtów += ilośćSczytanychBajtów;
			}
		} catch (IOException e) {
			System.out.println("Bład wejścia-wyjścia");
		}

		try {
			if(strumieńWejściowy != null) strumieńWejściowy.close();
			if(strumieńWyjściowy != null) strumieńWyjściowy.close();
		} catch (IOException e) {
			System.out.println("Błąd zamykania strumieni");
		}

		System.out.println(całkowitaIlośćBajtów);
	}

}

Komentarze

pawel

na czym polega (jak działa, co nam daje) IOException??

Dawid Kunert

Korzystając ze strumieni jesteśmy zobowiązani przechwycić lub "wyrzucić" wyjątek IOException(po którym dziedziczą wszystkie wyjątki wejścia-wyjścia). Projektanci Javy poprzez taką decyzję "zabezpieczyli" nas przed niepowołanym błędem, który spowodowany jest użyciem metod zawartych w klasach strumieniowych. Więcej o wyjątkach: Lekcja 1, Lekcja 2

Janosch

Trochę to zagmatwane i nie wystarczająco zostały wyjaśnione zagadnienia poruszane na lekcji, a które znajdują się w rozwiązaniu. Problemem dla mnie było nawet zaczęcie tego zadania, za mało przejrzystych przykładów jak w poprzednich lekcjach (np. w lekcji "Zapis i odczyt z plików", gdzie można było sobie przyswoić tą wiedzę, gdzie teoria była podparta solidnymi przykładami, a z zadaniem nie było problemów),
Tutaj nie bardzo mogę zrozumieć np.:
- DataInputStream strumieńWejściowy = null; - dlaczego null?
- byte[] bufor = new byte[1024]; (do czego ma się bufor? Czy jest to długość tak jakby pamięci, do której chcemy wrzucić dane z pliku? Jeżeli tak to skąd wiemy jaką wartość tutaj dobrać? Na jakiej podstawie wprowadziłeś 1024?
- Offset jest tutaj 0? Czy znając długość pliku, i jeżeli wprowadzimy ją jako offset to znaczy, że będziemy dopisywali do pliku kolejne rzeczy?
Generalnie przydałoby się jakieś też prostsze zadanie, które łatwiej byłoby ewentualnie przeanalizować w razie problemów ze swoim rozwiązaniem.
Dlaczego ilośćSczytanychBajtów = strumieńWejściowy.read(bufor)) != -1 jest porównywane do -1?
Poza tym kurs świetny!

Dawid Kunert

Masz rację. Postaram się podać więcej informacji na temat tego zadania oraz wstawię inny, łatwiejszy przykład. Dziękuję za zwrócenie uwagi :)

snt.banzai

"KopiowanieBinarne kopiowanie = new KopiowanieBinarne()" - wirtualna maszyna zwraca mi błąd z komunikatem Cannot Find Symbol. Jaki jest angielski odpowiednik?

I jeszcze nie mogę dojść na jakiej zasadzie nastąpiło przypisanie obu plików do Stringów plikWejściowy/plikWyjściowy.

Dawid Kunert

Zapomniałem, że to zagadnienie będzie dopiero w kolejnych lekcjach(programowanie obiektowe). Już to zmieniłem :)

snt.banzai

tak apropos - odkryłem coś takiego

http://wazniak.mimuw.edu.pl/index.php?title=PO_Wstęp_do_Javy

Też bardzo przydatne dla newbies.

pneumonia

Mam małe pytanko? Czy można zrobić to bez DataInputStream i DataOutputStream. Ja napisałem tak i działa:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Binarne2{
public static void main(String[] args){

FileOutputStream wyjscie = null;
FileInputStream wejscie = null;

try{
wyjscie = new FileOutputStream("przekopiowane.txt");
wejscie = new FileInputStream("binarnie.txt");
} catch (FileNotFoundException e){
System.out.println("Nie znaleziono pliku");
}

try{
byte[] bufor = new byte[1];
int b = 0;
while (wejscie.read(bufor) != -1){
wyjscie.write(bufor);
b++;
}
System.out.println("Liczba bajtów to: "+b);
}

catch (IOException e){
}
try{
if(wyjscie != null)
wyjscie.close();
} catch (IOException e){
System.out.println("Blad zamykania strumienia");
}

}
}

Może warto jakoś podkreślić kiedy używamy DataInputStream, poza tym dziękuję za świetny kurs!

Dawid Kunert

Oczywiście, że można to zrobić dowolną z opisanych w tej lekcji klas. W tym rozwiązaniu chciałem jedynie pokazać sposób użycia DataInputStream w kodzie. Co do stosowania tych klas. Data stosujemy w przypadku, gdy chcemy pracować np. na intach czy Stringach w naszym programie, a zwykły Input/Output na bajtach. Co do bufora wielkości 1, to dziwne rozwiązanie, lecz zgodne z poleceniem :)