如何在java中使用套接字在文件传输程序中包含进度条

我正在研究java中的一个项目,它将文件从客户端传输到服务器。 现在我需要显示每个文件传输的进度条,即每次传输开始时进度条应自动弹出。 我已经使程序创建进度条,但我无法将其与客户端 – 服务器程序合并。 如果有人帮我使用循环,我真的很感激。 谢谢。

ClientMain.java

public class ClientMain { private DirectoryTxr transmitter = null; Socket clientSocket = null; private boolean connectedStatus = false; private String ipAddress; String srcPath = null; String dstPath = ""; public ClientMain() { } public void setIpAddress(String ip) { this.ipAddress = ip; } public void setSrcPath(String path) { this.srcPath = path; } public void setDstPath(String path) { this.dstPath = path; } private void createConnection() { Runnable connectRunnable = new Runnable() { public void run() { while (!connectedStatus) { try { clientSocket = new Socket(ipAddress, 3339); connectedStatus = true; transmitter = new DirectoryTxr(clientSocket, srcPath, dstPath); } catch (IOException io) { io.printStackTrace(); } } } }; Thread connectionThread = new Thread(connectRunnable); connectionThread.start(); } 

DirectoryTxr.java

 import java.io.*; import java.net.Socket; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class DirectoryTxr { Socket clientSocket = null; String srcDir = null; String dstDir = null; byte[] readBuffer = new byte[1024]; private InputStream inStream = null; private OutputStream outStream = null; int state = 0; final int permissionReqState = 1; final int initialState = 0; final int dirHeaderSendState = 2; final int fileHeaderSendState = 3; final int fileSendState = 4; final int fileFinishedState = 5; private boolean isLive = false; private int numFiles = 0; private int filePointer = 0; String request = "May I send?"; String respServer = "Yes,You can"; String dirResponse = "Directory created...Please send files"; String fileHeaderRecvd = "File header received ...Send File"; String fileReceived = "File Received"; String dirFailedResponse = "Failed"; File[] opFileList = null; public DirectoryTxr(Socket clientSocket, String srcDir, String dstDir) { try { this.clientSocket = clientSocket; inStream = clientSocket.getInputStream(); outStream = clientSocket.getOutputStream(); isLive = true; this.srcDir = srcDir; this.dstDir = dstDir; state = initialState; readResponse(); //starting read thread sendMessage(request); state = permissionReqState; } catch (IOException io) { io.printStackTrace(); } } private void sendMessage(String message) { try { sendBytes(request.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * Thread to read response from server */ private void readResponse() { Runnable readRunnable = new Runnable() { public void run() { while (isLive) { try { int num = inStream.read(readBuffer); if (num > 0) { byte[] tempArray = new byte[num]; System.arraycopy(readBuffer, 0, tempArray, 0, num); processBytes(tempArray); } } catch (SocketException se) { System.exit(0); } catch (IOException io) { io.printStackTrace(); isLive = false; } } } }; Thread readThread = new Thread(readRunnable); readThread.start(); } private void sendDirectoryHeader() { File file = new File(srcDir); if (file.isDirectory()) { try { String[] childFiles = file.list(); numFiles = childFiles.length; String dirHeader = "$" + dstDir + "#" + numFiles + "&"; sendBytes(dirHeader.getBytes("UTF-8")); } catch (UnsupportedEncodingException en) { en.printStackTrace(); } } else { System.out.println(srcDir + " is not a valid directory"); } } private void sendFile(String dirName) { File file = new File(dirName); if (!file.isDirectory()) { try { int len = (int) file.length(); int buffSize = len / 8; //to avoid the heap limitation RandomAccessFile raf = new RandomAccessFile(file, "rw"); FileChannel channel = raf.getChannel(); int numRead = 0; while (numRead >= 0) { ByteBuffer buf = ByteBuffer.allocate(1024 * 100000); numRead = channel.read(buf); if (numRead > 0) { byte[] array = new byte[numRead]; System.arraycopy(buf.array(), 0, array, 0, numRead); sendBytes(array); } } System.out.println("Finished"); } catch (IOException io) { io.printStackTrace(); } } } private void sendHeader(String fileName) { try { File file = new File(fileName); if (file.isDirectory()) return;//avoiding child directories to avoid confusion //if want we can sent them recursively //with proper state transitions String header = "&" + fileName + "#" + file.length() + "*"; sendHeader(header); sendBytes(header.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } private void sendBytes(byte[] dataBytes) { synchronized (clientSocket) { if (outStream != null) { try { outStream.write(dataBytes); outStream.flush(); } catch (IOException io) { io.printStackTrace(); } } } } private void processBytes(byte[] data) { try { String parsedMessage = new String(data, "UTF-8"); System.out.println(parsedMessage); setResponse(parsedMessage); } catch (UnsupportedEncodingException u) { u.printStackTrace(); } } private void setResponse(String message) { if (message.trim().equalsIgnoreCase(respServer) && state == permissionReqState) { state = dirHeaderSendState; sendDirectoryHeader(); } else if (message.trim().equalsIgnoreCase(dirResponse) && state == dirHeaderSendState) { state = fileHeaderSendState; if (LocateDirectory()) { createAndSendHeader(); } else { System.out.println("Vacant or invalid directory"); } } else if (message.trim().equalsIgnoreCase(fileHeaderRecvd) && state == fileHeaderSendState) { state = fileSendState; sendFile(opFileList[filePointer].toString()); state = fileFinishedState; filePointer++; } else if (message.trim().equalsIgnoreCase(fileReceived) && state == fileFinishedState) { if (filePointer < numFiles) { createAndSendHeader(); } System.out.println("Successfully sent"); } else if (message.trim().equalsIgnoreCase(dirFailedResponse)) { System.out.println("Going to exit....Error "); // System.exit(0); } else if (message.trim().equalsIgnoreCase("Thanks")) { System.out.println("All files were copied"); } } private void closeSocket() { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } private boolean LocateDirectory() { boolean status = false; File file = new File(srcDir); if (file.isDirectory()) { opFileList = file.listFiles(); numFiles = opFileList.length; if (numFiles <= 0) { System.out.println("No files found"); } else { status = true; } } return status; } private void createAndSendHeader() { File opFile = opFileList[filePointer]; String header = "&" + opFile.getName() + "#" + opFile.length() + "*"; try { state = fileHeaderSendState; sendBytes(header.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { } } private void sendListFiles() { createAndSendHeader(); } } 

ServerMain.java

 public class ServerMain { public ServerMain() { } public static void main(String[] args) { DirectoryRcr dirRcr = new DirectoryRcr(); } } 

DirectoryRcr.java

 import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; public class DirectoryRcr { String request = "May I send?"; String respServer = "Yes,You can"; String dirResponse = "Directory created...Please send files"; String dirFailedResponse = "Failed"; String fileHeaderRecvd = "File header received ...Send File"; String fileReceived = "File Received"; Socket socket = null; OutputStream ioStream = null; InputStream inStream = null; boolean isLive = false; int state = 0; final int initialState = 0; final int dirHeaderWait = 1; final int dirWaitState = 2; final int fileHeaderWaitState = 3; final int fileContentWaitState = 4; final int fileReceiveState = 5; final int fileReceivedState = 6; final int finalState = 7; byte[] readBuffer = new byte[1024 * 100000]; long fileSize = 0; String dir = ""; FileOutputStream foStream = null; int fileCount = 0; File dstFile = null; public DirectoryRcr() { acceptConnection(); } private void acceptConnection() { try { ServerSocket server = new ServerSocket(3339); socket = server.accept(); isLive = true; ioStream = socket.getOutputStream(); inStream = socket.getInputStream(); state = initialState; startReadThread(); } catch (IOException io) { io.printStackTrace(); } } private void startReadThread() { Thread readRunnable = new Thread() { public void run() { while (isLive) { try { int num = inStream.read(readBuffer); if (num > 0) { byte[] tempArray = new byte[num]; System.arraycopy(readBuffer, 0, tempArray, 0, num); processBytes(tempArray); } sleep(100); } catch (SocketException s) { } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException i) { i.printStackTrace(); } } } }; Thread readThread = new Thread(readRunnable); readThread.start(); } private void processBytes(byte[] buff) throws InterruptedException { if (state == fileReceiveState || state == fileContentWaitState) { //write to file if (state == fileContentWaitState) state = fileReceiveState; fileSize = fileSize - buff.length; writeToFile(buff); if (fileSize == 0) { state = fileReceivedState; try { foStream.close(); } catch (IOException io) { io.printStackTrace(); } System.out.println("Received " + dstFile.getName()); sendResponse(fileReceived); fileCount--; if (fileCount != 0) { state = fileHeaderWaitState; } else { System.out.println("Finished"); state = finalState; sendResponse("Thanks"); Thread.sleep(2000); System.exit(0); } System.out.println("Received"); } } else { parseToUTF(buff); } } private void parseToUTF(byte[] data) { try { String parsedMessage = new String(data, "UTF-8"); System.out.println(parsedMessage); setResponse(parsedMessage); } catch (UnsupportedEncodingException u) { u.printStackTrace(); } } private void setResponse(String message) { if (message.trim().equalsIgnoreCase(request) && state == initialState) { sendResponse(respServer); state = dirHeaderWait; } else if (state == dirHeaderWait) { if (createDirectory(message)) { sendResponse(dirResponse); state = fileHeaderWaitState; } else { sendResponse(dirFailedResponse); System.out.println("Error occurred...Going to exit"); System.exit(0); } } else if (state == fileHeaderWaitState) { createFile(message); state = fileContentWaitState; sendResponse(fileHeaderRecvd); } else if (message.trim().equalsIgnoreCase(dirFailedResponse)) { System.out.println("Error occurred ...."); System.exit(0); } } private void sendResponse(String resp) { try { sendBytes(resp.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } private boolean createDirectory(String dirName) { boolean status = false; dir = dirName.substring(dirName.indexOf("$") + 1, dirName.indexOf("#")); fileCount = Integer.parseInt(dirName.substring(dirName.indexOf("#") + 1, dirName.indexOf("&"))); if (new File(dir).mkdir()) { status = true; System.out.println("Successfully created directory " + dirName); } else if (new File(dir).mkdirs()) { status = true; System.out.println("Directories were created " + dirName); } else if (new File(dir).exists()) { status = true; System.out.println("Directory exists" + dirName); } else { System.out.println("Could not create directory " + dirName); status = false; } return status; } private void createFile(String fileName) { String file = fileName.substring(fileName.indexOf("&") + 1, fileName.indexOf("#")); String lengthFile = fileName.substring(fileName.indexOf("#") + 1, fileName.indexOf("*")); fileSize = Integer.parseInt(lengthFile); dstFile = new File(dir + "/" + file); try { foStream = new FileOutputStream(dstFile); System.out.println("Starting to receive " + dstFile.getName()); } catch (FileNotFoundException fn) { fn.printStackTrace(); } } private void writeToFile(byte[] buff) { try { foStream.write(buff); } catch (IOException io) { io.printStackTrace(); } } private void sendBytes(byte[] dataBytes) { synchronized (socket) { if (ioStream != null) { try { ioStream.write(dataBytes); } catch (IOException io) { io.printStackTrace(); } } } } 

客户端应用程序包含两个类ClientMain.java和DirectoryTxr.java服务器应用程序包含两个类ServerMain.java和DirectoryRcr.java

还有我创建进度条的代码是

 import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; public class ProgressBar extends JFrame { JProgressBar current = new JProgressBar(0, 2000); int num = 0; public ProgressBar() { //exit button setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //create the panel to add the details JPanel pane = new JPanel(); current.setValue(0); current.setStringPainted(true); pane.add(current); setContentPane(pane); } //to iterate so that it looks like progress bar public void iterate() { while (num < 2000) { current.setValue(num); try { Thread.sleep(1000); } catch (InterruptedException e) { } num += 95; } } //for testing the app public static void main(String[] arguments) { ProgressBar frame = new ProgressBar(); frame.pack(); frame.setVisible(true); frame.iterate(); } } 

Swing是一个单线程框架。 这意味着与UI的所有交互都应该在此线程的上下文中进行(AKA事件调度线程)。

这也意味着如果您在EDT中执行任何类型的耗时/长时间运行或阻止过程,您将阻止它响应事件或更新UI。

这是您的代码目前正在做的事情。

有很多机制可供您使用,在您的情况下,最简单的可能是使用SwingWorker

 import java.awt.EventQueue; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class ProgressBar extends JFrame { JProgressBar current = new JProgressBar(0, 100); int num = 0; public ProgressBar() { //exit button setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //create the panel to add the details JPanel pane = new JPanel(); current.setValue(0); current.setStringPainted(true); pane.add(current); setContentPane(pane); } //to iterate so that it looks like progress bar public void iterate() { SwingWorker worker = new SwingWorker() { @Override protected Object doInBackground() throws Exception { while (num < 2000) { // current.setValue(num); try { Thread.sleep(125); } catch (InterruptedException e) { } num += 95; int p = Math.round(((float)Math.min(num, 2000) / 2000f) * 100f); setProgress(p); } return null; } }; worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if ("progress".equals(name)) { SwingWorker worker = (SwingWorker) evt.getSource(); current.setValue(worker.getProgress()); } } }); worker.execute(); } //for testing the app public static void main(String[] arguments) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } ProgressBar frame = new ProgressBar(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.iterate(); } }); } } 

查看http://docs.oracle.com/javase/tutorial/uiswing/concurrency/了解更多详情。

更新了双焊接进度条的示例

如果你需要显示多个进度棒,你可以简单地使用SwingWorkerpublishprocess方法来完成更复杂的结果......

在此处输入图像描述

 import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; */ public class ProgressBar extends JFrame { JProgressBar current = new JProgressBar(0, 100); JProgressBar overall = new JProgressBar(0, 100); int num = 0; public ProgressBar() { //exit button setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //create the panel to add the details JPanel pane = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; current.setValue(0); current.setStringPainted(true); overall.setStringPainted(true); pane.add(overall, gbc); pane.add(current, gbc); setContentPane(pane); } //to iterate so that it looks like progress bar public void iterate() { SwingWorker worker = new SwingWorker() { @Override protected void process(List chunks) { float[] progress = chunks.get(chunks.size() - 1); // only want the last one overall.setValue(Math.round(progress[0] * 100f)); current.setValue(Math.round(progress[1] * 100f)); } @Override protected Object doInBackground() throws Exception { int size = 2000; int overallSize = size * 10; int overallProgress = 0; for (int index = 0; index < 10; index++) { for (int count = 0; count < size; count++) { publish(new float[]{ getProgress(overallProgress, overallSize), getProgress(count, size), }); overallProgress++; Thread.sleep(2); } } return null; } public float getProgress(int value, int max) { return (float)value / (float)max; } }; worker.execute(); } //for testing the app public static void main(String[] arguments) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } ProgressBar frame = new ProgressBar(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); frame.iterate(); } }); } } 

查看使用进度条的Swing教程中的ProgressMonitorInputStream 。