File Input/Output in a JavaFX Application

You can use the APIs in the java.io package to read character data or byte data into a program, and write character or byte data to an external file, storage device, or program. The source or destination might be on the local computer system where the program is running or anywhere on the network. This section shows how to read data from and write data to a file on the local computer system.

  • Reading: A program opens an input stream on the file and reads the data in serially (in the order it was written to the file).
    Writing: A program opens an output stream on the file and writes the data out serially.

The example was built with the following software configuration:

  • JDK1.8.0_45
  • Apache Tomcat v8.0.36
  • Eclipse Mars.2 Release (4.6.0)

About the Example

This example converts the Build a JavaFX User Interface example to accept user input through a text field and save it to a file. The window on the left displays when you start the FileIO application. When you click the button, whatever is entered into the text field is saved to a file. After that, the file is opened, read, and its text displayed in the window on the right. Click again and you are back to the original window with a blank text field ready for more

Start Method: This start method uses a TextField control for the user to input text that is saved to a file.

File I/O:  The handle method uses the FileInputStream and FileOutputStream classes to read data from and write data to a file. These classes handle data in byte streams instead of character streams.  To write the input text to a file, the text is retrieved from the textField and converted to a byte array.

  1. The FileOutputStream object writes the byte array to the text.txt file and closes the output stream when the write operation completes.
  2. To read text from a file, a File object is created and used to create a FileInputStream object.
  3. Next, a byte array is created that is the same length as the file into which the text is stored.
  4. The byte array is used to construct a String object, which contains the retrieved text displayed in the textField component. The FileInputStream is closed when the operation completes.

You might think you could simplify this code by not creating the File object and just passing the inputFileName String object directly to the FileInputStream constructor. The problem is the FileInputStream object reads a byte stream, and a byte stream is created to a specified size. In this example, the byte stream needs to be the same size as the file, and that size varies depending with the text written to the file. The File class has a length method that lets you get this value so the byte stream can be created to the correct size each time.

Build in Eclipse

  1. Create the Project
  2. Add Code to the Project
  3. Enable JavaFX in Eclipse
  4. Add a Cascading Style Sheet
  5. Clean, Build, and Run the Example

1. Create the Project

  1. Select File > New > Project
  2. Select Java Project and click Next
  3. Name the project FileIOProject and click Finish

2. Add Code to the Project

  1. Expand the FileIO project and right-click the src folder
  2. Select New > Package
  3. Give the package the name: com.fileio and click finish
  4. Right-click the com.fileio package and select New > Class
  5. Give the new class the name: FileIO and click Finish
  6. Copy the following code into the FileIO class file:

FileIO class file:

package com.fileio;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 *
 * @author mpawlan
 */
public class FileIO extends Application {

    TextField textField;
    Label text, clicked;
    Button button, clickButton;
    BorderPane BPane;
    private boolean _clickMeMode = true;

    @Override
    public void start (Stage primaryStage) { 
    //Create GridPane
    BPane = new BorderPane();
    BPane.setId("grid-pane");
    BPane.getStyleClass().add("pane-styles");

    //Create Scene and add Grid
    Scene Scene = new Scene(BPane, 300, 200);
            Scene.getStylesheets().add(this.getClass().getResource(
                    "EssentialsJPL.css").toExternalForm());
 
    //Create the stage and add the scene
    primaryStage.setTitle("FileIO Application");
    primaryStage.setScene(Scene);

    text = new Label("Text to save to file:");
    textField = new TextField();
    textField.setMaxWidth(200);
    button = new Button("Click Me");
    button.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        Object source = event.getSource();
        String s = null;
        //Variable to display text read from file
        if (_clickMeMode) {
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
            //Code to write to file
            String text = textField.getText();
            byte b[] = text.getBytes();
            String outputFileName = System.getProperty("user.home",
            File.separatorChar + "home"
                + File.separatorChar + "monica")
                + File.separatorChar + "text.txt";
                out = new FileOutputStream(outputFileName);
                out.write(b);
                out.close();
                //Clear text field
                textField.setText("");
                //Code to read from file
                String inputFileName = System.getProperty("user.home",
                    File.separatorChar + "home"
                    + File.separatorChar + "monica")
                    + File.separatorChar + "text.txt";
                File inputFile = new File(inputFileName);
                in = new FileInputStream(inputFile);
                byte bt[] = new byte[(int) inputFile.length()];
                in.read(bt);
                s = new String(bt);
                in.close();
            } catch (java.io.IOException e) {
                    System.out.println("Cannot access text.txt");
            } finally {
                try {
                    in.close();
                    out.close();
                } catch (java.io.IOException e) {
                    System.out.println("Cannot close");
                }
            }
            //Clear text field
            textField.setText("");
            //Display text read from file
            text.setText("Text retrieved from file: \n\n" + s);
            BPane.getChildren().remove(textField);
            button.setText("Click Again");
            _clickMeMode = false;
        } else {
            //Save text to file
            text.setText("Text to save to file:");
            BPane.getChildren().add(textField);
            textField.setText("");
            button.setText("Click Me");
            _clickMeMode = true;
        }
    }
    });

    //Set positions for each control in the BorderPane
    BPane.setTop(text); 
    BPane.setCenter(textField);
    BPane.setBottom(button);
           
    //Show the scene
    primaryStage.show(); 
} 
    
    //main method
    public static void main(String[] args){
        launch(args);
    }
}

3. Enable JavaFX in Eclipse

JavaFX is not by default enabled on Eclipse. The easiest way to enable JavaFX is to add the path to jfxrt.jar to your build path.

  1. Right click FileIOProject
  2. In the drop-down menu, select Build Path > Configure Build Path.
  3. In the Libraries tab, select Add External JARs.
  4. Add the path to your jfxrt.jar file, for example:
    C:\Program Files (x86)\Java\jre1.8.0_91\lib\ext.javafxconfigure

Alternately and especially if you plan to do a lot of JavaFX programming, you can install e(fx)clipse, which is a plugin for Eclipse that supports JavaFX. See the following link for more information: https://www.eclipse.org/efxclipse/install.html#for-the-lazy.

4. Add a Cascading Style Sheet

The look and feel of JavaFX applications can be customized. Cascading Style Sheets (CSS) contain style definitions that control the look of user interface elements. CSS also separate appearance and style from implementation so that developers can concentrate on coding. Graphic designers can easily customize the appearance and style of the application through the CSS.

The following code adds the EssentialsJPL.css cascading style sheet (css) to the example program.

//Create Scene and add Grid
Scene Scene = new Scene(BPane, 300, 200);
  Scene.getStylesheets().add(this.getClass().getResource(
    "EssentialsJPL.css").toExternalForm());

The example program uses the following style definitions. See Skinning JavaFX Applications with CSS at http://docs.oracle.com/javafx/2/css_tutorial/jfxpub-css_tutorial.htm and The CSS Reference Guide at http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html for more information.

You must create and add this style sheet to your project:

  1. Right-click the com.fileio package and select File > Other
  2. Highlight CSS File under Web > CSS File and click Next
  3. Name the CSS fIle EssentialsJPL.css and click Finish.
  4. Locate the CSS file in your project and open it.
    It belongs under the com.fileio package. If it is not there, move it.
  5. Change the top line from @CHARSET “ISO-8859-1”; to [@CHARSET “ISO-8859-1”;]
  6. Copy and paste the following style sheet definitions into the css file (omit the [@CHARSET “ISO-8859-1”;] line below if you already replaced it in Step 5 :
[@CHARSET "ISO-8859-1";]
/* Global style definitions. Apply to all UI elements in the application. */
.root {
  display: block;
  -fx-font-size: 14px "Serif";
  -fx-font-family: Tahoma;
  -fx-font-weight: NORMAL;
}
/* Border pane style definitions. Apply to all UI elements in the border pane.
The pane-styles style definition was added to the border pane on Line 26. */
.pane-styles {
  -fx-background-color: rgb(87, 206, 248);
  -fx-hgap: 2px;
  -fx-vgap: 2px;
  -fx-padding: 5px;
  -fx-grid-lines-visible: false;
}
/* Labels in the border pane have this additional style definition. */
.pane-styles .label {
  -fx-padding: 10 10 10 0;
}
/* Text fields in the border pane have these additional style definitions. */
.pane-styles .text-field {
  -fx-background-color: #999999, #336699,
  linear-gradient(to bottom, #fff 0%, #ccc 100%);
  -fx-background-insets: 1px, 2px, 3px;
  -background-radius: 0px 0px 9px 0px, 0px 0px 8px 0px, 0px 0px 8px 0px;
  -padding: 5px;
  -fx-display-caret: true;
}
/* buttons added to the border pane have these additional style definitions. */
.pane-styles .button {
  -fx-background-color: #707070,
  linear-gradient(#fcfcfc, #f3f3f3),
  linear-gradient(#f2f2f2 0%, #ebebeb 49%, #dddddd 50%, #cfcfcf 100%);
  -fx-background-insets: 1px, 2px, 3px;
  -fx-padding: 3px 20px 3px 20px;
}

Clean, Build, and Run the Example

  1. Save all of your files.
  2. Select the FileIO project and select Project > Clean
  3. Select the FileIO project and select Project > Build Project
  4. Right click the FileIO project and select Run As > Java Application
File Input/Output in a JavaFX Application

7 thoughts on “File Input/Output in a JavaFX Application

  1. Include the folder name in the path. For example, the following code stores the text.txt file under the monica folder, which is under the home folder.
    String inputFileName = System.getProperty(“user.home”,
    File.separatorChar + “home”
    + File.separatorChar + “monica”)
    + File.separatorChar + “text.txt”;

    Like

    1. Tamas Soos says:

      What if I would like to save the document to a specific folder in a specific hard drive like hard drive D: for example?

      Like

Leave a reply to Monica Cancel reply