为什么在这种情况下会引发 ClassLoader 异常?
我成功编译了三个文件,当我尝试启动一个包含 public static void main
的类时,我收到了错误。这是错误:
C:\Documents and Settings\Ambre-28\Mes documents\JavaMESDKProjects\exempleRXTX\src\net\net>java Example
Exception in thread "main" java.lang.NoClassDefFoundError: Example (wrong name:
net/Example)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: Example. Program will exit.
这是代码:
package net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
/**
* This is a very simple example showing the most basic use of
* {@link net.Network} and {@link net.Network_iface}. Feel free to use,
* overwrite, or just ignore code as you like.
*
* As a default, a connection speed of 115200 baud is assumed. You can use a
* different speed by giving it as an <b>int</b> as the first command line
* argument or changing the default speed in the source code.
*
* @author Raphael Blatter ([email protected])
*/
public class Example implements net.Network_iface {
// set the speed of the serial port
public static int speed = 115200;
private static net.Network network;
private static boolean resend_active = false;
public static void main(String[] args) {
network = new net.Network(0, new net.Example(), 255);
// reading the speed if
if (args.length > 0) {
try {
speed = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("the speed must be an integer\n");
System.exit(1);
}
}
// initializing reader from command line
int i, inp_num = 0;
String input;
BufferedReader in_stream = new BufferedReader(new InputStreamReader(
System.in));
// getting a list of the available serial ports
Vector<String> ports = network.getPortList();
// choosing the port to connect to
System.out.println();
if (ports.size() > 0) {
System.out.println("the following serial ports have been detected:");
}
else {
System.out.println("sorry, no serial ports were found on your computer\n");
System.exit(0);
}
for (i = 0; i < ports.size(); ++i) {
System.out.println(" " + Integer.toString(i + 1) + ": " + ports.elementAt(i));
}
boolean valid_answer = false;
while (!valid_answer) {
System.out.println("enter the id (1,2,...) of the connection to connect to: ");
try {
input = in_stream.readLine();
inp_num = Integer.parseInt(input);
if ((inp_num < 1) || (inp_num >= ports.size() + 1))
System.out.println("your input is not valid");
else
valid_answer = true;
} catch (NumberFormatException ex) {
System.out.println("please enter a correct number");
} catch (IOException e) {
System.out.println("there was an input error\n");
System.exit(1);
}
}
// connecting to the selected port
if (network.connect(ports.elementAt(inp_num - 1), speed)) {
System.out.println();
} else {
System.out.println("sorry, there was an error connecting\n");
System.exit(1);
}
// asking whether user wants to mirror traffic
System.out.println("do you want this tool to send back all the received messages?");
valid_answer = false;
while (!valid_answer) {
System.out.println("'y' for yes or 'n' for no: ");
try {
input = in_stream.readLine();
if (input.equals("y")) {
resend_active = true;
valid_answer = true;
} else if (input.equals("n")) {
valid_answer = true;
} else if (input.equals("q")) {
System.out.println("example terminated\n");
System.exit(0);
}
} catch (IOException e) {
System.out.println("there was an input error\n");
System.exit(1);
}
}
// reading in numbers (bytes) to be sent over the serial port
System.out.println("type 'q' to end the example");
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
System.out.println("\nenter a number between 0 and 254 to be sent ('q' to exit): ");
try {
input = in_stream.readLine();
if (input.equals("q")) {
System.out.println("example terminated\n");
network.disconnect();
System.exit(0);
}
inp_num = Integer.parseInt(input);
if ((inp_num > 255) || (inp_num < 0)) {
System.out.println("the number you entered is not valid");
} else {
int temp[] = { inp_num };
network.writeSerial(1, temp); // ecriture dans le port série
System.out.println("sent " + inp_num + " over the serial port");
}
} catch (NumberFormatException ex) {
System.out.println("please enter a correct number");
} catch (IOException e) {
System.out.println("there was an input error");
}
}
}
/**
* Implementing {@link net.Network_iface#networkDisconnected(int)}, which is
* called when the connection has been closed. In this example, the program
* is ended.
*
* @see net.Network_iface
*/
public void networkDisconnected(int id) {
System.exit(0);
}
/**
* Implementing {@link net.Network_iface#parseInput(int, int, int[])} to
* handle messages received over the serial port. In this example, the
* received bytes are written to command line (0 to 254) and the message is
* sent back over the same serial port.
*
* @see net.Network_iface
*/
public void parseInput(int id, int numBytes, int[] message) {
if (resend_active) {
network.writeSerial(numBytes, message);
System.out.print("received and sent back the following message: ");
} else {
System.out.print("received the following message: ");
}
System.out.print(message[0]);
for (int i = 1; i < numBytes; ++i) {
System.out.print(", ");
System.out.print(message[i]);
}
System.out.println();
}
/**
* Implementing {@link net.Network_iface#writeLog(int, String)}, which is
* used to write information concerning the connection. In this example, all
* the information is simply written out to command line.
*
* @see net.Network_iface
*/
public void writeLog(int id, String text) {
System.out.println(" log: |" + text + "|");
}
}
package net;
import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
/**
* Used to simplify communication over a Serial port. Using the RXTX-library
* (rxtx.qbang.org), one connection per instance of this class can be handled.
* In addition to handling a connection, information about the available Serial
* ports can be received using this class.
*
* A separate {@link Thread} is started to handle messages that are being
* received over the Serial interface.
*
* This class also makes packages out of a stream of bytes received, using a
* {@link #divider}, and sending these packages as an array of <b>int</b>s (each
* between 0 and 255) to a function implemented by a class implementing the
* {@link net.Network_iface}-interface.
*
* @author Raphael Blatter ([email protected])
* @author heavily using code examples from the RXTX-website (rxtx.qbang.org)
*/
public class Network {
private InputStream inputStream;
private OutputStream outputStream;
/**
* The status of the connection.
*/
private boolean connected = false;
/**
* The Thread used to receive the data from the Serial interface.
*/
private Thread reader;
private SerialPort serialPort;
/**
* Communicating between threads, showing the {@link #reader} when the
* connection has been closed, so it can {@link Thread#join()}.
*/
private boolean end = false;
/**
* Link to the instance of the class implementing {@link net.Network_iface}.
*/
private Network_iface contact;
/**
* A small <b>int</b> representing the number to be used to distinguish
* between two consecutive packages. It can only take a value between 0 and
* 255. Note that data is only sent to
* {@link net.Network_iface#parseInput(int, int, int[])} once the following
* 'divider' could be identified.
*
* As a default, <b>255</b> is used as a divider (unless specified otherwise
* in the constructor).
*
* @see net.Network#Network(int, Network_iface, int)
*/
private int divider;
/**
* <b>int</b> identifying the specific instance of the Network-class. While
* having only a single instance, 'id' is irrelevant. However, having more
* than one open connection (using more than one instance of {@link Network}
* ), 'id' helps identifying which Serial connection a message or a log
* entry came from.
*/
private int id;
private int[] tempBytes;
int numTempBytes = 0, numTotBytes = 0;
/**
* @param id
* <b>int</b> identifying the specific instance of the
* Network-class. While having only a single instance,
* {@link #id} is irrelevant. However, having more than one open
* connection (using more than one instance of Network),
* {@link #id} helps identifying which Serial connection a
* message or a log entry came from.
*
* @param contact
* Link to the instance of the class implementing
* {@link net.Network_iface}.
*
* @param divider
* A small <b>int</b> representing the number to be used to
* distinguish between two consecutive packages. It can take a
* value between 0 and 255. Note that data is only sent to
* {@link net.Network_iface#parseInput(int, int, int[])} once the
* following {@link #divider} could be identified.
*/
public Network(int id, Network_iface contact, int divider) {
this.contact = contact;
this.divider = divider;
if (this.divider > 255)
this.divider = 255;
if (this.divider < 0)
this.divider = 0;
this.id = id;
tempBytes = new int[1024];
}
/**
* Just as {@link #Network(int, Network_iface, int)}, but with a default
* {@link #divider} of <b>255</b>.
*
* @see #Network(int, Network_iface, int)
*/
public Network(int id, Network_iface contact) {
this(id, contact, 255);
}
/**
* Just as {@link #Network(int, Network_iface, int)}, but with a default
* {@link #divider} of <b>255</b> and a default {@link #id} of 0. This
* constructor may mainly be used if only one Serial connection is needed at
* any time.
*
* @see #Network(int, Network_iface, int)
*/
public Network(Network_iface contact) {
this(0, contact);
}
/**
* This method is used to get a list of all the available Serial ports
* (note: only Serial ports are considered). Any one of the elements
* contained in the returned {@link Vector} can be used as a parameter in
* {@link #connect(String)} or {@link #connect(String, int)} to open a
* Serial connection.
*
* @return A {@link Vector} containing {@link String}s showing all available
* Serial ports.
*/
@SuppressWarnings("unchecked")
public Vector<String> getPortList() {
Enumeration<CommPortIdentifier> portList;
Vector<String> portVect = new Vector<String>();
portList = CommPortIdentifier.getPortIdentifiers();
CommPortIdentifier portId;
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
portVect.add(portId.getName());
}
}
contact.writeLog(id, "found the following ports:");
for (int i = 0; i < portVect.size(); i++) {
contact.writeLog(id, (" " + (String) portVect.elementAt(i)));
}
return portVect;
}
/**
* Just as {@link #connect(String, int)}, but using 115200 bps as a default
* speed of the connection.
*
* @param portName
* The name of the port the connection should be opened to (see
* {@link #getPortList()}).
* @return <b>true</b> if the connection has been opened successfully,
* <b>false</b> otherwise.
* @see #connect(String, int)
*/
public boolean connect(String portName) {
return connect(portName, 115200);
}
/**
* Opening a connection to the specified Serial port, using the specified
* speed. After opening the port, messages can be sent using
* {@link #writeSerial(String)} and received data will be packed into
* packets (see {@link #divider}) and forwarded using
* {@link net.Network_iface#parseInput(int, int, int[])}.
*
* @param portName
* The name of the port the connection should be opened to (see
* {@link #getPortList()}).
* @param speed
* The desired speed of the connection in bps.
* @return <b>true</b> if the connection has been opened successfully,
* <b>false</b> otherwise.
*/
public boolean connect(String portName, int speed) {
CommPortIdentifier portIdentifier;
boolean conn = false;
try {
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
contact.writeLog(id, "Error: Port is currently in use");
} else {
serialPort = (SerialPort) portIdentifier.open("RTBug_network",
2000);
serialPort.setSerialPortParams(speed, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
reader = (new Thread(new SerialReader(inputStream)));
end = false;
reader.start();
connected = true;
contact.writeLog(id, "connection on " + portName
+ " established");
conn = true;
}
} catch (NoSuchPortException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (PortInUseException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (UnsupportedCommOperationException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (IOException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
}
return conn;
}
/**
* A separate class to use as the {@link net.Network#reader}. It is run as a
* separate {@link Thread} and manages the incoming data, packaging them
* using {@link net.Network#divider} into arrays of <b>int</b>s and
* forwarding them using
* {@link net.Network_iface#parseInput(int, int, int[])}.
*
*/
private class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[1024];
int len = -1, i, temp;
try {
while (!end) {
if ((in.available()) > 0) {
if ((len = this.in.read(buffer)) > -1) {
for (i = 0; i < len; i++) {
temp = buffer[i];
// adjust from C-Byte to Java-Byte
if (temp < 0)
temp += 256;
if (temp == divider) {
if (numTempBytes > 0) {
contact.parseInput(id, numTempBytes,
tempBytes);
}
numTempBytes = 0;
} else {
tempBytes[numTempBytes] = temp;
++numTempBytes;
}
}
}
}
}
} catch (IOException e) {
end = true;
try {
outputStream.close();
inputStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
serialPort.close();
connected = false;
contact.networkDisconnected(id);
contact.writeLog(id, "connection has been interrupted");
}
}
}
/**
* Simple function closing the connection held by this instance of
* {@link net.Network}. It also ends the Thread {@link net.Network#reader}.
*
* @return <b>true</b> if the connection could be closed, <b>false</b>
* otherwise.
*/
public boolean disconnect() {
boolean disconn = true;
end = true;
try {
reader.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
disconn = false;
}
try {
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
disconn = false;
}
serialPort.close();
connected = false;
contact.networkDisconnected(id);
contact.writeLog(id, "connection disconnected");
return disconn;
}
/**
* @return Whether this instance of {@link net.Network} has currently an
* open connection of not.
*/
public boolean isConnected() {
return connected;
}
/**
* This method is included as a legacy. Depending on the other side of the
* Serial port, it might be easier to send using a String. Note: this method
* does not add the {@link #divider} to the end.
*
* If a connection is open, a {@link String} can be sent over the Serial
* port using this function. If no connection is available, <b>false</b> is
* returned and a message is sent using
* {@link net.Network_iface#writeLog(int, String)}.
*
* @param message
* The {@link String} to be sent over the Serial connection.
* @return <b>true</b> if the message could be sent, <b>false</b> otherwise.
*/
public boolean writeSerial(String message) {
boolean success = false;
if (isConnected()) {
try {
outputStream.write(message.getBytes());
success = true;
} catch (IOException e) {
disconnect();
}
} else {
contact.writeLog(id, "No port is connected.");
}
return success;
}
/**
* If a connection is open, an <b>int</b> between 0 and 255 (except the
* {@link net.Network#divider}) can be sent over the Serial port using this
* function. The message will be finished by sending the
* {@link net.Network#divider}. If no connection is available, <b>false</b>
* is returned and a message is sent using
* {@link net.Network_iface#writeLog(int, String)}.
*
* @param numBytes
* The number of bytes to send over the Serial port.
* @param message
* [] The array of<b>int</b>s to be sent over the Serial
* connection (between 0 and 256).
* @return <b>true</b> if the message could be sent, <b>false</b> otherwise
* or if one of the numbers is equal to the #{@link Network#divider}
* .
*/
public boolean writeSerial(int numBytes, int message[]) {
boolean success = true;
int i;
for (i = 0; i < numBytes; ++i) {
if (message[i] == divider) {
success = false;
break;
}
}
if (success && isConnected()) {
try {
for (i = 0; i < numBytes; ++i) {
outputStream.write(changeToByte(message[i]));
}
outputStream.write(changeToByte(divider));
} catch (IOException e) {
success = false;
disconnect();
}
} else if (!success) {
// message contains the divider
contact.writeLog(id, "The message contains the divider.");
} else {
contact.writeLog(id, "No port is connected.");
}
return success;
}
private byte changeToByte(int num) {
byte number;
int temp;
temp = num;
if (temp > 255)
temp = 255;
if (temp < 0)
temp = 0;
number = (byte) temp;
return number;
}
}
package net;
/**
* An instance of a class implementing this interface has to be passed to the
* constructor of {@link net.Network}. It will be used by {@link net.Network} to
* forward received messages, write to a log and take action when the connection
* is closed.
*
* @see net.Network#Network(int, Network_iface, int)
*
* @author Raphael Blatter ([email protected])
*/
public interface Network_iface {
/**
* Is called to write connection information to the log. The information can
* either be ignored, directed to stdout or written out to a specialized
* field or file in the program.
*
* @param id
* The <b>int</b> passed to
* {@link net.Network#Network(int, Network_iface, int)} in the
* constructor. It can be used to identify which instance (which
* connection) a message comes from, when several instances of
* {@link net.Network} are connected to the same instance of a
* class implementing this interface.
* @param text
* The text to be written into the log in human readable form.
* Corresponds to information about the connection or ports.
*/
public void writeLog(int id, String text);
/**
* Is called when sequence of bytes are received over the Serial interface.
* It sends the bytes (as <b>int</b>s between 0 and 255) between the two
* {@link net.Network#divider}s passed via the constructor of
* {@link net.Network} (
* {@link net.Network#Network(int, Network_iface, int)}), without the
* {@link net.Network#divider}s. Messages are only forwarded using this
* function, once a {@link net.Network#divider} has been recognized in the
* incoming stream.
*
* @param id
* The <b>int</b> passed to
* {@link net.Network#Network(int, Network_iface, int)} in the
* constructor. It can be used to identify which instance a
* message comes from, when several instances of
* {@link net.Network} are connected to the same instance of a
* class implementing this interface.
* @param numBytes
* Number of valid bytes contained in the message
* @param message
* Message received over the Serial interface. The complete array
* of bytes (as <b>int</b>s between 0 and 255) between
* {@link net.Network#divider} is sent (without
* {@link net.Network#divider}s).
*/
public void parseInput(int id, int numBytes, int[] message);
/**
* Is called when the network has been disconnected. This call can e.g. be
* used to show the connection status in a GUI or inform the user using
* other means.
*
* @param id
* {@link net.Network#id} of the corresponding
* {@link net.Network} instance (see {@link net.Network#id}).
*/
public void networkDisconnected(int id);
}
每个类都是一个单独的文件。那么为什么会出现这个错误呢?
I compiled successfully three files and when I tried to launch a class which contains a public static void main
then I got errors. Here is the error :
C:\Documents and Settings\Ambre-28\Mes documents\JavaMESDKProjects\exempleRXTX\src\net\net>java Example
Exception in thread "main" java.lang.NoClassDefFoundError: Example (wrong name:
net/Example)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: Example. Program will exit.
Here are the codes :
package net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
/**
* This is a very simple example showing the most basic use of
* {@link net.Network} and {@link net.Network_iface}. Feel free to use,
* overwrite, or just ignore code as you like.
*
* As a default, a connection speed of 115200 baud is assumed. You can use a
* different speed by giving it as an <b>int</b> as the first command line
* argument or changing the default speed in the source code.
*
* @author Raphael Blatter ([email protected])
*/
public class Example implements net.Network_iface {
// set the speed of the serial port
public static int speed = 115200;
private static net.Network network;
private static boolean resend_active = false;
public static void main(String[] args) {
network = new net.Network(0, new net.Example(), 255);
// reading the speed if
if (args.length > 0) {
try {
speed = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("the speed must be an integer\n");
System.exit(1);
}
}
// initializing reader from command line
int i, inp_num = 0;
String input;
BufferedReader in_stream = new BufferedReader(new InputStreamReader(
System.in));
// getting a list of the available serial ports
Vector<String> ports = network.getPortList();
// choosing the port to connect to
System.out.println();
if (ports.size() > 0) {
System.out.println("the following serial ports have been detected:");
}
else {
System.out.println("sorry, no serial ports were found on your computer\n");
System.exit(0);
}
for (i = 0; i < ports.size(); ++i) {
System.out.println(" " + Integer.toString(i + 1) + ": " + ports.elementAt(i));
}
boolean valid_answer = false;
while (!valid_answer) {
System.out.println("enter the id (1,2,...) of the connection to connect to: ");
try {
input = in_stream.readLine();
inp_num = Integer.parseInt(input);
if ((inp_num < 1) || (inp_num >= ports.size() + 1))
System.out.println("your input is not valid");
else
valid_answer = true;
} catch (NumberFormatException ex) {
System.out.println("please enter a correct number");
} catch (IOException e) {
System.out.println("there was an input error\n");
System.exit(1);
}
}
// connecting to the selected port
if (network.connect(ports.elementAt(inp_num - 1), speed)) {
System.out.println();
} else {
System.out.println("sorry, there was an error connecting\n");
System.exit(1);
}
// asking whether user wants to mirror traffic
System.out.println("do you want this tool to send back all the received messages?");
valid_answer = false;
while (!valid_answer) {
System.out.println("'y' for yes or 'n' for no: ");
try {
input = in_stream.readLine();
if (input.equals("y")) {
resend_active = true;
valid_answer = true;
} else if (input.equals("n")) {
valid_answer = true;
} else if (input.equals("q")) {
System.out.println("example terminated\n");
System.exit(0);
}
} catch (IOException e) {
System.out.println("there was an input error\n");
System.exit(1);
}
}
// reading in numbers (bytes) to be sent over the serial port
System.out.println("type 'q' to end the example");
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
}
System.out.println("\nenter a number between 0 and 254 to be sent ('q' to exit): ");
try {
input = in_stream.readLine();
if (input.equals("q")) {
System.out.println("example terminated\n");
network.disconnect();
System.exit(0);
}
inp_num = Integer.parseInt(input);
if ((inp_num > 255) || (inp_num < 0)) {
System.out.println("the number you entered is not valid");
} else {
int temp[] = { inp_num };
network.writeSerial(1, temp); // ecriture dans le port série
System.out.println("sent " + inp_num + " over the serial port");
}
} catch (NumberFormatException ex) {
System.out.println("please enter a correct number");
} catch (IOException e) {
System.out.println("there was an input error");
}
}
}
/**
* Implementing {@link net.Network_iface#networkDisconnected(int)}, which is
* called when the connection has been closed. In this example, the program
* is ended.
*
* @see net.Network_iface
*/
public void networkDisconnected(int id) {
System.exit(0);
}
/**
* Implementing {@link net.Network_iface#parseInput(int, int, int[])} to
* handle messages received over the serial port. In this example, the
* received bytes are written to command line (0 to 254) and the message is
* sent back over the same serial port.
*
* @see net.Network_iface
*/
public void parseInput(int id, int numBytes, int[] message) {
if (resend_active) {
network.writeSerial(numBytes, message);
System.out.print("received and sent back the following message: ");
} else {
System.out.print("received the following message: ");
}
System.out.print(message[0]);
for (int i = 1; i < numBytes; ++i) {
System.out.print(", ");
System.out.print(message[i]);
}
System.out.println();
}
/**
* Implementing {@link net.Network_iface#writeLog(int, String)}, which is
* used to write information concerning the connection. In this example, all
* the information is simply written out to command line.
*
* @see net.Network_iface
*/
public void writeLog(int id, String text) {
System.out.println(" log: |" + text + "|");
}
}
package net;
import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
/**
* Used to simplify communication over a Serial port. Using the RXTX-library
* (rxtx.qbang.org), one connection per instance of this class can be handled.
* In addition to handling a connection, information about the available Serial
* ports can be received using this class.
*
* A separate {@link Thread} is started to handle messages that are being
* received over the Serial interface.
*
* This class also makes packages out of a stream of bytes received, using a
* {@link #divider}, and sending these packages as an array of <b>int</b>s (each
* between 0 and 255) to a function implemented by a class implementing the
* {@link net.Network_iface}-interface.
*
* @author Raphael Blatter ([email protected])
* @author heavily using code examples from the RXTX-website (rxtx.qbang.org)
*/
public class Network {
private InputStream inputStream;
private OutputStream outputStream;
/**
* The status of the connection.
*/
private boolean connected = false;
/**
* The Thread used to receive the data from the Serial interface.
*/
private Thread reader;
private SerialPort serialPort;
/**
* Communicating between threads, showing the {@link #reader} when the
* connection has been closed, so it can {@link Thread#join()}.
*/
private boolean end = false;
/**
* Link to the instance of the class implementing {@link net.Network_iface}.
*/
private Network_iface contact;
/**
* A small <b>int</b> representing the number to be used to distinguish
* between two consecutive packages. It can only take a value between 0 and
* 255. Note that data is only sent to
* {@link net.Network_iface#parseInput(int, int, int[])} once the following
* 'divider' could be identified.
*
* As a default, <b>255</b> is used as a divider (unless specified otherwise
* in the constructor).
*
* @see net.Network#Network(int, Network_iface, int)
*/
private int divider;
/**
* <b>int</b> identifying the specific instance of the Network-class. While
* having only a single instance, 'id' is irrelevant. However, having more
* than one open connection (using more than one instance of {@link Network}
* ), 'id' helps identifying which Serial connection a message or a log
* entry came from.
*/
private int id;
private int[] tempBytes;
int numTempBytes = 0, numTotBytes = 0;
/**
* @param id
* <b>int</b> identifying the specific instance of the
* Network-class. While having only a single instance,
* {@link #id} is irrelevant. However, having more than one open
* connection (using more than one instance of Network),
* {@link #id} helps identifying which Serial connection a
* message or a log entry came from.
*
* @param contact
* Link to the instance of the class implementing
* {@link net.Network_iface}.
*
* @param divider
* A small <b>int</b> representing the number to be used to
* distinguish between two consecutive packages. It can take a
* value between 0 and 255. Note that data is only sent to
* {@link net.Network_iface#parseInput(int, int, int[])} once the
* following {@link #divider} could be identified.
*/
public Network(int id, Network_iface contact, int divider) {
this.contact = contact;
this.divider = divider;
if (this.divider > 255)
this.divider = 255;
if (this.divider < 0)
this.divider = 0;
this.id = id;
tempBytes = new int[1024];
}
/**
* Just as {@link #Network(int, Network_iface, int)}, but with a default
* {@link #divider} of <b>255</b>.
*
* @see #Network(int, Network_iface, int)
*/
public Network(int id, Network_iface contact) {
this(id, contact, 255);
}
/**
* Just as {@link #Network(int, Network_iface, int)}, but with a default
* {@link #divider} of <b>255</b> and a default {@link #id} of 0. This
* constructor may mainly be used if only one Serial connection is needed at
* any time.
*
* @see #Network(int, Network_iface, int)
*/
public Network(Network_iface contact) {
this(0, contact);
}
/**
* This method is used to get a list of all the available Serial ports
* (note: only Serial ports are considered). Any one of the elements
* contained in the returned {@link Vector} can be used as a parameter in
* {@link #connect(String)} or {@link #connect(String, int)} to open a
* Serial connection.
*
* @return A {@link Vector} containing {@link String}s showing all available
* Serial ports.
*/
@SuppressWarnings("unchecked")
public Vector<String> getPortList() {
Enumeration<CommPortIdentifier> portList;
Vector<String> portVect = new Vector<String>();
portList = CommPortIdentifier.getPortIdentifiers();
CommPortIdentifier portId;
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
portVect.add(portId.getName());
}
}
contact.writeLog(id, "found the following ports:");
for (int i = 0; i < portVect.size(); i++) {
contact.writeLog(id, (" " + (String) portVect.elementAt(i)));
}
return portVect;
}
/**
* Just as {@link #connect(String, int)}, but using 115200 bps as a default
* speed of the connection.
*
* @param portName
* The name of the port the connection should be opened to (see
* {@link #getPortList()}).
* @return <b>true</b> if the connection has been opened successfully,
* <b>false</b> otherwise.
* @see #connect(String, int)
*/
public boolean connect(String portName) {
return connect(portName, 115200);
}
/**
* Opening a connection to the specified Serial port, using the specified
* speed. After opening the port, messages can be sent using
* {@link #writeSerial(String)} and received data will be packed into
* packets (see {@link #divider}) and forwarded using
* {@link net.Network_iface#parseInput(int, int, int[])}.
*
* @param portName
* The name of the port the connection should be opened to (see
* {@link #getPortList()}).
* @param speed
* The desired speed of the connection in bps.
* @return <b>true</b> if the connection has been opened successfully,
* <b>false</b> otherwise.
*/
public boolean connect(String portName, int speed) {
CommPortIdentifier portIdentifier;
boolean conn = false;
try {
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
contact.writeLog(id, "Error: Port is currently in use");
} else {
serialPort = (SerialPort) portIdentifier.open("RTBug_network",
2000);
serialPort.setSerialPortParams(speed, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
reader = (new Thread(new SerialReader(inputStream)));
end = false;
reader.start();
connected = true;
contact.writeLog(id, "connection on " + portName
+ " established");
conn = true;
}
} catch (NoSuchPortException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (PortInUseException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (UnsupportedCommOperationException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
} catch (IOException e) {
contact.writeLog(id, "the connection could not be made");
e.printStackTrace();
}
return conn;
}
/**
* A separate class to use as the {@link net.Network#reader}. It is run as a
* separate {@link Thread} and manages the incoming data, packaging them
* using {@link net.Network#divider} into arrays of <b>int</b>s and
* forwarding them using
* {@link net.Network_iface#parseInput(int, int, int[])}.
*
*/
private class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[1024];
int len = -1, i, temp;
try {
while (!end) {
if ((in.available()) > 0) {
if ((len = this.in.read(buffer)) > -1) {
for (i = 0; i < len; i++) {
temp = buffer[i];
// adjust from C-Byte to Java-Byte
if (temp < 0)
temp += 256;
if (temp == divider) {
if (numTempBytes > 0) {
contact.parseInput(id, numTempBytes,
tempBytes);
}
numTempBytes = 0;
} else {
tempBytes[numTempBytes] = temp;
++numTempBytes;
}
}
}
}
}
} catch (IOException e) {
end = true;
try {
outputStream.close();
inputStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
serialPort.close();
connected = false;
contact.networkDisconnected(id);
contact.writeLog(id, "connection has been interrupted");
}
}
}
/**
* Simple function closing the connection held by this instance of
* {@link net.Network}. It also ends the Thread {@link net.Network#reader}.
*
* @return <b>true</b> if the connection could be closed, <b>false</b>
* otherwise.
*/
public boolean disconnect() {
boolean disconn = true;
end = true;
try {
reader.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
disconn = false;
}
try {
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
disconn = false;
}
serialPort.close();
connected = false;
contact.networkDisconnected(id);
contact.writeLog(id, "connection disconnected");
return disconn;
}
/**
* @return Whether this instance of {@link net.Network} has currently an
* open connection of not.
*/
public boolean isConnected() {
return connected;
}
/**
* This method is included as a legacy. Depending on the other side of the
* Serial port, it might be easier to send using a String. Note: this method
* does not add the {@link #divider} to the end.
*
* If a connection is open, a {@link String} can be sent over the Serial
* port using this function. If no connection is available, <b>false</b> is
* returned and a message is sent using
* {@link net.Network_iface#writeLog(int, String)}.
*
* @param message
* The {@link String} to be sent over the Serial connection.
* @return <b>true</b> if the message could be sent, <b>false</b> otherwise.
*/
public boolean writeSerial(String message) {
boolean success = false;
if (isConnected()) {
try {
outputStream.write(message.getBytes());
success = true;
} catch (IOException e) {
disconnect();
}
} else {
contact.writeLog(id, "No port is connected.");
}
return success;
}
/**
* If a connection is open, an <b>int</b> between 0 and 255 (except the
* {@link net.Network#divider}) can be sent over the Serial port using this
* function. The message will be finished by sending the
* {@link net.Network#divider}. If no connection is available, <b>false</b>
* is returned and a message is sent using
* {@link net.Network_iface#writeLog(int, String)}.
*
* @param numBytes
* The number of bytes to send over the Serial port.
* @param message
* [] The array of<b>int</b>s to be sent over the Serial
* connection (between 0 and 256).
* @return <b>true</b> if the message could be sent, <b>false</b> otherwise
* or if one of the numbers is equal to the #{@link Network#divider}
* .
*/
public boolean writeSerial(int numBytes, int message[]) {
boolean success = true;
int i;
for (i = 0; i < numBytes; ++i) {
if (message[i] == divider) {
success = false;
break;
}
}
if (success && isConnected()) {
try {
for (i = 0; i < numBytes; ++i) {
outputStream.write(changeToByte(message[i]));
}
outputStream.write(changeToByte(divider));
} catch (IOException e) {
success = false;
disconnect();
}
} else if (!success) {
// message contains the divider
contact.writeLog(id, "The message contains the divider.");
} else {
contact.writeLog(id, "No port is connected.");
}
return success;
}
private byte changeToByte(int num) {
byte number;
int temp;
temp = num;
if (temp > 255)
temp = 255;
if (temp < 0)
temp = 0;
number = (byte) temp;
return number;
}
}
package net;
/**
* An instance of a class implementing this interface has to be passed to the
* constructor of {@link net.Network}. It will be used by {@link net.Network} to
* forward received messages, write to a log and take action when the connection
* is closed.
*
* @see net.Network#Network(int, Network_iface, int)
*
* @author Raphael Blatter ([email protected])
*/
public interface Network_iface {
/**
* Is called to write connection information to the log. The information can
* either be ignored, directed to stdout or written out to a specialized
* field or file in the program.
*
* @param id
* The <b>int</b> passed to
* {@link net.Network#Network(int, Network_iface, int)} in the
* constructor. It can be used to identify which instance (which
* connection) a message comes from, when several instances of
* {@link net.Network} are connected to the same instance of a
* class implementing this interface.
* @param text
* The text to be written into the log in human readable form.
* Corresponds to information about the connection or ports.
*/
public void writeLog(int id, String text);
/**
* Is called when sequence of bytes are received over the Serial interface.
* It sends the bytes (as <b>int</b>s between 0 and 255) between the two
* {@link net.Network#divider}s passed via the constructor of
* {@link net.Network} (
* {@link net.Network#Network(int, Network_iface, int)}), without the
* {@link net.Network#divider}s. Messages are only forwarded using this
* function, once a {@link net.Network#divider} has been recognized in the
* incoming stream.
*
* @param id
* The <b>int</b> passed to
* {@link net.Network#Network(int, Network_iface, int)} in the
* constructor. It can be used to identify which instance a
* message comes from, when several instances of
* {@link net.Network} are connected to the same instance of a
* class implementing this interface.
* @param numBytes
* Number of valid bytes contained in the message
* @param message
* Message received over the Serial interface. The complete array
* of bytes (as <b>int</b>s between 0 and 255) between
* {@link net.Network#divider} is sent (without
* {@link net.Network#divider}s).
*/
public void parseInput(int id, int numBytes, int[] message);
/**
* Is called when the network has been disconnected. This call can e.g. be
* used to show the connection status in a GUI or inform the user using
* other means.
*
* @param id
* {@link net.Network#id} of the corresponding
* {@link net.Network} instance (see {@link net.Network#id}).
*/
public void networkDisconnected(int id);
}
Each class is a separate file. So why this error is raised ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该从父目录启动它,因为
当您运行
java
命令时,它会采用完整类名称,包括包名称。因此,在您的情况下,JVM 试图查找一个名为Example
的类 - 它发现Example.class
作为文件,但随后失败,因为该类文件包含类 <代码>net.Example,而不是示例
。您需要位于父目录 (
...\exempleRXTX\src\net
) 中,以便当 JVM 查找net.Example
时,它会在>...\exempleRXTX\src\net\net
目录中名为Example.class
的文件。You should be launching it from the parent directory as
When you run the
java
command, it takes the full class name, including the package name. So in your case the JVM was trying to find a class just calledExample
- it foundExample.class
as a file, but then failed because that class file contains the classnet.Example
, notExample
.You need to be in the parent directory (
...\exempleRXTX\src\net
) so that when the JVM looks fornet.Example
it will look in the...\exempleRXTX\src\net\net
directory for a file calledExample.class
.检查 .class 文件的生成位置并确保类路径设置正确,但是,您似乎没有从 @Jon 提到的正确目录运行“java 命令”。
注意:指定“.”(单点)作为类路径值将配置
java
在同一目录中搜索 .class 文件(您尝试java 的位置)
命令)。Check where the .class files are being generated and ensure that classpath settings are right, However it seems that ur nt running the `java command' from a proper directory as mentioned by @Jon.
Note: Specifying '.'(single dot) as the classpath value will configure
java
to search for the .class files in same directory (from where u r tryingjava
command).