이 기사는 Java 소켓 구현의 파일 재개(코드 예제)에 대한 자세한 소개입니다. 필요한 친구가 참고할 수 있기를 바랍니다.
얼마전부터 자바 쓰레기인 저에게 작업이 필요했기 때문에 자바를 사용하여 간단한 파일 중단점 이력서 전송을 구현하는 방법을 공부하기 시작했습니다. 소위 파일 재개에 대해 제가 이해한 바는 어떤 이유로 파일을 전송하면 프로그램 실행이 중지되고 파일이 종료되어 다음에 파일을 다시 전송할 때 마지막 전송부터 파일이 전송될 수 있다는 것입니다. 다시 전송할 필요 없이 처음부터 시작합니다.
파일 전송 과정은 보내는 사람과 받는 사람으로 나누어집니다. 결국 내 생각은 이렇습니다.
1: 전송이 시작되기 전에 보낸 사람은 먼저 받는 사람에게 확인 메시지를 보낸 다음 파일을 보냅니다. 파일 이름
2: 수신자는 확인 메시지를 받은 후 보낸 사람이 보낸 파일 이름을 수신한 후 보낸 사람에게 파일 이름이 지정되었음을 알리는 확인 메시지를 보냅니다. 그러면 수신자는 수신된 파일 이름을 기반으로 ".temp" 파일 개체와 ".temp" RandomAccessFile 개체를 기반으로 파일을 생성합니다. 이 File 객체에 해당하는 파일의 길이(크기)를 가져오고(이 길이는 수신자가 수락한 길이입니다. 이전에 파일을 수신하지 않은 경우 길이는 0입니다) 파일 길이를 발신자에게 보냅니다.
3: 보낸 사람은 확인 메시지를 받은 후 받는 사람이 보낸 파일의 길이를 받은 다음 보낼 파일의 전체 길이를 받는 사람에게 보내고 확인 메시지를 받는 사람에게 보냅니다. 그러면 수신자가 보낸 파일의 길이에 따라 파일의 길이에 해당하는 위치부터 전송이 시작됩니다.
4: 수신자는 확인 메시지를 받은 후 발신자가 보낸 데이터를 수락한 다음 파일 끝부터 씁니다. 승인이 완료되면 ".temp" 파일을 일반 파일명으로 변경합니다.
다음과 같이 프로세스를 그립니다.
중단점 재개를 달성하는 핵심은 RandomAccessFile을 사용하는 것입니다. 이 유형의 인스턴스는 임의 액세스 파일 읽기 및 쓰기를 지원합니다.
진행률 표시줄 및 파일 선택기와 같은 일부 GUI를 추가합니다. 최종 주요 코드는 다음과 같습니다.
Sender code:
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) { } } } }
Receiver code:
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) { } } } }
Receiver test:
public class FileReceiveTest{ //接收方 public static void main(String[] args) { // TODO Auto-generated method stub ReceiveFile rf= new ReceiveFile(); rf.start(); } }
Send Square test:
public class FileSendTest{ //发送方 public static void main(String[] args) { // TODO Auto-generated method stub SendFile sf=new SendFile(); sf.start(); } }
주의하세요. 수신자 코드를 먼저 실행한 다음 발신자 코드를 실행합니다. 테스트할 때 더 큰 파일을 선택했습니다. 여기에서 실행 결과는 다음과 같습니다.
먼저 Box를 수신할지 여부를 묻는 메시지가 표시됩니다.
받기를 시작하려면 예를 클릭하고, 취소하려면 아니요를 클릭하세요
이것이 성공적으로 끝났습니다!
위 내용은 파일의 중단점 재개 업로드를 구현하는 Java 소켓에 대한 자세한 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!