Assignment 08


Practice manipulating strings in the context of examining and converting a filename.

Concepts: Invoking methods, parameters, return values; String methods
Textbook: 3.2


You are going to write a program that asks for a (hypothetical) filename. It will then use String methods to print out only the name part of that filename, only the extension, and then convert the filename to a 8.3 filename.

Ask the user to enter the filename. (This is just a String; it doesn't need to correspond to a real file.) The entered String must contain at least one non-whitespace character, and you should disregard any whitespace characters on the ends of the name. (Simply using the trim() method will prevent both these problems.) A filename may not begin with a '.' character. (They can on some operating systems, but we'll pretend we're modeling Windows here.)

First, print out the whole filename (to prove you read it in and trimmed it properly).

Then print out just the name part of the filename. This is all of filename up to the last '.' character. If there is no '.' character, then it is the whole filename.

Print out the extension (if there is one). This is everything after the last '.' character.

Then, covert the filename to a 8.3 filename. (We're not actually following all the 8.3 rules here, just most of them.) Specifically:

Finally, print out each of the four outputs--full filename, name, extension, and 8.3 filename--on their own line, clearly labeled.

Extra credit: Ideally, a 8.3 filename should be stripped of any illegal characters. Since there is no easy String method to check for this sort of thing, you would need to use a loop to check that each character is acceptable. Since we have not covered loops yet in lab, this is not required.

However, for those interested in attempting this for extra credit: Replace all characters other than letters, digits, dashes ('-'), underscores ('_'), and the single/last dot ('.') with underscores. Do this only to the 8.3 filename, not to the regular name and extension output. (Hint: Check out the Character class in the API, particularly the isLetterOrDigit method.)

Sample Output

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: 

Sorry, but you did not enter a filename.

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: .hiddenfile

Sorry, but a filename may not start with a '.' character.

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert:                 file

Filename: file
Name only: file
8.3 Filename: FILE

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: My Favorite Song.mp3

Filename: My Favorite Song.mp3
Name only: My Favorite Song
Extension: mp3
8.3 Filename: MY_FAVOR.MP3

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: index.html

Filename: index.html
Name only: index
Extension: html
8.3 Filename: INDEX.HTM

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: A.txt.backup

Filename: A.txt.backup
Name only: A.txt
Extension: backup
8.3 Filename: A_TXT.BAC

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: trailing dot.

Filename: trailing dot.
Name only: trailing dot
8.3 Filename: TRAILING

D:\TA\grading\A08>java ZtomaszeA08
Enter a filename to convert: ~myfile#.lock

Filename: ~myfile#.lock
Name only: ~myfile#
Extension: lock
8.3 Filename: _MYFILE_.LOC

The last execution is an example of the extra credit replacing illegal characters. If you did not do the EC, the 8.3 filename would be ~MYFILE#.LOC.

What to Submit

Upload your file to Tamarin.

Grading [6 points]

1 - Compiles
Your program compiles successfully (no errors)
0.5 - Output formatting
Prints full filename, name part, extension, and 8.3 filename, one per line, each labelled appropriately.
0.5 - Detects errors
Reports an error if the given full filename contains no characters, contains only whitespace, or starts with a '.'.
1 - Name and extension
Correctly displays the name and extension parts of the filename.
3 - 8.3 filename
Properly shortens to 8.3 lengths, if necessary (1.5). Uppercased (0.5). Replaces spaces and extra dots with underscores (1.0).
+2 - Replaces invalid characters in the 8.3 filename
Replaces with underscores all characters except letters, digits, dashes, underscores, and a single dot.


Some of these String methods listed in the API are really confusing!
Indeed, some of them use other classes (such as CharSequence) and complicated features (such as regular expressions) that we won't even cover in this class. But you don't need to use all the methods; you only need to learn some of them. In particular: length, charAt, indexOf, lastIndexOf, substring, trim, replace, toUpperCase, toLowercase. And you won't even need all of those to complete this particular assignment. If you do find some other String methods you'd like to use that are not in this list, though, feel free to do so (except isEmpty()).
Warning: Don't use String's isEmpty() method.
Tamarin is currently running Java 1.5; most of you are probably running Java 1.6. (If you want to check your version, type java -version on the command line.) There is one String method that some students find--isEmpty()--that was added in Java 1.6. If you use this method, your code will probably compile on your machine, but it won't compile when you upload it to Tamarin.

Therefore, I'm asking that you don't use this method in your code. Two alternatives to str.isEmpty() are str.length() == 0 and str.equals("")

How do get the name and extension parts of the filename?
You need to split the filename on the last '.' character. So this will require use of either the indexOf or the lastIndexOf method. (Which one do you think you should use? What will it return if it can't find a '.' at all? What should you do if that happens?) Once you have the location of the last (or only) dot, you can use the substring method to split the string.
My program prints out my error messages but then keeps going.
You need to use an if/else or some similar structure so that either your program prints an error message or it keeps going. There are two reasons to stop with an error message: the user didn't enter a string at all or they entered one starting with a '.' character. You can't check the latter before you check the former. That is, if you try to look at the first character but the String is empty, your program is going to crash. So check the length of the string first. Here's just one way you could do this:
  //read in filename
  filename = filename.trim();
  //if (filename contains no characters) then:
    //print error message: user entered nothing or only whitespace
  //else if (filename starts with a '.' character) then:
    //print error message: filename can't start with a dot
    //the filename is valid, so start processing it.
    //The rest of your code goes here....
My program crashes if there is no dot in the filename.
You probably get something like this:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String
index out of range: -1
        at java.lang.String.substring(Unknown Source)
        at ZtomaszeA08.main(
Note how the error is complaining that you're trying to access index -1 of a String. -1 is never a valid index. Specifically, from this error message, we can see the problem comes from line 36 of my code when I make a call to substring.

This error usually happens when you forget to check whether an index you got is really valid. You need something like this:

  int lastDot = filename.lastIndexOf('.');
  if (lastDot < 0) {
    //no dot was found
    //so this means there is no extension
    //and the name part goes to the end of the string
  }else {
    //everything's fine
    //grab the name and extension using lastDot and substring
My program crashes if the name (or extension) is too short.
Then you probably need to check the length of the name before you try manipulating it. Use the length method.
So, wait: for the extra credit, we leave all the dots in place?
No. You are to replace everything except the list of characters given. Assuming you did the regular part of the assignment correctly, you already replaced all but one of the dots with underscores (if there are any dots at all). This single remaining dot is a legal character, so leave it there.
I'm having trouble using the replaceAll and/or replaceFirst methods.
These methods actually use regular expressions, which is a sort of pattern-matching language. In a regular expression, the '.' matches any character, so you'll probably run into difficulties trying to use these methods.

Instead, just use the replace method. This will replace all matches found in a String. You can replace either one char with another; or you can replace one String (the API calls this a CharSequence, but a String is such a thing) with another.