Zapis i odczyt danych. Jak to ugryźć ?

Zapis i odczyt danych. Jak to ugryźć ?
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Cześć,

Robię swoją pierwszą Apkę w Javie(to tak w formie nauki). Wygląda ona tak:
user image

I teraz opiszę jak to ma funkcjonować...

Po kliknięciu przycisku DODAJ, pola 1 i 2 zapisują się. Tekst z pola 1 pokazuję się w ListView(numer 3). Teraz załóżmy, że włączyłem moją apkę i zapisałem np. 100 pozycji. Chciałbym, aby one wczytywały mi się do ListView, przy każdym ponownym włączeniu aplikacji.

Próbowałem wielu metod(Jestem początkującym programistą Javy, więc pewnie wszystkiego nie zdołałem spróbować) dlatego chciałbym , abyście mi podsunęli pomysł, jak to ugryźć. Nie chcę tutaj gotowych rozwiązań, ale może ktoś mnie jakoś naprowadzi na właściwe tory ?(Na koniec dodam, że fileChooser odpada. Przy zapisywaniu tychże pól, nie chciałbym, aby użytkownik, wybierał sobie nazwę pliku i miejsca, gdzie ma się to zapisać, nie mówiąc już o załadowaniu takiego pliku, gdzie trzeba go szukać właśnie poprzez fileChooser - Chciałbym, aby to działo się... automatycznie, bądź po kliknięciu na odpowiedni BUTTON).

JK
  • Rejestracja:około 11 lat
  • Ostatnio:około 3 godziny
  • Postów:107
0

Masz kilka możliwości

a) baza zdalna:
stawiasz bazę na jednym serwerze w Internecie i tam trzymasz dane każdego użytkownika

  • jedna centralna baza dla wszystkich
  • łatwość zarządzania
    b) baza lokalna
    tak samo jak baza zdalna, z tym że każdy użytkownik będzie miał bazę danych u siebie lokalnie.
    c) pliki - chyba najlepsze rozwiązanie na początek
    Możesz stworzyć jakiś ukryty folder w katalogu domowym użytkownika (np. http://stackoverflow.com/questions/585534/what-is-the-best-way-to-find-the-users-home-directory-in-java) i tam trzymać jego plik konfiguracyjny i wszystkie dane. Możesz je trzymać w plain text, możesz również serializować sobie to do jsona lub xmla - twój wybór.

Jak masz jakieś pytania to wal śmiało - możesz również na PW.

K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Postanowiłem załatwić sprawę za pomocą serializacji. Jednak utknąłem... czy ktoś poradzi coś na mój wyjątek ?

Kopiuj
    public void loadDream(ActionEvent event)
    {
        String fileName = "C:\"Users\"pstan\"workspace\"DreamNote\"sen.txt"; // probowalem rowniez z fileName = "sen.txt"

        Dream dream = null;

        try(
                FileInputStream fis = new FileInputStream(fileName);
                ObjectInputStream ois = new ObjectInputStream(fis); //TUTAJ JEST BLAD
                ) {


        	dream = (Dream) ois.readObject();

        } catch (FileNotFoundException e) {
            System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
            e.printStackTrace();
        } catch (IOException e) {
        	 System.out.println("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); //TEN BŁĄD SIĘ POJAWIA
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
        	 System.out.println("ccccccccccccccccccccccccccccccccccccc");
            e.printStackTrace();
        }

Jakieś propozycję co może być nie tak ?

Konsola pokazuje mi cos takiego:
java.io.StreamCorruptedException: invalid stream header: 73656E6E

bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1
  1. Co to
Kopiuj
String fileName = "C:\"Users\"pstan\"workspace\"DreamNote\"sen.txt";

za cudo? Zamień na

Kopiuj
String fileName = "C:/Users/pstan/workspace/DreamNote/sen.txt";
//lub
String fileName = "C:\\Users\\pstan\\workspace\\DreamNote\\sen.txt";
  1. Pokaż jak zapisujesz.

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0
  1. Zamieniłem tak jak napisałeś, ale błąd pozostał identyczny.

Resztę już pokazuję...

  1. Zapisuję tak:
Kopiuj
    public static void save(Dream dream)
    {
    	String title = dream.getTitle(); //Klasa Dream ma pola(String) title oraz content. Chcialbym, aby zapisywany plik mial nazwe taka jak tytul, ktory wpisal uzytkownik

    	title+=".txt";
	    try{
	    // Create file
	    FileWriter fstream = new FileWriter(title);
	    BufferedWriter out = new BufferedWriter(fstream);

	    //get the CONTENT from dream
	    String cont = dream.getContent();
	    out.write(cont); //zapisuje sam kontent w pliku ktory nazywa sie tak jak tytul ktory podal uzytkownik

	    //Close the output stream
	    out.close();
	    }catch (Exception e){//Catch exception if any
	    System.err.println("Error: " + e.getMessage());
	    }
    }

Struktura:

user image

O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:dzień
1

Jak odbierasz

Kopiuj
ObjectInputStream

to wysłanie powinno odbyć się za pomocą ObjectOutputStream

Kopiuj
edytowany 1x, ostatnio: olek1
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Wszystko działa :) Dziękuję za pomoc :). Nie mam pojęcia czemu tego nie zauważyłem...

Ale teraz trafiam na kolejny problem^^. Obiekty klasy Dream, zapisuję do ObservableList<Dream>, aby je wyświetlać w ListView. Po wyłączeniu aplikacji pliki(czyli w moim przypadku obiekty klasy Dream) są zapisane i z tego się niezmiernie cieszę, ale chciałbym teraz żeby te pliki(ich zawartość) "wskakiwały" do mojej listy po ponownym włączeniu apki.

Przy moim obecnym poziomie wiedzy ;] jakoś nie widzę rozwiązania innego niż zastosowanie tutaj fileChoosera(Nie chciałbym, żeby użytkownik musiał wybierać manualnie pliki do wczytania).

Macie jakieś pomysły ?

Z góry dziękuję

O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:dzień
0

Po prostu wraz ze starem apki wczytaj ten plik z dysku i powypełniaj danymi z niego co tam sobie chcesz.

K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Czyli dopisywać wszystko do jednego pliku tekstowego i później bawić się operacjami na tekście ?

O1
Po co bawić się na tekście? Zdeserializujesz sobie obiekty z pliku i nie potrzeba żadnej zabawy. Tak jak robiłeś to wyżej: dream = (Dream) ois.readObject();
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Ok to zabieram sie do pracy. Tylko jeszcze jedno pytanie. Czy jest mozliwosc zapisania/odczytania List do pliku za pomocą serializacji?

O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:dzień
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Można też pisać element po elemencie:

Kopiuj
List lista = new Vector<MojaKlasa>();
...
ObjectOutputStream oos = ...;
for(MojaKlasa obiekt:lista)
{
    if(obiekt spełnia warunek)
    {
       oos.write(obiekt);
    }
}

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Opiszę kolejny problem. zrobiłem 2 okna w mojej apce(po kliknieciu na jakis button otwiera się drugie okno). Na tym pierwszym mam moje listView a na drugim mam przycisk DODAJ, ktory dodaje coś do listView w innym oknie(tym startowym). Przycisk oraz listView są w dwóch odrębnych klasach. Bawiłem się troche polami Static, ale nie udało się tego zrobić bez błędu :/. Czy jest możliwość listView zrobić statyczne, w taki sposób, abym dodawał do niego cos z innej klasy(w moim przypadku jeszcze z innego okna apki) ? Nie mam możliwości podrzucenia kodu. Zrobię to później jeśli nie da się pomóc bez zajrzenia do niego :).

bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Tworząc drugie okno przekaż referencję do pierwszego okna, coś w rodzaju:

Kopiuj
DrugieOkno drugie = new DrugieOkno(this);
drugie.setVisible(true);

W konstruktorze drugiego okno zapamiętaj przekazana referencję w polu klasy

Kopiuj
    private PierwszeOkno pierwsze = null;
    ...
    public DrugieOkno(PierwszeOkno pierwsze)
    {
        this.pierwsze = pierwsze;

W obsłudze przycisku DODAJ możesz wtedy użyć kodu

Kopiuj
pierwsze.listView.add(...);
//lub - zależnie od modyfikatora dostępu do pola listView
pierwsze.getListView().add(...);

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Troszkę tego nie ogarniam. Nowe okno otwieram tak:

Kopiuj
   public void newWindow(ActionEvent event) throws IOException {
		Stage stage = new Stage();
		stage.setTitle("Apka");

		Parent root1 = FXMLLoader.load(getClass().getResource("/fxml/nazwa.fxml"));


/**************************************************************************/
		//SCENA
		Scene scene = new Scene(root1,600,400);
		stage.setScene(scene);
		stage.showAndWait();
    }

i teraz mam dwa pliki .fxml jeden w ktorym jest

Kopiuj
    @FXML // fx:id="dreamHistoryList"
	public ListView<String> dreamHistory; // Value injected by FXMLLoader
//oraz
.
.
.
public ArrayList<Dream> listDreams = new ArrayList<Dream>();

do mojego listView pakuje sobie pola w ten sposob:

Kopiuj
dreamHistory.getItems().add(title);
//title to pole String z klasy Dream

a w tym drugim pliku .fxml(czyli nowym oknie) mam przycisk ADD(musi wysylac moje *title *do dreamHistory).

Kopiuj
    @FXML
    void ADD(ActionEvent event) {

    	}

Zabrać się za otwieranie nowego okna inaczej ?

bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Przekaz do metody newWindow dwa argumenty

Kopiuj
public void newWindow(ActionEvent event, PierwszeOkno okno) throws IOException

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

z tym też mam problemy, ale rozwiązałem to inaczej :) ustawilem** ListDreams** na static i w drugim oknie dopisuje obiekty do mojej listy + zapisuje je w pliku. Aby wczytać je do ListView ustawiłem na drugim oknie

Kopiuj
stage.setOnCloseRequest(e -> loadDream());
Kopiuj
loadDream()

ładuje mi obiekty z pliku do ListView. Obejście problemu długim łukiem, ale to moja pierwsza apka, więc proszę o wyrozumiałość.

Dziękuję wam za udzielanie się w temacie !

K9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:15
0

Posiedziałem dzisiaj nad kolejnym problemem dobrych kilka godzin, ale nie udało mi się go rozwiązać. Mój program wygląda tak:

user image

Pole zaznaczone na zółto to w pliku FXML coś takiego:

Kopiuj
<BorderPane>
<center>
.
.
.
</center>
</BorderPane> 

Po kliknięciu w przycisk w przycisk chciałbym, aby moje CENTER uległo zmianie. Robię to tak:

Kopiuj
			  contentID.getChildren().clear();//contentID to ID do VBox który chcę zmienić
			  contentID.getChildren().add(FXMLLoader.load(getClass().getResource("/fxml/showDreamFXML.fxml")));

To mi się udało, ale mój nowy plik FXML nie jest responsywny... mianowicie buttony itp które zawiera nie są umiejscowione tak jakbym chciał. Pokazuję screena z nowego pliku FXML(otwartym w Scene Builderze)

user image

Strzałka pokazuję gdzie chciałbym, aby button się przykleił. Jak włączam program na full screen to button jest mniej więcej na środku wysokości okna programu. Jakieś pomysły ? podać kod źródłowy ?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.