0

I am doing this for an assignment for school, so I am not looking for a clear answer, more so some information and pointers as to what is going wrong with my File I/O.

I am trying to write an ArrayList object to a file, and have it overwrite what is currently in the ArrayList. So far, I have tried two things. The first, was the code

    public static void saveToDo(String fileName, ArrayList<ToDo> td)
{
    try{
    FileOutputStream objectFileStream = new FileOutputStream(fileName);
    ObjectOutputStream oos = new ObjectOutputStream(objectFileStream);
    oos.writeObject(td);
    oos.close();
    objectFileStream.close();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
}

Currently, when I run this (using a GUI), and save, it throws

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at cst8284.assignment1.TaskManager.findFirstValue(TaskManager.java:335)
at cst8284.assignment1.TaskManager.getFile(TaskManager.java:361)
at cst8284.assignment1.TaskManager.lambda$7(TaskManager.java:428)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at 
com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)

Which leads me to believe that it's printing an empty ArrayList, so when it's read back, it can't find the index, and then terminates.

My next attempt at a fix was

    public static void saveToDo(String fileName, ArrayList<ToDo> td)
{
    try{
    FileOutputStream objectFileStream = new FileOutputStream(fileName);
    ObjectOutputStream oos = new ObjectOutputStream(objectFileStream);
    for(ToDo tdArray : td){
    oos.writeObject(tdArray);
    }
    oos.close();
    objectFileStream.close();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
}

Which, as far as I can tell, does not actually change anything. When I click save, and go to reload the file, the old input is still present, and the input I wanted saved is no where to be found. I'm at a loss at the moment, I've been musing over this for a solid 4 hours. I'm going to assume the problem lies in I have a fundamental misunderstanding of how File I/O works, but anything to point me in the right direction will be greatly appreciated.

The two files in question that use these are below. I have omitted import statements for readability.

public class TaskManager extends Application{

private ArrayList<ToDo> toDoArray;
private static int currentToDoElement;
private Stage primaryStage;
//Dave Houtman, March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
@Override
public void start(Stage primaryStage) {
    setPrimaryStage(primaryStage);
    getPrimaryStage().setTitle("To Do List");
    getPrimaryStage().setScene(getSplashScene());
    //getPrimaryStage().setScene(getDefaultScene("Click here to open"));
    getPrimaryStage().show();
}
//Dave Houtman, March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
public void setPrimaryStage(Stage PrimaryStage)
{
    this.primaryStage = PrimaryStage;
}

public Stage getPrimaryStage()
{
    return this.primaryStage;
}
public Scene getSplashScene()
{   
    Label defaultLabel = new Label("())======D");
    Path path = new Path();
    path.getElements().add (new MoveTo (-250f, -157f));
    path.getElements().add (new CubicCurveTo (300f, 250f, -100f, 50f, 440f, 80f));
    PathTransition pathT = new PathTransition();
    pathT.setDuration(Duration.millis(5000));
    pathT.setNode(defaultLabel);
    pathT.setPath(path);
    pathT.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
    pathT.setCycleCount(Timeline.INDEFINITE);
    //(Kostovarov, 2012)
    pathT.setAutoReverse(true);
    //(Class PathTransition, n.d)
    FadeTransition fadeT = new FadeTransition(Duration.millis(500), defaultLabel);
    fadeT.setFromValue(1.0);
    fadeT.setToValue(0.0);
    fadeT.setCycleCount(Timeline.INDEFINITE);
    fadeT.setAutoReverse(true);
    //(Kostovarov, 2012)
    ParallelTransition paralT = new ParallelTransition(pathT, fadeT);
    paralT.play();
    //(Class ParallelTransition, n.d)
    StackPane defaultPane = new StackPane();
    defaultPane.getChildren().add(defaultLabel);
    Scene defaultScene = new Scene(defaultPane, 900, 500);
    defaultPane.setOnMouseClicked((e) -> {
        getFile();
    });
    return defaultScene;

}

public static void main(String[] args) {
    Application.launch(args);
}

public ArrayList<ToDo> getToDoArray()
{
    return toDoArray;
}

public void setToDoArray(ArrayList<ToDo> toDoArray){
    this.toDoArray = toDoArray;
}

public Scene getToDoScene(ToDo td)
{
    Scene toDoScene = new Scene(getToDoPane(td), 900, 500);
    return toDoScene;
}
public Pane getToDoPane(ToDo td)
{
    BorderPane rootNode = new BorderPane();                                             
    VBox vbLeft = new VBox();                                                   
    vbLeft.setMinWidth(120);                                                    
    VBox vbRight = new VBox();                                                  
    vbRight.setMinWidth(120);       

    rootNode.setLeft(vbLeft);                                                   
    rootNode.setRight(vbRight);                     
    //(Houtman, 2017)
    rootNode.setBottom(getBottomPane());
    rootNode.setCenter(getCenterInfoPane(td));
    rootNode.setTop(getMenuBar());
    return rootNode;
}

public static void setToDoElement(int element)
{
    currentToDoElement = element; 
}

public static int getToDoElement()
{
    return currentToDoElement;
}

public Pane getCenterInfoPane(ToDo td)
{
    GridPane infoPane = new GridPane(); 
    infoPane.setVgap(5);
    infoPane.setHgap(3);
    infoPane.setAlignment(Pos.CENTER);
    //(Gordon, 2013)
    Label lblTask = new Label("Task");
    GridPane.setConstraints(lblTask, 2, 0);
    TextField tfTask = new TextField(td.getTitle());
    GridPane.setColumnSpan(tfTask, 4);
    GridPane.setConstraints(tfTask, 5, 0);
    //(Houtman, 2017)
    Label lblSubject = new Label("Subject");
    GridPane.setConstraints(lblSubject, 2, 6);
    TextArea taSubject = new TextArea(td.getSubject());
    GridPane.setColumnSpan(taSubject, 4);
    GridPane.setConstraints(taSubject, 5, 6);
    //(Houtman, 2017)
    Label lblDate = new Label("Due Date");
    GridPane.setConstraints(lblDate, 2, 12);
    TextField tfDate = new TextField(td.toString());
    GridPane.setColumnSpan(tfDate, 4);
    GridPane.setConstraints(tfDate, 5, 12);
    //(Houtman, 2017)
    Label lblPriority = new Label("Priority");
    GridPane.setConstraints(lblPriority, 2, 20);
    //(Class GridPane, n.d)
    final ToggleGroup radioGroup = new ToggleGroup();
    RadioButton rButton1 = new RadioButton("1");
    rButton1.setToggleGroup(radioGroup);
    GridPane.setConstraints(rButton1, 6, 20);
    RadioButton rButton2 = new RadioButton("2");
    rButton2.setToggleGroup(radioGroup);
    GridPane.setConstraints(rButton2, 7, 20);
    RadioButton rButton3 = new RadioButton("3");
    GridPane.setConstraints(rButton3, 8, 20);
    rButton3.setToggleGroup(radioGroup);
    //(Redko, 2013)
    infoPane.getChildren().addAll(lblTask, lblSubject, lblDate, lblPriority, tfTask, taSubject, tfDate, rButton1, rButton2, rButton3);
    return infoPane;
}

public Pane getBottomPane()
{

    Button btnFirst = new Button("|<<");
    btnFirst.setOnMouseClicked((e) -> {
        setToDoElement(findFirstValue());
        getPrimaryStage().setScene(getToDoScene(getToDoArray().get(currentToDoElement)));
    });
    if(btnBeginDisableCheck() || prevEmptyCheck())
    {
        btnFirst.setDisable(true);
    }
    Button btnLast = new Button(">>|");
    btnLast.setOnMouseClicked((e) -> {
        setToDoElement(findFinalValue());
        getPrimaryStage().setScene(getToDoScene(getToDoArray().get(currentToDoElement)));
    });
    if(btnEndDisableCheck() || nextEmptyCheck())
    {
        btnLast.setDisable(true);
    }
    Button btnNext = new Button(">>");
    btnNext.setOnMouseClicked((e) -> {
        setToDoElement(findNextValue());
        getPrimaryStage().setScene(getToDoScene(getToDoArray().get(currentToDoElement)));
    });
    if(btnEndDisableCheck() || nextEmptyCheck())
    {
        btnNext.setDisable(true);
    }
    Button btnPrev = new Button("<<");
    btnPrev.setOnMouseClicked((e) -> {
        setToDoElement(findPrevValue());
        getPrimaryStage().setScene(getToDoScene(getToDoArray().get(currentToDoElement)));
    });
    if(btnBeginDisableCheck() || prevEmptyCheck())
    {
        btnPrev.setDisable(true);
    }
    //Houtman, D (n.d) Module 04: Intro to JavaFX [PowerPoint Slides]
    //Retrieved from https://blackboard.algonquincollege.com/bbcswebdav/pid-2266545-dt-content-rid-8023117_1/courses/17W_CST8284_300/17W_Module%2004%20-%20Introduction%20to%20JavaFX%287%29.pdf
    HBox hbBottom = new HBox();
    hbBottom.setAlignment(Pos.CENTER);
    hbBottom.setSpacing(15);
    //(Hbox, n.d)
    hbBottom.getChildren().addAll(btnFirst, btnPrev , btnNext, btnLast);
    return hbBottom;
}

public boolean btnBeginDisableCheck()
{
    return(getToDoElement() == 0);
}

public boolean btnEndDisableCheck()
{
    return(getToDoElement() == getToDoArray().size() - 1);
}

public boolean nextEmptyCheck()
{
    int startingElement = getToDoElement() + 1;
    if(startingElement >= getToDoArray().size())
    {
        return true;
    }
    while(getToDoArray().get(startingElement).isEmptySet())
    {
        startingElement++;
        if(startingElement == getToDoArray().size())
        {
            return true;
        }

    }
    return false; 
}

public boolean prevEmptyCheck()
{
    int startingElement = getToDoElement() - 1;
    while(getToDoArray().get(startingElement).isEmptySet())
    {
        startingElement--;
        if(startingElement <= -1)
        {
            return true;
        }   
    }
    return false;
}

public int findNextValue()
{
    int nextValue = getToDoElement();
    do
    {
        nextValue++;
    }while(getToDoArray().get(nextValue).isEmptySet());
    return nextValue;
}

public int findPrevValue()
{
    int PrevValue = getToDoElement();
    do
    {
        PrevValue--;
    }while(getToDoArray().get(PrevValue).isEmptySet());
    return PrevValue;
}

public int findFinalValue()
{
    int finalValue = getToDoArray().size() - 1;
    while(getToDoArray().get(finalValue).isEmptySet())
    {
        finalValue--;
    }
    return finalValue;
}

public int findFirstValue()
{
    int firstValue = getToDoArray().size() - getToDoArray().size();
    while(getToDoArray().get(firstValue).isEmptySet())
    {
        firstValue++;
    }
    return firstValue;
}   

public void getFile()
{
    FileChooser fc = new FileChooser();
    fc.setTitle("Open ToDO File");
    fc.setInitialDirectory(new File("D:\\"));
    //fc.setInitialDirectory(new File("C:\\Users\\Alec\\Desktop"));
    //refernce docs
    fc.getExtensionFilters().addAll(
            new ExtensionFilter("Quiz Files", "*.todo"),
            new ExtensionFilter("All Files", "*.*")
            );
    File todoFile = fc.showOpenDialog(primaryStage);   //turn this into a method to be used down below for saving to the file.
    //(Houtman, 2017)
    if(checkExentsion(todoFile))
    {
        FileUtils utils = new FileUtils();      
        FileUtils.setAbsPath(todoFile);
        utils.getToDoArray(todoFile.getAbsolutePath());  //possible redundancy
        setToDoArray(utils.getToDoArray(FileUtils.getAbsPath()));
        setToDoElement(findFirstValue());
        getPrimaryStage().setScene(getToDoScene(getToDoArray().get(getToDoElement())));
        getPrimaryStage().show();
        System.out.print(getToDoArray().size());    
    }
    else
    {
        getErrorStage();
    }       
}

public Stage getErrorStage()
{
    Stage errorDialogue = new Stage();
    errorDialogue.setScene(getErrorScene());
    errorDialogue.setTitle("Invalid .todo file selected");
    errorDialogue.setResizable(false);
    errorDialogue.initStyle(StageStyle.UTILITY);
    //reference needed, stackoverflow
    errorDialogue.show();
    return errorDialogue;

}

public Scene getErrorScene()
{

    HBox hbox = new HBox();
    hbox.setAlignment(Pos.CENTER);
    hbox.setSpacing(50.5);
    Button btnOk = new Button("OK");
    btnOk.setOnMouseClicked((e -> {
        getFile();
    }));
    HBox.setMargin(btnOk, new Insets(0,0,25,0));
    //reference needed, docs
    Button btnCancel = new Button("Cancel");
    btnCancel.setOnMouseClicked((e -> {
        Platform.exit();
    }));
    hbox.getChildren().addAll(btnOk, btnCancel);
    HBox.setMargin(btnCancel, new Insets(0,0,25,0));
    //referned docs
    Label errorLabel = new Label("You did not select a valid .todo file. Please select a valid .todo file. Selecting cancel will exit the program.");
    BorderPane errorPane = new BorderPane();
    errorPane.setCenter(errorLabel);
    errorPane.setBottom(hbox);
    Scene errorScene = new Scene(errorPane, 700, 150);

    return errorScene;

}

public boolean checkExentsion(File fName)
{
    String extension = fName.getName().substring(fName.getName().lastIndexOf("."));
    return (extension.equals(".todo"));
    //reference here
}

public MenuBar getMenuBar()
{
    MenuBar mBar = new MenuBar();
    mBar.prefWidthProperty().bind(primaryStage.widthProperty());
    Menu fileMenu = new Menu("File");
    MenuItem openMenu = new MenuItem("Open");
    openMenu.setOnAction((e) -> {
        getFile();
    });
    MenuItem saveMenu = new MenuItem("Save");
    saveMenu.setOnAction((e) -> {
        FileUtils.saveToDo(FileUtils.getAbsPath(), getToDoArray());
    });
    MenuItem addTD = new MenuItem("Add ToDo");
    MenuItem removeTD = new MenuItem("Remove ToDo");
    MenuItem exitMenu = new MenuItem("Exit");
    exitMenu.setOnAction(actionEvent -> Platform.exit());

    fileMenu.getItems().addAll(openMenu, saveMenu, addTD, removeTD,
            new SeparatorMenuItem(), exitMenu);
    mBar.getMenus().add(fileMenu);
    return mBar;
    //reference here
}

}

And the actual file I/O class public class FileUtils {

private static String relPath = "ToDoList.todo";
                    //Houtman, D. March 17th, 2017, Assignment1.zip [Zip File Download]. 
                    //Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
public ArrayList<ToDo> getToDoArray(String fileName) {
    ArrayList<ToDo> toDoArray = new ArrayList<>();
    try
    {
        FileInputStream objectFileStream = new FileInputStream(fileName);
        ObjectInputStream ois = new ObjectInputStream(objectFileStream);
        //Houtman, D. March 17th, 2017, File I/O Part 2 [MP4 File]. 
        //Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_2178319_1&mode=reset
        Object obj = null;
        while ((obj = ois.readObject()) != null) {
            if (obj instanceof ToDo) {
            ToDo newObject = (ToDo) obj;
            toDoArray.add(newObject);
            }
        }
        //reference stackoverflow
        ois.close();
        objectFileStream.close();
    }

    catch(ClassNotFoundException | IOException e){
        e.printStackTrace();
    }
    //(Houtman, 2017)
    return toDoArray;
}



public static String getAbsPath() {
    return relPath;
}
//Houtman, D. March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
public static String getAbsPath(File f) {
    return f.getAbsolutePath();
}
//Houtman, D. March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
public static void setAbsPath(File f) { 
    relPath = (fileExists(f))? f.getAbsolutePath():""; 
}
//Houtman, D. March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset
public static Boolean fileExists(File f) {
    return (f != null && f.exists() && f.isFile() && f.canRead());
}
//Houtman, D. March 17th, 2017, Assignment1.zip [Zip File Download]. 
//Retrieved from https://blackboard.algonquincollege.com/webapps/blackboard/content/listContent.jsp?course_id=_345505_1&content_id=_1930549_1&mode=reset

public static void saveToDo(String fileName, ArrayList<ToDo> td)
{
    try{
    FileOutputStream objectFileStream = new FileOutputStream(fileName);
    ObjectOutputStream oos = new ObjectOutputStream(objectFileStream);
    for(ToDo tdArray : td){
    oos.writeObject(tdArray);
    }
    oos.close();
    objectFileStream.close();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
}

}

EDIT: In regards to being marked as a duplicate, I've tried the steps provided in that thread to no avail. There is something going on locally in my code that I fundamentally am having a hard time understand. Marking this as a duplicate does nothing for me. (Or anyone else having a similar problem.)

EDIT2: I'd like to reiterate that I have come to my own conclusions as what I believe the root problem to be. In terms of the stack trace, I believe when it runs the findFirst method, it finds nothing, and thats why it throws the exception, but I believe it throws the exception because the objectoutput stream is outputting an empty array list.

  • 2
    Wrong strategy. You're trying random things instead of reading the message and stack trace of the exception which would tell you (and us, if you post it) what is wrong and where the problem is. – JB Nizet Apr 05 '17 at 17:03
  • I have added the full stack trace. – ComradeSpaceMan Apr 05 '17 at 17:09
  • 1
    So, as you can see, the exception has nothing to do with your method saveTodo(). It happens in findFirstValue(), at line 335 of the file TaskManager.java. That's where you should start your investigation. – JB Nizet Apr 05 '17 at 17:11
  • Which I have tried. It tries to load the first element in the ArrayList, but it does not find anything. Above, I have the method written to search from the element 0, until the very end. It does not find anything, and throws the exception, which lead me to believe it's not even saving anything period. Which is something I've stated above. – ComradeSpaceMan Apr 05 '17 at 18:01

0 Answers0