Files: Commentary

Steven Zeil

Last modified: Aug 19, 2016
Contents:

We’ve looked at how to read and write from various kinds of input and output sources, including files. Now we want to take a brief look at working with files and directories directly.

1 I/O Streams

We’ve already covered this section earlier. Feel free to review it if you wish. Otherwise skip ahead to section 2.

2 File I/O (Featuring NIO.2)

C++ programmers are used to storing file information in ordinary strings. Suppose, for example, that you wanted to write some data into a file named “temp.dat” in a directory that had been passed to you for that purpose. In C++, you might write something like:

void writeDataToFile (string data, string directory)
{
   string fileName = directory + "/" + "temp.dat";
   ofstream out (fileName);
   out << data;
   out.close();
}

Now, this code isn’t all that bad. It would work fine on a Linux or OSX machine. It would have problems on Windows, because in Windows the separator character between a directory and a file for other directory is the backslash instead of a forward slash, so you would need

string fileName = directory + "\\" + "temp.dat";

or, more generally,

void writeDataToFile (string data, string directory)
{
#ifdef __WIN32
   string separator = "\\";
#else
   string separator = "/";
#endif
   string fileName = directory + "/" + "temp.dat";
   ofstream out (fileName);
   out << data;
   out.close();
}

although that’s not 100% guaranteed to work.

The most direct equivalent to this in Java would be

public static void writeDataToFile0 (String data, String directory) 
throws IOException
{
   String fileName = directory + java.io.File.separator + "temp.dat";
   BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
   out.write(data);
   out.close();
}

The constant java.io.File.separator will contain a forward or a backward slash, whichever is appropriate to the operating system on which you are running.

This code, however, is not good Java. In general, programmers should always try to use classes that most nearly match the data that they are working with. In this case, String is way too general. The data that we are working with is not general text, but file and directory names. Java provides a class specifically for that purpose. This means that operations like “create the name of file residing inside a directory” can be handled in a quick and general manner:

public static void writeDataToFile (String data, File directory) 
throws IOException
{
   File outputFile = new File(directory, "temp.dat");
   BufferedWriter out = new BufferedWriter(new FileWriter(outputFile));
   out.write(data);
   out.close();
}

but also that you have available other operations that are specific to files and directories:

public static void writeDataToFile (String data, File directory) 
throws IOException
{
   if (directory.exists() && directory.isDirectory()) {
	  File outputFile = new File(directory, "temp.dat");
	  BufferedWriter out = new BufferedWriter(new FileWriter(outputFile));
	  out.write(data);
	  out.close();
   }
}

Now, what I have been illustrating here is the “old” Java File class, java.io.File. Version 1.7 of Java introduced the new I/O system (java.nio.file).

The new system is a bit cleaner, largely because it separates the concept of a single file from the concept of a path used to locate that file. These concepts got smashed together a bit in the older system.

2.1 What Is a Path? (And Other File System Facts)

3 Summary