今天就跟大家聊聊有關如何使用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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。