问题
I've adapted the Apache IOUtil sample to work with the WeatherTelnet sample a little differently. While the comments for WeatherTelnet state that:
The TelnetClient class used by itself is mostly intended for automating access to telnet resources rather than interactive use.
I would like to split the output using Apache TeeOutputStream, but the API branches OutputStream whereas TelnetClient "output" is in the form of an InputStream, so that, of course, it can be read. Conveniently, the Apache copyStream utility method will copy an InputStream to an OutputStream.
1.) How do I copy the InputStream to an OutputStream in printKindaWorks or printToFile?
2.) How do I either write the OutputStream to a file, or tee it?
the trick is to do these operations live, while the user interacts with the weather server.
I did my best to look at the source code for copyStream and used that for reference, but it just plain doesn't work. I haven't yet looked at the internals for the Apache implementation of tee.
The utility class:
package apache;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.net.io.Util;
public final class IOUtil {
private static final Logger log = Logger.getLogger(IOUtil.class.getName());
private static void readFromConsole(final OutputStream outputStream) {
Thread read = new Thread() {
@Override
public void run() {
int ch;
try {
while ((ch = System.in.read()) != -1) {
outputStream.write(ch);
outputStream.flush();
}
} catch (IOException ioe) {
log.warning(ioe.toString());
}
}
};
read.start();
}
private static void writeToConsole(final InputStream inputStream) {
Thread write = new Thread() {
@Override
public void run() {
try {
Util.copyStream(inputStream, System.out);
} catch (IOException ioe) {
log.warning(ioe.toString());
}
}
};
write.start();
}
private static void printKindaWorks(final InputStream inputStream) {
Thread write = new Thread() {
@Override
public void run() {
PrintStream printStream = null;
try {
File file = new File("weather.log");
FileOutputStream fos = new FileOutputStream(file, true);
printStream = new PrintStream(fos);
Util.copyStream(inputStream, printStream);
} catch (IOException ioe) {
log.warning(ioe.toString());
}
}
};
write.start();
}
// TeeOutputStream tee = new TeeOutputStream(inputStream, bis);
private static void writeToFile(final InputStream inputStream) throws FileNotFoundException, IOException {
final String fname = "whether.log";
File f = new File(fname);
f.createNewFile();
Thread fileWriter = new Thread() {
@Override
public void run() {
char c = 0;
int r = 0;
try {
while ((r = inputStream.read()) != -1) {
c = (char) r;
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fname, true)));
out.print(c);
out.close();
}
} catch (IOException ex) {
Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
fileWriter.start();
}
public static void readWriteLog(final InputStream inputStream, final OutputStream outputStream) throws FileNotFoundException, IOException {
readFromConsole(outputStream);
writeToConsole(inputStream);
writeToFile(inputStream); //doesn't write much
// printKindaWorks(inputStream); //blocks writeToConsole ?
}
}
and the driver:
package weather;
import apache.IOUtil;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.commons.net.telnet.TelnetClient;
public class Weather {
public Weather() {
}
public static void main(String[] args) throws UnknownHostException, IOException {
int port = 3000;
InetAddress host = InetAddress.getByName("rainmaker.wunderground.com");
TelnetClient telnetClient = new TelnetClient();
telnetClient.connect(host, port);
IOUtil.readWriteLog(telnetClient.getInputStream(), telnetClient.getOutputStream());
}
}
Please consider the code under the ASL.
While I am "logging" the InputStream I'm not not working on a logging problem, writing to a file is just for illustration purposes. I just want to split the InputStream while the user interacts with the weather server.
回答1:
You need to instantiate a TeeOutputStream which wraps System.out and the log file. Then create a thread which copies the telnet InputStream to the TeeOutputStream. (you can only have a single thread consuming the telnet InputStream)
回答2:
Not really what I want, would rather use Apache tee, but this does the job (clumsily):
package apache;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class IOUtil {
private static final Logger log = Logger.getLogger(IOUtil.class.getName());
private static void readFromConsole(final OutputStream outputStream) {
Thread read = new Thread() {
@Override
public void run() {
int ch;
try {
while ((ch = System.in.read()) != -1) {
outputStream.write(ch);
outputStream.flush();
}
} catch (IOException ioe) {
log.warning(ioe.toString());
}
}
};
read.start();
}
// TeeOutputStream tee = new TeeOutputStream(inputStream, bis);
private static void readInput(final InputStream inputStream) throws FileNotFoundException, IOException {
Thread readInput = new Thread() {
@Override
public void run() {
char c = 0;
int r = 0;
try {
while ((r = inputStream.read()) != -1) {
c = (char) r;
printToConsole(c);
logToFile(c);
}
} catch (IOException ex) {
Logger.getLogger(IOUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void logToFile(char c) throws IOException {
String fname = "whetherOrNot.log";
File f = new File(fname);
f.createNewFile();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fname, true)));
out.print(c);
out.flush();
out.close();
}
private void printToConsole(char c) {
System.out.print(c);
}
};
readInput.start();
}
public static void readWriteLog(final InputStream inputStream, final OutputStream outputStream) throws FileNotFoundException, IOException {
readFromConsole(outputStream);
readInput(inputStream);
}
}
来源:https://stackoverflow.com/questions/18801901/how-to-copy-an-inputstream-to-apache-teeoutputstream-which-expects-an-outputstr