您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何使用Java Socket實現文件的斷點續傳,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
前段時間因為任務需要本人這個java渣渣開始研究如何用java實現簡單的文件斷點續傳。所謂的文件斷點續傳,我的理解是文件在傳輸過程中因為某些原因程序停止運行文件終止傳輸,下一次重新傳輸文件的時候還能從上一次傳輸的位置開始傳輸,而不需要重新從頭開始。
文件傳輸的過程分為發送方和接收方,最終我的思路是這樣的:
1:傳輸開始之前發送方先向接收方發送一個確認信息,然后再向接收方發送準備發送的文件的文件名
2:接收方收到確認信息之后,接收從發送方發送過來的文件名,接收完之后向發送方發送一個確認信息表示文件名接收完畢,然后接收方根據收到的文件名創建一個“.temp”File對象和一個“.temp”RandomAccessFile對象。獲取這個File對象所對應文件的長度(大小)(這個長度就是接收方已經接受的長度,如果之前沒有接收過這個文件,長度就為0),并把文件長度發送給發送方。
3:發送方收到確認信息之后,接收接受方發送的文件長度,然后向接收方發送準備發送的文件的總長度,并向接收方發送一個確認信息。然后根據接收方發送的文件長度,從文件對應長度的位置開始發送。
4:接收方收到確認信息之后,接受發送方發送過來的數據,然后從此文件的末尾寫入。接受完成之后再將“.temp”文件重命名為正常的文件名。
把過程畫成圖就是下面這樣:
ok”表示確認信息
能夠實現斷點續傳的關鍵就是使用了RandomAccessFile,此類的實例支持對隨機訪問文件的讀取和寫入。
加入一些如進度條、文件選擇器之類的GUI,最終的主要代碼如下:
發送方代碼:
import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.Socket; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; public class SendFile extends Thread{ private Socket socket=null; private DataOutputStream dos; private DataInputStream dis; private RandomAccessFile rad; private Container contentPanel; private JFrame frame; private JProgressBar progressbar; private JLabel label; public SendFile(){ frame= new JFrame(" 文件傳輸 "); try { socket=new Socket("localhost", 8080); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run(){ JFileChooser fc = new JFileChooser(); int status=fc.showOpenDialog( null ); if (status==JFileChooser. APPROVE_OPTION ) { String path =fc.getSelectedFile().getPath(); try { dos= new DataOutputStream(socket.getOutputStream()); dis= new DataInputStream(socket.getInputStream()); dos.writeUTF(" ok "); rad= new RandomAccessFile(path, " r "); File file= new File(path); byte[] buf= new byte[1024]; dos.writeUTF(file.getName()); dos.flush(); String rsp=dis. readUTF (); if (rsp.equals("ok")) { long size=dis.readLong(); //讀取文件已發送的大小 dos.writeLong(rad.length()); dos.writeUTF(" ok "); dos.flush(); long offset=size; //字節偏移量 int barSize=(int) (rad.length()/1024); int barOffset=(int)(offset/1024); //傳輸界面 frame.setSize(380,120); contentPanel = frame.getContentPane(); contentPanel.setLayout( new BoxLayout(contentPanel, BoxLayout. Y_AXIS )); progressbar = new JProgressBar(); //進度條 label=new JLabel(file.getName()+" 發送中 "); contentPanel.add(label); progressbar.setOrientation(JProgressBar. HORIZONTAL ); progressbar.setMinimum(0); progressbar.setMaximum(barSize); progressbar.setValue(barOffset); progressbar.setStringPainted(true); progressbar.setPreferredSize( new Dimension(150, 20)); progressbar.setBorderPainted(true); progressbar.setBackground( Color .pink); JButton cancel= new JButton(" 取消 "); JPanel barPanel= new JPanel(); barPanel.setLayout( new FlowLayout(FlowLayout. LEFT )); barPanel.add(progressbar); barPanel.add(cancel); contentPanel.add(barPanel); cancel.addActionListener( new CancelActionListener()); frame.setDefaultCloseOperation( JFrame. EXIT_ON_CLOSE ); frame.setVisible( true ); //從文件指定位置開始傳輸 int length; if (offset<rad.length()) { rad.seek(offset); while ((length=rad.read(buf))>0){ dos.write(buf,0,length); progressbar.setValue(++barOffset); dos.flush(); } } label.setText(file.getName()+" 發送完成 "); } dis.close(); dos.close(); rad.close(); } catch (IOException e) { // TODO Auto-generated catch block label.setText(" 取消發送,連接關閉 "); } finally { frame.dispose(); } } } class CancelActionListener implements ActionListener{ public void actionPerformed(ActionEvent e3){ try { label.setText(" 取消發送,連接關閉 "); JOptionPane.showMessageDialog(frame, " 取消發送給,連接關閉! ", " 提示: ", JOptionPane. INFORMATION_MESSAGE ); dis.close(); dos.close(); rad.close(); frame.dispose(); socket.close(); } catch (IOException e1) { } } } }
接收方代碼:
import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.net.ServerSocket; import java.net.Socket; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; public class ReceiveFile extends Thread{ private ServerSocket connectSocket=null; private Socket socket=null; private JFrame frame; private Container contentPanel; private JProgressBar progressbar; private DataInputStream dis; private DataOutputStream dos; private RandomAccessFile rad; private JLabel label; public ReceiveFile(){ frame= new JFrame(" 接收文件 "); try { connectSocket= new ServerSocket(8080); socket=connectSocket.accept(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run(){ try { dis= new DataInputStream(socket.getInputStream()); dos= new DataOutputStream(socket.getOutputStream()); dis.readUTF(); int permit=JOptionPane.showConfirmDialog(frame, " 是否接收文件","文件傳輸請求: ", JOptionPane. YES_NO_OPTION ); if (permit==JOptionPane. YES_OPTION ) { String filename=dis. readUTF (); dos.writeUTF(" ok "); dos.flush(); File file= new File(filename+" .temp "); rad= new RandomAccessFile(filename+" .temp ", " rw "); //獲得文件大小 long size=0; if (file.exists() && file.isFile()){ size=file.length(); } dos.writeLong(size); //發送已接收的大小 dos.flush(); long allSize=dis.readLong(); String rsp=dis. readUTF (); int barSize=( int )(allSize/1024); int barOffset=( int )(size/1024); //傳輸界面 frame.setSize(300,120); contentPanel =frame.getContentPane(); contentPanel.setLayout(new BoxLayout (contentPanel, BoxLayout. Y_AXIS )); progressbar = new JProgressBar(); //進度條 label= new JLabel(filename+" 接收中 "); contentPanel.add(label); progressbar.setOrientation(JProgressBar. HORIZONTAL ); progressbar.setMinimum(0); progressbar.setMaximum(barSize); progressbar.setValue(barOffset); progressbar.setStringPainted(true); progressbar.setPreferredSize( new Dimension(150, 20)); progressbar.setBorderPainted( true ); progressbar.setBackground( Color .pink); JButton cancel= new JButton(" 取消 "); JPanel barPanel= new JPanel(); barPanel.setLayout(new FlowLayout (FlowLayout. LEFT )); barPanel.add(progressbar); barPanel.add(cancel); contentPanel.add(barPanel); cancel.addActionListener( new CancelActionListener()); frame.setDefaultCloseOperation( JFrame. EXIT_ON_CLOSE ); frame.setVisible( true ); //接收文件 if (rsp.equals(" ok ")) { rad.seek(size); int length; byte[] buf= new byte[1024]; while((length=dis.read(buf, 0, buf.length))!=-1){ rad.write(buf,0,length); progressbar.setValue(++barOffset); } System. out .println(" FileReceive end... "); } label.setText(filename+" 結束接收 "); dis.close(); dos.close(); rad.close(); frame.dispose(); //文件重命名 if (barOffset>=barSize) { file.renameTo(new File(filename)); } } else { dis.close(); dos.close(); frame.dispose(); } } catch (IOException e) { // TODO Auto-generated catch block label.setText(" 已取消接收,連接關閉! "); } finally { frame.dispose(); } } class CancelActionListener implements ActionListener{ public void actionPerformed(ActionEvent e){ try { dis.close(); dos.close(); rad.close(); JOptionPane.showMessageDialog(frame, " 已取消接收,連接關閉! ", " 提示: ", JOptionPane. INFORMATION_MESSAGE ); label.setText(" 取消接收,連接關閉 "); } catch (IOException e1) { } } } }
接收方測試:
public class FileReceiveTest{ //接收方 public static void main(String[] args) { // TODO Auto-generated method stub ReceiveFile rf= new ReceiveFile(); rf.start(); } }
發送方測試:
public class FileSendTest{ //發送方 public static void main(String[] args) { // TODO Auto-generated method stub SendFile sf=new SendFile(); sf.start(); } }
注意 先運行接收方代碼再運行發送方代碼,測試的時候我們選一個大一點的文件,我這里選了個電影文件,運行結果如下:
首先會有是否接收的提示框
點擊是后,開始接收,點擊否就取消
至此就成功結束了!
看完上述內容,你們對如何使用Java Socket實現文件的斷點續傳有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。