gpt4 book ai didi

java - 在java中通过客户端服务器网络将进程输出打印到JTextArea

转载 作者:行者123 更新时间:2023-12-01 18:03:36 24 4
gpt4 key购买 nike

import java.io.*;
import java.net.*;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.FileChannel;

class StreamCopier implements Runnable {
private InputStream in;
private BufferedOutputStream out;

public StreamCopier(InputStream in, BufferedOutputStream out)
{
this.in = in;
this.out = out;
}

public void run()
{
try
{
int n;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1)
{
out.write(buffer, 0, n);
out.flush();
}
}
catch (IOException e)
{
System.out.println(e);
}
}
}

class InputCopier implements Runnable
{

private BufferedInputStream in;
private OutputStream out;

public InputCopier(BufferedInputStream in, OutputStream out)
{
this.in = in;
this.out = out;
}

public void run()
{
try
{
int n;
byte buffer[] = new byte[4096];
while ((n = in.read(buffer)) != -1)
{
out.write(buffer, 0, n);
out.flush();
}
out.close();
}
catch (AsynchronousCloseException e)
{
}
catch (IOException e)
{
System.out.println(e);
}
}
}

public class Test
{
private static Socket socket;

public static void main(String[] args)throws IOException, InterruptedException, NoSuchFieldException, IllegalAccessException
{
try
{
ServerSocket serverSocket=new ServerSocket(5000);
socket=serverSocket.accept();

BufferedInputStream in=new BufferedInputStream(socket.getInputStream());
BufferedOutputStream out=new BufferedOutputStream(socket.getOutputStream());
// BufferedOutputStream err=new BufferedOutputStream(socket.getErrorStream());
Process process = Runtime.getRuntime().exec("java Hello");

Thread outThread = new Thread(new StreamCopier(process.getInputStream(), out));
outThread.start();

// Thread errThread = new Thread(new StreamCopier(process.getErrorStream(), err));
// errThread.start();

Thread inThread = new Thread(new InputCopier(in, process.getOutputStream()));
inThread.start();

process.waitFor();
System.in.close();
outThread.join();
// errThread.join();
inThread.join();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}

测试类包含服务器套接字程序

import java.io.*;
import java.net.*;

class User
{
private static Socket socket;

public static void main(String args[])
{
try
{
socket = new Socket("localhost",5000);
Thread t1 = new A(socket);
t1.start();
Thread t2 = new B(socket);
t2.start();

t1.join();
t2.join();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
class B extends Thread
{
Socket socket;
B(Socket socket)
{
this.socket=socket;
}
public void run()
{
try
{
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
InputStream in=System.in;
int n;
byte buffer[] = new byte[4096];
while ((n = in.read(buffer)) != -1)
{
out.write(buffer, 0, n);
out.flush();
}
}
catch(Exception e)
{}
}
}
class A extends Thread
{
Socket socket;
A(Socket socket)
{
this.socket=socket;
}
public void run()
{
try
{
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
OutputStream out = System.out;

int n;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1)
{
out.write(buffer, 0, n);
out.flush();
}
}
catch(Exception e)
{}
}
}

用户类包含客户端套接字程序。

程序的输出 Output of program

我想将进程的输出打印到 JTextArea 并通过 JTextField 将输入传递给进程。

用户界面代码。

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;


public class Client {

private JFrame frame;
private JTextField textField;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Client window = new Client();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the application.
*/
public Client() {
initialize();
}

/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);

JTextArea txtrTextAreaFor = new JTextArea();
txtrTextAreaFor.setText("Text Area For Output of process");
txtrTextAreaFor.setBounds(36, 11, 289, 143);
frame.getContentPane().add(txtrTextAreaFor);

textField = new JTextField();
textField.setBounds(36, 165, 191, 43);
frame.getContentPane().add(textField);
textField.setColumns(10);

JButton btnSubmit = new JButton("Submit");
btnSubmit.setBounds(236, 185, 89, 23);
frame.getContentPane().add(btnSubmit);
}
}

最佳答案

所以,我完全是凭空写出来的,没有经过测试,所以可能需要一些调整

Swing 是一个单线程框架,它也不是线程安全的。这意味着您不应该执行任何可能阻塞事件调度线程的操作,例如读取/写入Socket,并且永远不应该从事件调度线程外部更新 UI。

看看Concurrency in Swing了解更多详情。

现在,对此的解决方案很少,最简单的可能是使用 SwingWorker,它允许您在 EDT 之外在后台进行某种处理(长时间运行/阻塞)线程,但它提供了许多简单的方法将数据安全地同步回 UI。

参见Worker Threads and SwingWorker了解更多详情。

此示例对 WriteWorkerReadWorker 使用 SwingWorker,从技术上讲,您不需要使用 SwingWorker 用于写入操作,因为您并未真正与 UI 交互,但我这样做是因为它稍微简化了错误管理。

public class SocketThread implements Runnable {

private String host;
private int port;

private JTextArea ta;

private WriteWorker writeWorker;
private ReadWorker readWorker;

private CountDownLatch shutDownLatch;

public SocketThread(String host, int port, JTextArea ta) {
this.host = host;
this.port = port;
this.ta = ta;
}

public void write(String text) {
if (writeWorker != null) {
if (writeWorker.getState() == SwingWorker.StateValue.STARTED) {
writeWorker.write(text);
} else {
throw new IllegalStateException("Write worker is not running");
}
} else {
throw new NullPointerException("Write worker is nul");
}
}

public void close() {
if (writeWorker != null) {
writeWorker.cancel(true);
}
if (readWorker != null) {
readWorker.cancel(true);
}

// Force the CountDownLatch to release
if (shutDownLatch != null) {
shutDownLatch.countDown();
shutDownLatch.countDown();
}
}

@Override
public void run() {
try (Socket socket = new Socket(host, port)) {
writeWorker = new WriteWorker(socket.getOutputStream());
readWorker = new ReadWorker(socket.getInputStream(), ta);

writeWorker.addPropertyChangeListener(new PropertyChangeHandler());
readWorker.addPropertyChangeListener(new PropertyChangeHandler());

writeWorker.execute();
readWorker.execute();

shutDownLatch = new CountDownLatch(2);
shutDownLatch.await();
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}

protected class PropertyChangeHandler implements PropertyChangeListener {

@Override
public void propertyChange(PropertyChangeEvent evt) {
SwingWorker worker = (SwingWorker) evt.getSource();
if (worker.getState() == SwingWorker.StateValue.DONE) {
shutDownLatch.countDown();

// Not interested in the return value, only interested in the
// exception if one was thrown...
try {
worker.get();
} catch (InterruptedException | ExecutionException ex) {
// Resync the error with the UI, probably using SwingUtilities.invokeLater
// and call some error handling method
ex.printStackTrace();
}
}
}

}

}

public class WriteWorker extends SwingWorker {

private OutputStream os;

private List<String> queue = new ArrayList<String>(25);
private ReentrantLock queueLock = new ReentrantLock();
private Condition queueCondition = queueLock.newCondition();

public WriteWorker(OutputStream os) {
this.os = os;
}

public void write(String text) {
queueLock.lock();
try {
queue.add(text);
queueCondition.signal();
} finally {
queueLock.unlock();
}
}

@Override
protected Object doInBackground() throws Exception {
while (!isCancelled()) {
String text = null;
while (text == null && !isCancelled()) {
queueLock.lock();
try {
if (queue.isEmpty()) {
queueCondition.await();
}

if (!queue.isEmpty()) {
text = queue.remove(0);
}
} finally {
queueLock.unlock();
}
if (text != null) {
os.write(text.getBytes());
}
}
}
return null;
}

}

public class ReadWorker extends SwingWorker<Void, String> {

private InputStream is;
private JTextArea ta;

public ReadWorker(InputStream is, JTextArea ta) {
this.is = is;
this.ta = ta;
}

@Override
protected void process(List<String> chunks) {
for (String text : chunks) {
ta.append(text);
}
}

@Override
protected Void doInBackground() throws Exception {
byte[] buffer = new byte[4096];
int bytesRead = -1;
while (!isCancelled() && (bytesRead = is.read(buffer)) != -1) {
String text = new String(buffer, 0, bytesRead);
publish(text);
}
return null;
}

}

关于java - 在java中通过客户端服务器网络将进程输出打印到JTextArea,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60593207/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com