Dodawanie do pliku (Listy)

0

Witam, problem jak w temacie. Chciałbym dodawać a nie nadpisywać, nowe obiekty do Listy. Niestety po wczytaniu pliku i wpisaniu nowych danych stare dane znikają. Czy istnieje sposób, aby po wczytaniu zawartości Listy z pliku dopisać nowe dane i zapisać je w tym samym pliku?

0

Klasa FileWriter jako drugi parametr w konstruktorze przyjmuje wartość boolean, która oznacza czy chcesz nadpisać = false czy dopisać = true do pliku.

FileWriter fileWriter = new FileWriter(path, true)
0

Raczej chodziło mi o klasę

FileOutputStream fo = new FileOutputStream(Object object)

, która jako parametr przyjmuje obiekt, który nie jest typu String, ale w tym wypadku typu List<Float>

. Czy też wystraczy dopisać "true" po przecinku?
0

No dobrze, to może inaczej. Mam taki oto kod:

public class Class {
	
	Map<Student, List<Float>> register = new TreeMap<Student, List<Float>>(); 
	
	public void addStudent() { 				     
		
		
		Student s = new Student();
		s.setName();
		register.put(s, s.marks); 
		
		try (FileOutputStream fs = new FileOutputStream ("register.bin", true)){
			ObjectOutputStream os = new ObjectOutputStream(fs);
			
			os.writeObject(register);
			os.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void loadRegister(){
		
		try (FileInputStream fi = new FileInputStream("register.bin")){
			ObjectInputStream os = new ObjectInputStream(fi);
			
			@SuppressWarnings("unchecked")
			Map<Student, List<Float>>register = (Map<Student, List<Float>>)os.readObject();			
			
			for (Student key: register.keySet()){
				System.out.println(key+", oceny "+key.marks);
			}
			os.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Chciałbym, aby program pozwalał dopisywać uczniów do listy, a następnie zapisał listę do pliku (register.bin). Po zapisaniu chciałbym, aby odczytał zawartość pliku i wyświetlił zawartość listy w konsoli (metoda loadRegister). Po dodaniu kolejnych uczniów, chciałbym, aby nie nadpisywał nowych, ale dodawał ich do istniejącej listy. Wydaje się, że program dopisuje nowych uczniów do istniejącej listy, ale nie wyświetla tych nowo dopisanych w konsoli. Proszę o wskazówki, co można poprawić w kodzie. Proszę również o wyrozumiałość, gdyż od miesiąca uczę się programowania.

0

Do istniejącego pliku nie można metodą writeObject dopisać obiektów. W Twoim przypadku dopisywanie obiektów nie jest potrzebne, Ty zapisujesz jeden obiekt - listę, która zawiera wszystkich studentów.

0

Istnieje zatem sposób, aby po wczytaniu Kolekcji z pliku dodać do niej nowe elementy nie zmieniając starych?

0

Oczywiście. Na starcie programu odczytaj kolekcję, w czasie pracy modyfikuj kolekcję (np. dopisuj nowe elementy), przed zakończeniem programu zapisuj nową wersję kolekcji.
Po zapisaniu koniecznie zamykaj FileOutputStream. W zamieszczonym kodzie nie zamykasz.

0

Wydaje mi się, że problem rozwiązałem. Niżej zamieszczam kod metody, która rozszerza kolekcję i zapisuje poszerzoną mapę w pliku. Mam jeszcze jedno pytanie. Czy powinienem wywołać metodę zamykającą FileOutputStream? Jeśli tak to w jakim miejscu? Po ois.close()? Może już nie trzeba zamykać oos skoro zamykamy ois?

public void extendRegister(){
		
		try (FileInputStream fi = new FileInputStream("register.bin")){
			ObjectInputStream ois = new ObjectInputStream(fi);
			
			@SuppressWarnings("unchecked")
			Map<Student, List<Float>>register = (Map<Student, List<Float>>)ois.readObject();			
			
			Student s = new Student();
			s.setName();
			register.put(s, s.marks);
			
			
			
			try (FileOutputStream fs = new FileOutputStream ("register.bin")){
				ObjectOutputStream oos = new ObjectOutputStream(fs);
				oos.writeObject(register);
				
								
				
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			ois.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
0

Jeżeli zamieszczasz je w try-with-resources (

 try(->tu<-) 

) to jeżeli obiekty rozszerzają intefejs Autoclosable zostaną automatycznie zamknięte. Czyli w twoim wypadku FileOutpuStream i FileInputStream zostaną zamknięte.

ObjectInput/OutputStream też rozszerza Autoclosable możesz zamiast "ręcznego" zamyknia tych obiektów zrobić coś takiego

try(FileOutputStream fs = new FileOutputStream ("register.bin");
                       ObjectOutputStream oos = new ObjectOutputStream(fs)); 

lub krócej:

try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream ("register.bin")) 
0

Zamiast

ois.close();

daj fi.close();

.

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