Level-up challenge · CSCD210
One program that writes a file and reads it back into an array
You have finished the catch-up path and you want to write one program that makes a file and then reads it back the way a lab will ask you to.
Unlocked at the end of: Arrays and file I/O, from zero, after the room count-allocate-fill. Room 15 closes the path. After it you have written a file, opened it, read it to the end, and built the count pass and the fill pass yourself, which is exactly the program this challenge asks for.
What this shows you can do
Each line below is one outcome, written the way the course records it. A program that does the whole task shows all of them at once.
Student can construct a
PrintStreamover aFile, declare or catch theFileNotFoundExceptionthe constructor throws, write output withprintln/printf, andclose()the stream to flush buffered bytes.In this program: Everything the program reports comes back out of the file it wrote, so a program that does not construct the stream, does not declare the exception, or writes nothing produces no report at all.
Not shown by a run:"
close()the stream to flush buffered bytes". Removing the close from the writing method changed no line of any check, becausePrintStream(File)wraps aFileOutputStreamwith no byte buffer of its own and the bytes reach the operating system as eachprintlnruns. The guarantee still needs the close and the spec still asks for it, and a run is not what shows it.Student can construct a
Scannerover a file using the two-step idiomnew Scanner(new File(filename)), declare or catch theFileNotFoundExceptionthe constructor throws, and close theScannerto release the file handle when finished.In this program: Measured: replacing the two-step idiom with
new Scanner(filename)in the counting pass reports zero readings and then ends with ArrayIndexOutOfBoundsException, because the scanner reads the characters of the file name instead of the file.Not shown by a run:"close the
Scannerto release the file handle when finished". A comparison of what a program prints cannot see a close.Student can import
java.io.FileNotFoundException, declare it withthrowson every method that constructs aScanneron aFile, distinguish it fromFileSystemNotFoundExceptioninjava.nio.file, and explain why a pre-check (e.g.,exists()orcanRead()) does not remove the declaration requirement.In this program: Three of the four required headers already carry the line, and
maincalls all three. The header ofmainis not given, so the program does not compile until the student carries the line up to it or handles it there.Not shown by a run:"distinguish it from
FileSystemNotFoundException" and "explain why a pre-check does not remove the declaration requirement". Both of those are said. What a run shows is that the import and the declarations are right, because nothing compiles otherwise.Student can write a
while (sc.hasNextLine())loop to read every line of a file, recognize the guard-and-read pairing, and adapt the pattern for counting lines (Pass 1 of count-allocate-fill) and for skipping a header before the loop.In this program: The file has a header line and then one reading per line, so the counting pass has to skip before the loop and pair one guard with one read inside it. Measured: a loop that reads in the guard and again in the body counts half the lines, or ends with NoSuchElementException when the count left is odd.
Student can produce a Pass-1 counting method that takes a filename, opens a fresh Scanner, walks to EOF using a
hasNextLine(orhasNextX) guard, increments a counter while discarding the read value, closes the Scanner, and returns the count.In this program: The first line of the report is the count this method returns, and the four checks have four different counts, so a count that comes from anywhere else matches at most one of them.
Not shown by a run:"closes the Scanner". Not visible in output, the same limit as the Scanner leaf above.
Student can produce a Pass-2 method that takes a filename and a count, opens a fresh Scanner, allocates an array of exactly
countslots, fills it with a countedforloop using the appropriate typed read, closes the Scanner, and returns the array.In this program: The report prints the array's own slot count and its first and last values, so an array allocated larger than the count shows a wrong slot count and a last value of zero.
Not shown by a run:"closes the Scanner", as above.
What to build
Write one program named ReadingsFile.
It reads from standard input. The first number is how many readings follow. Each reading after that is a whole number, and there is at least one.
The program does three things, in order.
First it writes a file named readings.txt in the folder it is running in. The first line of that file is the single word readings. Every line after that is one reading, in the order they arrived.
Then it reads that file back twice. The first pass counts how many readings the file holds, which is every line after the header. The second pass builds an int[] with exactly that many slots and fills it with the readings from the file. Each pass opens the file for itself.
Then it prints five lines, in this order, with the labels spelled exactly as shown here:
readings in file
slots
first
last
sumEach line is the label, a colon, one space, and the value. Print nothing else, and print no prompt. Nothing in the output names the folder the program ran in.
Every method that opens a file carries throws FileNotFoundException. Three of the four headers below already have it. Java will tell you if another method needs it too.
The rest of the program is yours to shape.
Write these methods with these headers
- public static void writeReadings(final String filename, final int[] xs) throws FileNotFoundException
- public static int countReadings(final String filename) throws FileNotFoundException
- public static int[] readReadings(final String filename, final int count) throws FileNotFoundException
- public static int sum(final int[] xs)
One worked example
The first of the inputs, with what the program prints for it.
Five readings, all positive
The count in the report has to come from the file rather than from standard input, which is what the second and third lines of the report separate.
5
71
68
78
62
69
readings in file: 5
slots: 5
first: 71
last: 69
sum: 348
How your program is checked
Your program is run once for each input and its output is compared with what is shown. The worked example above is the first of them. You can run every one of them yourself before you hand anything in.
One reading
The smallest file the spec allows, one header line and one reading, where a counting pass that includes the header is off by a factor of two rather than by a little.
1
40
readings in file: 1
slots: 1
first: 40
last: 40
sum: 40
Eight readings, mixed signs, with a repeated value
Negative numbers are written and read back as tokens, so this is the check that a minus sign survives the round trip through the file.
8
-3
12
5
-8
20
1
20
7
readings in file: 8
slots: 8
first: -3
last: 7
sum: 54
Three readings, all negative
A third count, so a program that returns a fixed number from the counting pass cannot pass more than one check.
3
-12
-7
-25
readings in file: 3
slots: 3
first: -12
last: -25
sum: -44
What to watch for
Each one is copied from the notes for the rooms this challenge draws on, with what a run shows when it happens.
new Scanner(filename)instead ofnew Scanner(new File(filename))What a run shows: The report says zero readings and zero slots, and then the run ends with ArrayIndexOutOfBoundsException on the line that asks for the first value.
omitting
throws FileNotFoundExceptionafter writing a runtime checkWhat a run shows: Nothing runs. The compiler stops at the line that opens the file.
importing
java.nio.file.FileSystemNotFoundExceptioninstead ofjava.io.FileNotFoundExceptionWhat a run shows: Nothing runs. The wrong import satisfies nothing, so the compiler still asks for the exception the constructor actually throws.
reading inside the guard and inside the body (double-read)
What a run shows: The count comes out at half the readings when the number left is even, and the run ends with NoSuchElementException when it is odd.
omitting
sc.nextLine()inside the loop bodyWhat a run shows: The run does not end on its own and the sandbox stops it at the CPU limit, so there is no output to compare.
counting before the header skip
What a run shows: The count is one too high, so the filling pass asks the file for one more reading than it holds and the run ends with NoSuchElementException before anything is printed.
forgetting to skip the header in Pass 2
What a run shows: The run ends with InputMismatchException, because the first thing the filling pass tries to read as a number is the word
readings.forgetting
close()and finding an empty fileWhat a run shows: Nothing. Measured on the reference machine, every line of every check was identical with the close removed, because
PrintStream(File)has no byte buffer of its own. APrintWriterin the same shape does leave the file empty. The spec still asks for the close, and the checks do not see it.passing a
StringtoPrintStreamWhat a run shows: Nothing. The
PrintStream(String)constructor opens the file, so the output is right. The leaf keeps this one because the same habit on the reading side is the pitfall above it, which does fail every check.mode mismatch between Pass 1 and Pass 2
What a run shows: Nothing, with this file. Counting lines and reading whitespace-separated numbers agree when there is one number on each line, which is the shape the spec asks for. A file with two numbers on a line would separate them.
using
while (sc.hasNext...)in Pass 2What a run shows: Nothing, as long as the counting pass is right. An end-of-file loop fills the same slots. It stops being the same when the count is wrong, and then it hides the wrong count instead of showing it.
What this puts on your resume
You have written Java that creates a text file, reads it back in two separate passes to learn how many records it holds, and loads those records into an array sized to fit them.
What the program needs where it runs
- The sandbox has to let the program create a file in the folder it runs in.
- Each check runs in a folder of its own, or the file left by the previous check is read by the next one. The reference runs used a fresh temporary folder for every case.
- Not yet confirmed on the deployed runner. This was verified locally only. No call was made to the Judge0 host from this pass.
Mark it built
Nothing on this page runs your program. You run it yourself, once for each input above, and compare what it prints with what is shown. When all of them match, check the box. The mark is your own note about your own work, and it stays in this browser.
Unchecking the box takes the mark back off. Each outcome above then reads whatever the rest of your work shows.