Inf1 OP : Lab Sheet Week 5 Q5 - Path Names
Overview

In this exercise we will experiment with some of the methods of the String class. We will write a program that examines a *nix-style pathname, and breaks it into its components.

Note

*nix refers to the various Unix-like operating systems, for example, UNIX itself, Linux, Mac OS, and the BSD family. Many of the techniques and tools you have learned for using Linux also apply to these other operating systems.

Directories and files on *nix style filesystem are structured as a tree. An example is shown below.

images/FileSystem.png

In this example, there are a total of four files in six directories. The full pathnames of the files are:

/home/bill/work/flowerpotlist.xls
/home/bill/work/weedfertilisers.pdf
/home/ben/todo.txt
/programs/MyClass.java

and the directories are:

/
/home/
/home/bill/
/home/bill/work
/home/ben/
/programs/

If we remove the directory portion from the pathnames, we are left with the files’ basenames, such as flowerpotlist.xls.

All the pathnames have a suffix consisting of a period followed by some further characters. These suffixes are called file extensions. The file extensions in this example are:

.xls
.pdf
.txt
.java

Note

In contrast to Windows, *nix systems use the slash symbol '/' to separate directories. There is also no notion of drives; everything exists in the tree under /.

Basename & File Type

Write a class SplitPathName containing a static method splitPath() that splits a pathname into components. The method has the following signature:

public static String[] splitPath(String s)

splitPath() should return an array of four Strings.

  • The first element of the array should be the directory path that the file is in (including the trailing slash).
  • The second element should be the basename including extension, if any.
  • The third element should be the basename without the extension.
  • The fourth element should be the file extension, if any.

For example:

String[] components = splitPath("/home/bill/work/weedfertilisers.pdf");
//components[0] == "/home/bill/work/"
//components[1] == "weedfertilisers.pdf"
//components[2] == "weedfertilisers"
//components[3] == ".pdf"

String[] components = splitPath("ben/todo");
//components[0] == "ben/"
//components[1] == "todo"
//components[2] == "todo"
//components[3] == ""

You will need to use the methods of the String class, in particular:

  • indexOf()
  • lastIndexOf()
  • substring()

Check the Java string API documentation to find out more about how the methods work.

Warning

If you try calling something like "abc".indexOf("d"), i.e., where the string "d" whose index you are looking for doesn’t occur in "abc", then the returned value will be -1, and similarly for lastIndexOf().

Write a main() method which reads a list of pathnames as command-line arguments, and for each one, prints out the basename, the file extension and the directory that the file is in, enclosed by square brackets. For example:

: java SplitPathName /home/ben/todo.txt /home/bill/work/flowerpotlist.xls /programs/MyClass.java
File: todo.txt Type: .txt [/home/ben/]
File: flowerpotlist.xls Type: .xls [/home/bill/work/]
File: MyClass.java Type: .java [/programs/]

The skeleton of your main() method should look something like this:

public static void main(String args[]) {

     // for each argument:
     {
         // String[] components = splitPath( argument );
         // print out the components of argument accordingly
     }

 }

An automated test has been created for this exercise: SplitPathNameTest.java.

Absolute Paths

You will have noticed in the previous question that most of the pathnames began with a forward slash, so called absolute paths. However, this is not always the easiest way of referring to a file. When we open a terminal, we can access all the files in subdirectories of our current directory by just using the path that names the relevant subdirectory. For example, if my current working directory is /home/bill, then I can use the pathname work/flowerpotlist.xls rather than the absolute path /home/bill/work/flowerpotlist.xls This is known as using a relative path. A relative path can be turned into an absolute path by prepending the current working directory.

Your current working directory can be discovered in Java by calling System.getProperty("user.dir"). For example:

String currentDir = System.getProperty("user.dir");

Create a new class AbsolutePath containing two static methods. The first of these, ensureAbsolute(), has the following signature:

public static String ensureAbsolute(String path)

This returns path unchanged if it is already an absolute path (i.e., if it starts with a slash), and if not it converts the relative pathname to an absolute one and returns that.

The second method, absoluteSplitPath(), has the following signature:

public static String[] absoluteSplitPath(String s)

This behaves just like splitPath() except that the first element, i.e., components[0], must be an absolute pathname. Rather than duplicating the code from splitPath(), you should call it from within absoluteSplitPath(). Since it lives in a different class, you have to refer to it with a so-called qualified name, that is, as SplitPathName.splitPath()

An automated test has been created for this exercise: AbsolutePathTest.java.