Showing posts with label J2SE Tips. Show all posts
Showing posts with label J2SE Tips. Show all posts

Saturday, March 15, 2008

How to write a Java Application without a main method

You can write a runnable Java program which does not have main method at all. This can be done using the static block of the class.

The reason this works is that static initialization blocks get executed as soon as the class is loaded, even before the main method is called. During run time JVM will search for the main method after exiting from this block. If it does not find the main method, it throws an exception. To avoid the exception System.exit(0); statement is used which terminates the program at the end of the static block itself.

class MainMethodNot
{
static
{
System.out.println("This java program have run without the run method");
System.exit(0);

}
}

Sunday, March 09, 2008

How to use System class to copy Array

arrayCopy() method of System class copy data from one array into another. The arrayCopy method requires five arguments:

     public static void arraycopy(Object source, int srcIndex,
Object dest, int destIndex, int length)

The two Object arguments indicate the source and destination array. The three integer arguments indicate the starting location in each the source and the destination array, and the number of elements to copy.

This method will copy ‘length’ number of elements of array ‘source’ starts from the location ‘srcIndex’ to the array ‘dest’ starts from ‘destIndex’.

public class ArrayCopyDemo {

public static void main(String[] args) {

char[] Src = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
'i', 'n', 'a', 't', 'e', 'd' };
char[] dst = new char[7];
System.arraycopy(src, 2, dst, 0, 7);
System.out.println(new String(dst));

}
}

Tuesday, March 04, 2008

Capturing Audio with Java Sound API

This Tech Tip reprinted with permission by java.sun.com

The Java Sound API has been a part of the standard libraries of the Java 2 Platform since the 1.3 release. Found in the javax.sound.sampled package, the Java Sound API provides support for playing and capturing audio. In addition, the library offers a software-based audio mixer and MIDI (Musical Instrument Digital Interface) device access. In this tip, you'll learn how to capture audio through the Java Sound API and play it back.

The javax.sound.sampled package consists of eight interfaces, twelve top-level classes, twelve inner classes, and two exceptions. To record and play audio, you only need to deal with a total of seven parts of the package.

Let's examine recording first. The basic recording process is as follows:

Describe the audio format in which you want to record the data. This includes specifying the sampling rate and the number of channels (mono versus stereo) for the audio. You specify these properties using the aptly named AudioFormat class. There are two constructors for creating an AudioFormat object:

AudioFormat(AudioFormat.Encoding encoding,
float sampleRate, int sampleSizeInBits,
int channels, int frameSize, float frameRate,
boolean bigEndian)

AudioFormat(float sampleRate, int sampleSizeInBits,
int channels, boolean signed, boolean bigEndian)

The first constructor lets you explicitly set the audio format encoding, while the latter uses a default. The available encodings are ALAW, PCM_SIGNED, PCM_UNSIGNED, and ULAW. The default encoding used for the second constructor is PCM. Here is an example that uses the second constructor to create an AudioFormat object for single channel recording in 8 kHz format:

float sampleRate = 8000;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate,
sampleSizeInBits, channels, signed, bigEndian);

After you describe the audio format, you need to get a DataLine. This interface represents an audio feed from which you can capture the audio. You use a subinterface of DataLine to do the actual capturing. The subinterface is called TargetDataLine. To get the TargetDataLine, you ask the AudioSystem. However when you do that, you need to specify information about the line. You make the specification in the form of a DataLine.Info object. In particular, you need to create a DataLine.Info object that is specific to the DataLine type and audio format. Here are some lines of source that get the TargetDataLine.

DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);

If the TargetDataLine is unavailable, a LineUnavailableException is thrown.

At this point you have your input source. You can think of the TargetDataLine like an input stream. However, it requires some setup before you can read form it. Setup in this case means first opening the line using the open() method, and then initializing the line using the start() method:

line.open(format);
line.start();

Your data line is ready, so you can start recording from it as shown in the following lines of code. Here you save a captured audio stream to a byte array for later playing. You could also save the audio stream to a file. Notice that you have to manage when to stop outside the read-loop construct.

int bufferSize = (int)format.getSampleRate() *
format.getFrameSize();
byte buffer[] = new byte[bufferSize];
out = new ByteArrayOutputStream();
while (externalTrigger) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();

Now let's examine playing audio. There are two key differences in playing audio as compared to recording audio. First, when you play audio, the bytes come from an AudioInputStream instead of a TargetDataLine. Second, you write to a SourceDataLine instead of into a ByteArrayOutputStream. Besides that, the process is the same.

To get the AudioInputStream, you need to convert the ByteArrayOutputStream into the source of the AudioInputStream. The AudioInputStream constructor requires the bytes from the output stream, the audio format encoding used, and the number of sample frames:

byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
AudioInputStream ais = new AudioInputStream(input,
format, audio.length / format.getFrameSize());

Getting the DataLine is similar to the way you get it for audio recording, but for playing audio, you need to fetch a SourceDataLine instead of a TargetDataLine:

DataLine.Info info = new DataLine.Info(
SourceDataLine.class, format);
SourceDataLine line =
(SourceDataLine)AudioSystem.getLine(info);

Setup for the line is identical to the setup for audio recording:

line.open(format);
line.start();

The last step is to play the audio as shown below. Notice that this step is similar to the last step in recording. However, here you read from the buffer and write to the data line. There is also an added drain operation that works like a flush on an output stream.

int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

int count;
while ((count =
ais.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();

The following program puts these steps together to demonstrate using the Java Sound the API to record and play audio. The program also presents a GUI. Press the Capture button to start recording the audio, the Stop button to stop recording, and the Play button to play back the audio.

Note: Depending on the audio support your platform provides, you might need to change the format returned by the getFormat method in the program. If you don't know what format is supported by your platform, download the demo program from the Java Sound Demo page, and run it. Click on the CapturePlayback tab, and find a set of format settings that work for you. You can load an audio file from the audio subdirectory, and then try various settings on the left until something works. Use those settings in the creation of the AudioFormat returned by getFormat().

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;

public class Capture extends JFrame {

protected boolean running;
ByteArrayOutputStream out;

public Capture() {
super("Capture Sound Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container content = getContentPane();

final JButton capture = new JButton("Capture");
final JButton stop = new JButton("Stop");
final JButton play = new JButton("Play");

capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(false);

ActionListener captureListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(false);
stop.setEnabled(true);
play.setEnabled(false);
captureAudio();
}
};
capture.addActionListener(captureListener);
content.add(capture, BorderLayout.NORTH);

ActionListener stopListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
capture.setEnabled(true);
stop.setEnabled(false);
play.setEnabled(true);
running = false;
}
};
stop.addActionListener(stopListener);
content.add(stop, BorderLayout.CENTER);

ActionListener playListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
playAudio();
}
};
play.addActionListener(playListener);
content.add(play, BorderLayout.SOUTH);
}

private void captureAudio() {
try {
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int)format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

public void run() {
out = new ByteArrayOutputStream();
running = true;
try {
while (running) {
int count =
line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-1);
}
}
};
Thread captureThread = new Thread(runner);
captureThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}

private void playAudio() {
try {
byte audio[] = out.toByteArray();
InputStream input =
new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
DataLine.Info info = new DataLine.Info(
SourceDataLine.class, format);
final SourceDataLine line = (SourceDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();

Runnable runner = new Runnable() {
int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];

public void run() {
try {
int count;
while ((count = ais.read(
buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-3);
}
}
};
Thread playThread = new Thread(runner);
playThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-4);
}
}

private AudioFormat getFormat() {
float sampleRate = 8000;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
return new AudioFormat(sampleRate,
sampleSizeInBits, channels, signed, bigEndian);
}

public static void main(String args[]) {
JFrame frame = new Capture();
frame.pack();
frame.show();
}
}

You can find a more complete example of using the Java Sound API at the Java Sound Demo page. That example also shows an oscilloscope of the sound wave as it is playing back.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.

Wednesday, January 30, 2008

Dialog Modality

his Tech Tip reprinted with permission by java.sun.com

Top-level popup windows in "Java-speak" are called dialog boxes (or simply "dialogs"). They are typically used to interact with a user -- either to display a message or to accept user input. Before Java SE 6, dialog boxes were modeless by default, with an option to be modal. When a dialog box is modal, other windows in the application are blocked from accepting input, unless they have the dialog box as their owner. After a user reacts accordingly to a dialog box, that is, by entering input or just closing the dialog, the other windows of the application become accessible again.

Java SE 6 gives you more options regarding dialog modality. No longer are you limited in scope to one level of modality: on or off. Now you have four distinct settings defined by the new Dialog.ModalityType enumeration:

  • MODELESS
  • APPLICATION_MODAL
  • DOCUMENT_MODAL
  • TOOLKIT_MODAL

First let's look at MODELESS and APPLICATION_MODAL. A MODELESS setting means a modeless dialog box. As before, a modeless dialog box does not block input to any other window of the application. Another modal dialog box could block input to it, but a modeless one has no effect on another. If you call the setModal() method of the Dialog class with a value of false, it sets the Dialog.ModalityType to MODELESS.

The APPLICATION_MODAL setting means a modal dialog box. As before, all windows of the application that do not have the modal dialog box in their owner hierarchy are blocked from getting focus. This means that new windows can be created from the modal dialog and will accept input. However, new windows created from other pre-existing windows cannot. If you call the setModal() method of Dialog with a value of true, it sets the modality of the Dialog to DEFAULT_MODALITY_TYPE, which equates to APPLICATION_MODAL. This keeps legacy code valid, though new code should use the new setModalityType() method.

At this point you might ask what if you don't explicitly specify a modality? The answer is that the initial modality is modeless. Also, if you specify a boolean modality, it produces the same settings as calling setModal() with that boolean value. The last option is explicitly setting the modality, which has the obvious effect.

DOCUMENT_MODAL and TOOLKIT_MODAL are where things get interesting. DOCUMENT_MODAL allows you to have different sets of windows that are modal. For instance, you can have a modal application window that displays a help window. Provided that it has a top-level window that is not part of the main application hierarchy, the help window can be modal. In addition, the help window can create other modal windows that have a modality separate from the main window and separate from any modal dialogs that the help window creates. Having a modal application that displays a modal help window is a common need when utilizing the JavaHelp library. It's typical that users want to be able to interact with help, even when the current window is modal. This need wasn't adequately met prior to support for DOCUMENT_MODAL because the main application window and help window had different owner hierarchies.

Think of TOOLKIT_MODAL as APPLICATION_MODAL, where the application is the browser. (In this paragraph what's said about applets also applies to applications started through Java WebStart technology.) This setting allows one applet in a browser to be modal, blocking other applets from accepting input. That's because all the applets are loaded with the same Toolkit. Your applet must have AWTPermission.toolkitModality enabled for TOOLKIT_MODAL to work.

In addition to setting the modality type of a window, you can set the modal exclusion type by calling the setModalExclusionType() method of Window. This allows you to exclude certain windows from behaving according to the pertinent modality type. The setModalExclusionType() method accepts one of three values from the Dialog.ModalExclusionType enumeration:

  • NO_EXCLUDE
  • APPLICATION_EXCLUDE
  • TOOLKIT_EXCLUDE

The NO_EXCLUDE option means no modal exclusion. The window behaves according to its current modality type. The other two settings allow you to use a modality type, but also allow specific windows to accept input focus. The APPLICATION_EXCLUDE setting specifies that at the application level, the window will not behave according to its modality. TOOLKIT_EXCLUDE specifies that at both the application and Toolkit level, the window will not behave according to its modality. There is no way to have a window exclude behavior at the Toolkit level, but not at the application level.

Before using either the modality types or the exclusion option, you can ask the Toolkit if either is supported. To discover if a particular modality is supported, use the boolean isModalityTypeSupported(Dialog.ModalityType modalityType) method. To discover if an exclusion type is supported, use the boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType modalExclusionType) method.

Here's a program, DualModal, that displays two frames that use the DOCUMENT_MODAL setting. Each frame has a button that creates a document modal option pane, accepting input. The label of the selected button changes to the text that was entered when the option pane closes.

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

public class DualModal {
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
JFrame frame1 = new JFrame("Left");
JFrame frame2 = new JFrame("Right");
frame1.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame2.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JButton button1 = new JButton("Left");
JButton button2 = new JButton("Right");
frame1.add(button1, BorderLayout.CENTER);
frame2.add(button2, BorderLayout.CENTER);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton source = (JButton)e.getSource();
String text = getNewText(source);
if (!JOptionPane.UNINITIALIZED_VALUE.equals(text)
&& text.trim().length() > 0) {
source.setText(text);
}
}
};
button1.addActionListener(listener);
button2.addActionListener(listener);
frame1.setBounds(100, 100, 200, 200);
frame1.setVisible(true);
frame2.setBounds(400, 100, 200, 200);
frame2.setVisible(true);
}
};
EventQueue.invokeLater(runner);
}
private static String getNewText(Component parent) {
JOptionPane pane = new JOptionPane(
"New label", JOptionPane.QUESTION_MESSAGE
);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parent, "Enter Text");
// Uncomment line and comment out next
// to see application modal
// dialog.setModalityType(
// Dialog.ModalityType.APPLICATION_MODAL);
dialog.setModalityType(
Dialog.ModalityType.DOCUMENT_MODAL);
dialog.setVisible(true);
return (String)pane.getInputValue();
}
}

Notice how you can interact with the top-level dialog, but not the frame under either of them when the dialog is shown.

Here is what the initial pair of frames look like:


Image

And here are the two frames with their respective option panes:


Image

You might think that changing the setModalityType() line to use APPLICATION_MODAL would allow you to interact with both option frames simultaneously. It won't. You need to finish using one option frame before you can bring up the other.

Two points worth mentioning here. Changing the modality of an already displayed window has no effect. You must hide the dialog box and make it visible again for the new modality setting to take effect.

Also, prior to Java SE 6, any AWT Window or subclass could use the setAlwaysOnTop() method of Window to request that it is always displayed on top. This is not the same as modal and does not prevent other windows from getting input focus.

For more information on dialog modality, see the article The New Modality API in Mustang.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.

Monday, January 28, 2008

How to use List interface

List interface is an extension of Collection interface. List interface indicates the behavior of the collection of objects. It allows duplicate objects and one or more elements to be null.

Useful methods of the List Interface:

Method

Usage

add()

Adds an objects to the collection

clear()

Removes all objects from the collection.

contains()

Returns true if a special object is an element with in the collection.

get()

Returns the element at the specified index position in this collection.

isEmpty()

Returns true if the collection has no elements.

listIterator()

Returns a ListItertor object for the collection which may then be used to retrieve an object.

Remove()

Removes the element at the specified index position in this collection.

size()

Returns the number of elements in the collection.

In this code ListIterator is used for reading the objects of the list. It allows reading objects from the collection in both the forward and backward directions.

import java.util.*;

public class DemoList {

public static void main(String[] args) {

List ls = new LinkedList();

for(int i=1; i<=5; i++){
ls.add(new StringBuffer("Object " + i));
}

//display how many objects are in the collection
System.out.println("The collection has " + ls.size() + "objects");

//Instantiate a ListIterator
ListIterator li = ls.listIterator();
System.out.println("Forward Reading");

//Forward direction
while(li.hasNext()){
System.out.println(" " + li.next());
}

System.out.println("Backward Reading");

//backword direction
while(li.hasPrevious()){
System.out.println(" " + li.previous());
}
}

}

Output Screen:

The collection has 5objects
Forward Reading
Object 1
Object 2
Object 3
Object 4
Object 5
Backward Reading
Object 5
Object 4
Object 3
Object 2
Object 1

Tuesday, January 22, 2008

How to copy a directory from one location to another location

This Java tip demonstrates a method of copying a directory from one location to another. Copying is done from sourcedirectory to targetdirectory.


// If targetLocation does not exist, it will be created.
public void copyDirectory(File sourceLocation , File targetLocation)
throws IOException {

if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}

String[] children = sourceLocation.list();
for (int i=0; i) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {

InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);

// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}