Exception Handling for File Operations
A JFileChooser object is only a description of a dialog until showOpenDialog or showSaveDialog is called, and those calls block until the user responds.
Why a Program Cannot Know Which File to Use
A program that reads or writes a file usually needs a name for that file. Hard-coding a name works for a quick test, but a text editor or data viewer cannot know in advance which file the person at the keyboard wants. Java's Swing library addresses this with a ready-made window for choosing files. That window is built from a class named JFileChooser, which lives in the javax.swing package.
This article follows one routine from start to finish. You will predict what happens when the user makes different choices, check those predictions against a traced execution, and then use the same reasoning to locate the exact point where a program departs from what you expected. The goal is to read file-dialog code the way a debugger reads it: step by step, asking at each line what state the program is now in.
What do you think happens?
You write JFileChooser chooser = new JFileChooser(); and nothing else. Does a file dialog appear on screen?
Reveal answer
No, nothing is shown yet.
The constructor only builds the object in memory. A window appears only when your code calls one of the show methods on that object.
A Dialog Is Only a Description Until It Is Shown
A JFileChooser object is only a description of a dialog until showOpenDialog or showSaveDialog is called. Creating the object does not display anything, and the object is not yet interacting with the user. Something visible happens only when your code calls one of the two show methods.
The show methods are also blocking. The call does not finish until the user has either selected a file or dismissed the window. From the point of view of the calling code, the line that calls showOpenDialog does not produce its result until the user has acted. Only then does execution move on to the next line.
Read the diagram from top to bottom. Steps 1 and 2 happen entirely in memory, so the user sees nothing. Step 3 is the moment the dialog becomes real. Steps 4 and 5 happen while the calling code is paused inside that single method call. Step 6 is the only point at which the calling code learns the outcome.
Configuring the Chooser Before It Appears
Configuration is optional, but it is common practice to set a few properties before showing the window. Because the window has not been displayed yet, these settings shape what the user first sees. The two properties that appear again and again in real routines are the dialog title and the currently selected file.
Reading the Return Value
When showOpenDialog or showSaveDialog returns, it gives back one of three integer constants: JFileChooser.APPROVE_OPTION, JFileChooser.CANCEL_OPTION, or JFileChooser.ERROR_OPTION. Only APPROVE_OPTION means the user actually selected a file. Every other value means the program should not expect a file. The Cancel button is the usual example of a non-approval, but closing the window with its close box produces the same kind of result.
The method that receives the answer is getSelectedFile(), which returns a File object describing the chosen file. The safe order is fixed. First compare the return value with APPROVE_OPTION. Only if that comparison succeeds should you ask the dialog for the selected file. Asking for a selected file after the user cancelled gives the program nothing meaningful to work with, so the check must come first.
Notice what the diagram implies. On the yes branch, getSelectedFile and the Scanner line run. On the no branch, both are skipped entirely and the routine ends. A routine that returns early in the no case is not broken. It is doing exactly what it was written to do when the user declined to pick a file.
Tracing a Routine That Opens a File
The following routine prepares the dialog, shows it, checks the answer, obtains the selected file, and then creates a Scanner on that file. It is written to match the steps described above. Read it line by line before looking at the trace that follows.
- 1Line 1 to 3: the imports bring in the chooser, the File class, and the Scanner.
- 2Line 6: the chooser object is created in memory. Nothing is displayed yet.
- 3Line 9: the title is stored in the chooser, still without showing anything.
- 4Line 10: the selection is reset to null so the dialog starts neutral.
- 5Line 11: the window appears and the call blocks until the user acts. The returned integer is stored in result.
- 6Line 12 to 15: if result is not APPROVE_OPTION, the message prints and return exits the method. Nothing after this point runs.
- 7Line 16: only on the approve path is
getSelectedFilecalled to obtain the chosen File. - 8Line 17 to 19: the Scanner is created on the file, a message prints, and the scanner is closed.
- The chooser is a static field, so it is created once and reused on each call
- The title is set before the window is shown
setSelectedFile(null)clears any file highlighted during an earlier useshowOpenDialogblocks until the user responds, then returns an integer- The guard compares the result with APPROVE_OPTION before asking for the file
If the user presses Cancel:
No file chosen; returning early.
If the user selects a file named notes.txt:
Opened: notes.txtTracing the state when the user cancels
The user opens the window and then presses Cancel. Trace the variables and which lines run.
- 1Build and configure
chooser exists and its title is set. result has no value yet, and no window is visible.
- 2Show the dialog
showOpenDialogruns. The window appears, and execution waits inside this line. - 3Return the answer
The user presses Cancel.
showOpenDialogreturns CANCEL_OPTION, and result now holds that value. - 4Evaluate the guard
result is not equal to APPROVE_OPTION, so the condition is true and the print line runs.
- 5Exit
return executes.
getSelectedFileand the Scanner line are skipped, and no file is opened.
The routine prints a message and ends. It never calls getSelectedFile, so there is no file to read.
Using the routine above, predict what happens if you delete the if block entirely and the user presses Cancel. Which line would then receive a value that is not a real file?
Hints
- Think about what
getSelectedFilereturns when the user has not chosen a file. - Ask whether the Scanner line can still run when the guard is removed.
Guarding Against Overwriting an Existing File
Writing a file through a dialog raises a different concern. The save dialog allows the user to name a file that already exists, and writing to that file would destroy its previous contents. The source material therefore recommends a specific check. After the user approves a choice, ask whether the chosen file already exists. If it does, ask the user to confirm the replacement before anything is written.
- The first guard checks whether the user chose anything at all
- The second guard checks whether the chosen name collides with an existing file
askUserToConfirmReplacementandwriteToare placeholders for your own code
Read the diagram as two separate guards in sequence. The first guard concerns whether the user chose anything at all. The second concerns whether the chosen name collides with an existing file. A learner who knows only one of these guards will be surprised when a save ends without writing, so it helps to point to which decision produced the outcome. If the first guard stopped the save, the user never chose a file. If the second guard stopped it, the user chose an existing file and declined to replace it.
Mistakes That Lead to Lost Data or Confusing Dialogs
Common mistake Calling getSelectedFile before comparing the return value
What it looks likeFile f = chooser.getSelectedFile(); then checking the result afterward
Why it failsWhen the user cancelled, there is no meaningful selected file to work with, so the code is operating on nothing useful.
Do this insteadCompare the result with JFileChooser.APPROVE_OPTION first, and only then call getSelectedFile.
Common mistake Assuming the constructor shows the window
What it looks likeJFileChooser chooser = new JFileChooser(); followed by reading a file as if the user had already answered
Why it failsThe constructor only builds the object in memory. Nothing is displayed until a show method is called.
Do this insteadCall showOpenDialog or showSaveDialog, and only use the result after that call returns.
Common mistake Saving to a chosen name without checking whether it exists
What it looks likeWriting directly to target after getSelectedFile returns
Why it failsIf the name belongs to an existing file, writing replaces its previous contents.
Do this insteadCall exists() on the chosen file and ask the user to confirm before replacing it.
Common mistake Treating only the Cancel button as a non-approval
What it looks likeChecking for CANCEL_OPTION alone and ignoring ERROR_OPTION
Why it failsAny value other than APPROVE_OPTION means the program should not expect a file.
Do this insteadCompare against APPROVE_OPTION so every non-approval result takes the same safe path.
Common mistake Forgetting to reset the selection, so a file chosen for an earlier purpose is highlighted again
Practice Predicting the Path Through a Save
A save routine calls showSaveDialog. The user types the name of a file that already exists and then clicks the approve button. The user then answers no to the replacement confirmation. Before reading the answer, state which decision points are passed and whether writeTo runs.
Hints
- Start with the APPROVE_OPTION check. Did the user approve?
- Next, ask whether the chosen file exists.
- Then check the confirmation answer. Does
writeTosit after a path that returns?
Key Takeaways
- A
JFileChooseris only a description untilshowOpenDialogorshowSaveDialogis called, and those calls block until the user responds. - Compare the integer result with APPROVE_OPTION before calling
getSelectedFile; only APPROVE_OPTION means the user chose a file. - Set the title before showing the dialog, and call
setSelectedFile(null)on each use so the dialog starts from a neutral state. - When saving, check whether the chosen file already exists and confirm before replacing it, so an existing file's contents are not destroyed by accident.