Showing posts with label packages. Show all posts
Showing posts with label packages. Show all posts

Friday, May 6, 2011

Java File Save and File Load: Text

We've looked at saving and loading objects to files. If we need to exchange information for use by a different program than our own it will seldom be convenient to save objects. Text files are commonly used to do this.

Text files are even simpler to deal with than Object files, thanks to classes in the java.io package. FileWriter gives us everything we need to write from our program to a text file. All we need to do is feed it String data.

FileReader lets us access a file, but using a BufferedReader makes it a lot easier to handle reading data from a file as lines of text.

As with object files, the basic steps are:
1. Open a file.
2. Write or read data.
3. Close the file.


Here are example programs, the first writes a simple text file. After you run it, you can take a look at the file it creates (in the same directory) using your favorite text viewer. You'll see normal text written line by line.

Then run the second program. It reads in the information line by line. It takes advantage of the fact that we know the format of the data file to read what's in it back into Java objects. You can do the same thing with any file that you either know the format of, or can detect the format of. For example, reading data from CSV files saved by spreadsheets (I'll provide a specific example of this in a future article.)

As always, you can download the program files from the Begin With Java Code Archive.

TextSave.java


import java.io.*;

public class TextSave{

public static void main(String[] arg) throws Exception {
// Create some data to write.
int x=1, y=2, z=3;
String name = "Galormadron", race = "elf";
boolean hyperactive = true;

// Set up the FileWriter with our file name.
FileWriter saveFile = new FileWriter("TextSave.txt");

// Write the data to the file.
saveFile.write("\n");
saveFile.write(x + "\n");
saveFile.write(y + "\n");
saveFile.write(z + "\n");
saveFile.write(name + "\n");
saveFile.write(race + "\n");
saveFile.write(Boolean.toString(hyperactive) + "\n");
saveFile.write("\n");

// All done, close the FileWriter.
saveFile.close();

} //main()
} // TextSave


TextRead.java


import java.io.*;

public class TextRead{

public static void main(String[] arg) throws Exception {
int x, y, z;
String name = "", race = "";
boolean hyperactive;

BufferedReader saveFile=
new BufferedReader(new FileReader("TextSave.txt"));

// Throw away the blank line at the top.
saveFile.readLine();
// Get the integer value from the String.
x = Integer.parseInt(saveFile.readLine());
y = Integer.parseInt(saveFile.readLine());
z = Integer.parseInt(saveFile.readLine());
name = saveFile.readLine();
race = saveFile.readLine();
hyperactive = Boolean.parseBoolean(saveFile.readLine());
// Not needed, but read blank line at the bottom.
saveFile.readLine();

saveFile.close();

// Print out the values.
System.out.println("x=" + x + " y=" + y + " z=" + z + "\n");
System.out.println("name: " + name + " race: " + race + "\n");
if (hyperactive)
System.out.println("Oh, yeah. He's hyperactive all right.");
else System.out.println("What a mellow dude.");
System.out.println();

} //main()
} // TextRead
StumbleUpon

Tuesday, January 25, 2011

Java's File Names and Class Names

Java is picky about the file names you use.

Each source file can contain one public class. The source file's name has to be the name of that class. By convention, the source file uses a .java filename extension (a tail end of a file name that marks the file as being of a particular type of file.)

So, for a class declared as such:

public class HelloWorld{
...

The file it is stored in should be named HelloWorld.java.

The capitalization should be the same in both cases. Some operating systems don't notice whether file names are capitalized or not. It doesn't matter, you should be in the habit of using the correct capitalization in case you work on a system that does care about capitalization.

When you compile your file with javac, you pass the full file name to javac:

javac HelloWorld.java

Let's say we save the file under a different name. We write the following program:

public class HelloThere{
public static void main(String arg[]){
System.out.println("Hello There.");
}
}

Then we save it as HelloWorld.java, and try to compile it:

>javac HelloWorld.java
FileName.java:1: class HelloThere is public, should be declared
in a file named HelloThere.java
public class HelloThere{
^
1 error


Java lets us know that it won't compile until we rename the file appropriately (according to its rules.)

So let's rename the file. Let's call it HelloThere.javasource. Seems a bit more explicit than just .java, right? Let's run the compiler:


>javac HelloThere.javasource
error: Class names, 'HelloThere.javasource', are only accepted
if annotation processing is explicitly requested
1 error

Java's still not happy with us. Annotation processing? That's when we include extra information in the program about the program itself. We're not bothering with that just now. So we should just name the file HelloThere.java, and not get fancy with our file names.

But, under the right circumstances, javac does allow file name extensions other than .java. That's why we always type in the full file name, including .java, when we use javac. We say 'javac HelloThere.java', not just 'javac HelloThere'. Javac can't assume that we mean a .java file, though that's what it will usually be.

The Class File

Once we make javac happy with a proper file name, and a program with no errors, javac produces a new file. This file will have the original file name, but with .java replaced with .class. This is your bytecode file, the file that the Java Virtual Machine can run.

When we run the program with Java, we're running the .class file. In the case of HelloThere, we're running the HelloThere.class file. But we don't type in the full file name. Why?

Unlike javac, java requires a .class file. That's all it will work with. There's no opportunity to have a different extension to the file name. So it assumes the .class part of the file name. But that's not the whole story.

If you add .class yourself, here's what you'll get:

>java HelloThere.class
Exception in thread "main" java.lang.NoClassDefFoundError:
HelloThere/class
Caused by: java.lang.ClassNotFoundException: HelloThere.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Pretty ugly. What we're actually doing when we type "java HelloThere" is telling Java to run the class HelloThere. Java assumes that it will find this in a file called "HelloThere.class", so that's what it's looking for first.

We're not telling Java to run the file HelloThere.class, we're telling it to run the class HelloThere, which it expects to find in the file HelloThere.class.

But what if we ask for another class that doesn't have its own .class file?

Just for fun, let's change HelloThere.java like this, and see what happens:
public class HelloThere{
public static void main(String[] arg){
System.out.println("Hello.");
}
}

class HelloZoik{
public static void main(String[] arg){
System.out.println("Zoiks!");
}
}

After we edit it, we compile with 'javac HelloThere.java' and hold our breath.

Hurray! No errors!

Now we have a second class, HelloZoik, in the HelloThere.class file. Can Java find it?

Let's try:
 java HelloZoik
Zoiks!

It worked! Java found our class inside HelloThere.class.

This shows it's not the file name that we're calling with the 'java' command, it's the class name.

If Java doesn't find the class inside a file with the same name as the class followed by .class, it'll look in the other .class files available.
StumbleUpon

Thursday, July 17, 2008

Stars in import Statements

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

These are some representative import statments. Each one has an asterisk (or "star") at the end of it. What does that mean?

The asterisk is a special pattern-matching character. It matches any combination of characters (letters, numbers, or special characters.) In other words, it will match any name of any class in the package. Let's say we want to import Frame, Panel, Component, Color, Dialog, Dimension, Graphics and Image from the java.awt package for a program we're writing. We could have the following import statements:
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Component;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

Since star can take the place of any name, we can replace all of those import statements with one:
import java.awt.*;

This imports every class in java.awt. It also imports all the interfaces, exceptions, and errors defined in java.awt. It makes absolutely everything in the java.awt package available to our program.

OK, then why do we need to do this?
import java.awt.*;
import java.awt.event.*;

If the * makes us get everything in java.awt, why do we need to then go an import java.awt.event.*?

The reason is that java.awt.event is a different package than java.awt. The stuff in java.awt.event isn't actually in java.awt. With package names, the dot notation is just a way of letting us know that the stuff in java.awt.event is related to the stuff in java.awt, and that we'll probably want to use the stuff in these packages together. But java.awt.event isn't in java.awt, the way that System.out is in the class System.

Just remember, every package with its own name is a totally different package. You can tell a class name from a package name by whether it is capitalized:
import java.awt.Color;

Color is a class in the java.awt package. This is one of the reasons we follow the convention of using a capital letter at the start of a class's name. Whereas this:
import java.awt.color.*;

is an import of the classes in the java.awt.color package. These classes are not in java.awt, so you can't import them using "import java.awt.*;"

The asterisk is a "regular expression" character. It and a number of other characters are a way of building up what are called regular expressions, which are a way of matching things without using the precise name. The asterisk is a "wildcard," it can stand for any character, or any number of any characters.
StumbleUpon

Friday, June 27, 2008

import Statements

An import statement is a way of making more of the functionality of Java available to your program. Java can do a lot of things, and not every program needs to do everything. So, to cut things down to size, so to speak, Java has its classes divided into "packages." Your own classes are part of packages, too.

No import Needed

The simple Hello.java program we've used as an example so far doesn't have any import statements:

public class Hello{
public static void main(String arg[]){
System.out.println("Hello.");
}
}

Everything in the program is already available to the compiler. The compiler can access any class in the java.lang package without needing an import statement. It can also access any classes in the "local" package, which is any classes defined in files in the same directory as the program being compiled that aren't part of another package (that is, they don't have a package statement at the start of the file.)

import Required

Anything that isn't in the java.lang package or the local package needs to be imported. An example is the Scanner class. If you look up the Scanner class in the Java API Specification, you'll see that it is in the java.util package. Remember, to look it up you scroll to the class name in the lower left frame then click on it to bring up its definition in the main frame of the browser. Class names are in regular typeface, interfaces are in italics (some classes and interfaces have the same name.)

Here's an example program that uses Scanner, with an import statement:

import java.util.Scanner;

public class ScannerTest{
public static void main(String arg[]){

// scanner gets its input from the console.
Scanner scanner = new Scanner(System.in);
String name = "";

// Get the user's name.
System.out.print("Your name, adventurer? >");
name = scanner.next();
System.out.println();

// Print their name in a a message.
System.out.println("Welcome, " + name + " to Javaland!");
}
}

We imported just the class Scanner from java.util in the import statement in this program. If we'd been using multiple classes from java.util, we could have made all the classes in java.util available to us by using this import statement:

import java.util.*;

The * is a "regular expression operator" that will match any combination of characters. Therefore, this import statement will import everything in java.util. If you have tried entering and running the example program above, you can change the import statement to this one.

If we need multiple classes from different packages, we use an import statement for each package from which we need to import classes (or interfaces, or any other part of that package we need.) It's not unusual to see a series of import statements near the start of a program file:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

Now, you may wonder why we have statements importing java.awt.* and java.awt.event.*. It seems like if you import java.awt.* that ought to import everything "under" java.awt, right? And the "dot" notation sure makes it look like java.awt.event is under java.awt.

Package Names and Those Misleading Dots

The thing is, each package with its own name is an entirely separate entity. The dot notation and name similarities are just a convention for making it easier to keep track of which packages have functions that are related to each other. One package isn't inside another one. java.awt.event is an entirely separate package from java.awt, it's not inside java.awt.

This can be very confusing, since the other use of the "dot notation" is a way of getting to something that is "inside" or a member of something else. System.out.println() is a way of getting at the println() method that's a member of out which is a member of the System class. But it doesn't work that way with packages. Each package name is a whole different package, and each package needs its own import statement. java.awt.event is entirely different from java.awt.

You can see package names in the API reference in the upper left frame. If you click on a package name, the lower left frame with change to limit what it shows to just the items in the package you've clicked.
StumbleUpon

Saturday, June 21, 2008

Java's Reference Manual

Java has a peculiar name for the reference where you look up Java classes and their methods and member variables. It's called the "API Specification." If you want to know what something does, or how to use it, you look it up in the Java API Specification for the version of Java that you're using.

The online home of these Java language reference manuals is at http://download.oracle.com/javase/

Look for the link here to "API Specification."

Here are direct links for several versions of Java in current use:
Java SE 5.0 (a.k.a. Java 1.5.0): http://download.oracle.com/javase/1.5.0/docs/api/

Java SE 6: http://download.oracle.com/javase/6/docs/api/

Java SE 7: http://download.oracle.com/javase/7/docs/api/

Your Java Version
To find the version of Java that you're using, open a Terminal or Command Line window and enter the command "java -version" (without the quotes, of course.) It will print out something like this:

java version "1.5.0_13"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-241)
Java HotSpot(TM) Client VM (build 1.5.0_13-121, mixed mode, sharing)

The key item here is the information in the quotes in the first line, "1.5.0_13". For the purposes of figuring out which version of the API specification we want to be referring to, we look at the digits before the underscore. In this case, "1.5.0" is the part that's important to us. For this version of Java, we'd select the link for J2SE 1.5.0.

Another approach that's simpler is to simply go to the most recent API reference. Within the API reference, it lists what version of Java each feature appeared. You want to check that on each item before you dig into reading about what cool things it can do--it's terrible to spend a bunch of time reading about a class and methods that solve your programming problem only to have your compiler reject it because you're using a version that doesn't have that feature yet!

You also want to make sure that your compiler version matches your JVM version. "java -version" gives you the version of your JVM (Java Virtual Machine) a.k.a. Java Runtime Environment (they're not exactly the same thing, but close enough for this discussion and the terms JVM and JRE tend to get used interchangeably.)

To get your compiler version, enter the command "javac -version" at the Command Line or command prompt of your Terminal window. Some versions may want you to enter "javac --version" instead of "javac -version", so if you get a big long error message instead of a version message, try using two dashes (or read the usage message and see what it says, it may want "javac -v" or something.)

If your compiler version is newer than your JVM version, you'll want to follow the instructions for your system to point it to the newer JVM as a default so that you are interpreting your programs with the same version of Java that you are compiling it with. Your Java compiler may be compiling code that your JVM can't run, otherwise! The Java Development Kit (JDK), which contains the compiler, also has a JRE bundled with it that matches the version of the compiler. So you shouldn't have to download any updates to get a JRE that matches your compiler, you just have to let your system know which version of the JRE you want it to run.

How this is done varies between different operating systems, so consult the online information on how to do this for your OS or distro.

If your JRE is a newer version than your compiler, you'll probably want to update your compiler so that you can take advantage of all the features of your JVM. Once again, this is a system-specific process.

Looking Things Up in the Java API Specification

Once you're at the correct API specification (say language reference manual or library reference in your mind) you can find a list of classes on the lower left hand side (in the frames view.) Chances are you don't know what package the classes are in that you want to look up, at least at first, so scanning through the long alphabetic list of class names is usually the place to start. There are also names in italic, these are names of interfaces.

Let's say we want to look up System.out.println() which has appeared in many of our examples here. The class name is System, so we click on System in the lower left hand frame. This makes the documentation page for System appear on the right side frame.

Above the words "Class System" you'll see the name of the package that System is part of, java.lang. Click on java.lang in the upper left hand frame and you'll see that it updates the lower left frame to show a much shorter list, a list of the interfaces, classes, enums, and errors that are part of the java.lang package. It's worthwhile to remember the package your commonly used classes are part of, for this and other reasons.

We wanted to look up System.out.println(). Back on the main frame on the right side of the window we can scroll down a little to see the Field Summary, where out is listed. This field, or member variable, is System.out. Click on out.

out is a PrintStream object, which means that it has all the methods of the PrintStream class, among other things. Below its verbose description is a set of links to PrintStream methods, including PrintStream.println(). Click on this link now.

This takes you to a list of different versions of the println() method, which do different things depending on what sort of data is inside the parentheses. In the examples we've been using so far, we've been using "System.out.println("Hello")" so we've been putting String data inside the parens ("Hello").

If we scroll down a bit we see println(String x), which tells us what the expected behavior is for a call of println() with a string inside the parens.

Try looking up some other classes and methods. For example, take a look at what the Scanner class can do.
StumbleUpon