Java Socket实现文件的断点续传的详细方法介绍(代码示例)

互联网 19-3-13
本篇文章给大家带来的内容是关于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实现文件的断点续传的详细方法介绍(代码示例)的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: java
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:Java中Object类的详细介绍

相关资讯