java笔记 传送文件实例

代码主要注意使用文件选择器的时候,读取文件语句while((len = in.read(bytes)) > 0),会一直卡在这个循环中,所以只能传送一次文件

因此我们要在读取文件的时候,加入文件截至符:
1 发送文件时,将文件截至符以byte的数据类型写入文件

// 传送文件截至符
            out.write("##end".getBytes() , 0, 5);   // 获取字节数组

2 接受文件时,我们要判断文件是否读到截至符

// 判断文件是否结束
String end = new String(bytes, 0, len);
if(end.substring(end.length() - 5).equals("##end"))
{
    fileOut.write(end.substring(0, end.length()-5).getBytes() ,0, end.length()-5);
    fileOut.flush();
    break;
}

服务端

package Platform;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class ServerGUI extends JFrame
{

    JTextArea showArea;                  // 显示文本框
    JTextField sendfield;                // 端口文本框
    serthread st;                        // 线程
    Startbtnpolice startbtnpolicebp;     // 开始按钮的监听器
    Sentbtnpolice sentbtnpolice;         // 发送按钮的监听器
    JTextField portfield;                // 端口的文本框

    // 开始按钮监听器
    private class Startbtnpolice implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            if(portfield.getText().equals("1999"))
                showArea.append("Server starting… "+"\n" );
            else
                showArea.append("非法端口" + "\n");
        }
    }

    // 发送按钮监听器
    private class Sentbtnpolice extends KeyAdapter implements ActionListener  //
    {
        public void actionPerformed(ActionEvent e)
        {
            st.sentmssage(sendfield.getText());
            showArea.append("发送文件:" + sendfield.getText() + "\n");
            sendfield.setText("");
        }

        public void keyTyped(KeyEvent ke)
        {
            if(ke.getKeyCode() == KeyEvent.VK_ENTER)
            {
                st.sentmssage(sendfield.getText());
                showArea.append("发送文件:" + sendfield.getText() + "\n");
                sendfield.setText("");
            }
        }
    }




    public void setthread(serthread st)
    {
        this.st = st;
    }

    public ServerGUI()
    {
        super("服务器");
        Container contain = getContentPane();

        // 实例化监听器
        startbtnpolicebp = new Startbtnpolice();
        sentbtnpolice = new Sentbtnpolice();

        // 显示文本框设置
        showArea = new JTextArea(5,20);
        JScrollPane js = new JScrollPane(showArea);
        contain.add(js);

        // 顶端布局设置
        JPanel upPanel = new JPanel();
        upPanel.setLayout(new FlowLayout());
        JButton startbtn = new JButton("Start");
        startbtn.addActionListener(startbtnpolicebp);
        JLabel portlabel=new JLabel("Port:",SwingConstants.LEFT);
        portfield=new JTextField(30);
        portfield.setText("1999");
        upPanel.add(portlabel);
        upPanel.add(portfield);
        upPanel.add(startbtn);
        contain.add(upPanel, BorderLayout.NORTH);

        // 底端布局设置
        JPanel downpanel = new JPanel();
        downpanel.setLayout(new FlowLayout());
        sendfield = new JTextField(30);    // 发送文件文本框
        JButton sendbtn = new JButton("Send");
        sendbtn.addActionListener(sentbtnpolice);

        //
        sendbtn.addKeyListener(sentbtnpolice);

        downpanel.add(new JLabel("File Path:"));
        downpanel.add(sendfield);
        downpanel.add(sendbtn);
        contain.add(downpanel, BorderLayout.SOUTH);

        setSize(600, 400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

class serthread extends Thread
{
    Socket socketonserver;            // 自身的套接字
    ServerSocket socketforclient;     // 返回客户端的套接字
    DataInputStream in;               // 输入数据流
    DataOutputStream out;             // 输出数据流
    ServerGUI gui;                    // 利用gui发送消息,使其显示在文本框中


    public serthread(ServerGUI Gui)
    {
        try
        {
            gui = Gui;
            gui.setthread(this);    // 获得线程,最后利用线程在监听器中发送消息,其实在实例化主线程的st,进而完成监听器的操作

            socketforclient = new ServerSocket(1999);  // 返回客户端是1999的套接字
            socketonserver = socketforclient.accept();       // 建立连接

            // 接受发出数据流
            in = new DataInputStream(socketonserver.getInputStream());          // 读取接受文件名
            out = new DataOutputStream(socketonserver.getOutputStream());       // 读取发送文件名
        }
        catch(IOException e)
        {
            System.out.println(e);
        }
    }

    public void run()
    {
        String filename;       // 接受到的文件名(包含地址)

        // 不断获取信息
        while(true)
        {
            try
            {
                System.out.println("有文件了");
                filename = in.readUTF();       // 获取接收到的文件名
                gui.showArea.append("接收文件:" + filename + "\n");
                System.out.println(filename);  // 先输出文件名

                // 获取文件名(不带路径)
                String newpath = null;   // 不带路径的文件名
                for(int i = 0;i < filename.length();i++)
                {
                    char c = filename.charAt(i);

                    if(c == '\\')
                        newpath = filename.substring(i + 1);
                }

                // 在本地创建文件
                File file = new File("C:\\Users\\dell\\Desktop\\Experiment2_Chat 传文件\\文件下载地址\\" + newpath);  // 写本地文件(固定地址)
                if(!file.exists())
                    file.createNewFile();

                // 在本地写文件
                FileOutputStream fileOut = new FileOutputStream(file);
                byte bytes[] = new byte[1024];  // 读取的内容数据
                int len;
                while((len = in.read(bytes)) > 0)
                {
                    // 判断文件是否结束
                    String end = new String(bytes, 0, len);
                    if(end.substring(end.length() - 5).equals("##end"))
                    {
                        fileOut.write(end.substring(0, end.length()-5).getBytes(),0,end.length()-5);
                        fileOut.flush();
                        break;
                    }

                    fileOut.write(bytes, 0, len);  // 读取一部分内容
                    fileOut.flush();                    // 刷新缓存区
                }

                // 关闭流
                fileOut.close();
            }
            catch(Exception e)
            {
                System.out.println(e.getMessage());
                break;
            }
        }
    }

    // 发送消息
    public void sentmssage(String filename)
    {
        try
        {
            // 传送文件名
            out.writeUTF(filename);

            // 打开文件
            File file = new File("C:\\Users\\dell\\Desktop\\2019215053 杨雨润\\Experiment2_Chat 作业5\\文件来源\\" + filename);
            FileInputStream filein = new FileInputStream(file);   // 传送文件流

            // 开始传送文件
            byte bytes[] = new byte[1024];
            int l;
            while((l = filein.read(bytes)) > 0)
            {
                out.write(bytes, 0, l);
                out.flush();
            }

            // 传送文件截至符
            out.write("##end".getBytes() , 0, 5);   // 获取字节数组
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

public class Serve
{
    public static void main(String args[])
    {
        ServerGUI sGUI = new ServerGUI();
        serthread st = new serthread(sGUI);
        st.start();
    }
}

客户端

package Platform;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;

class ClientGUI extends JFrame
{
    JTextArea showArea;                       // 输出文本框
    JTextField sendfield;                     // 发送框
    clithread ct;                             // 自定义客户端线程
    JTextField ipfield;                       // IP地址输入框
    JTextField portfield;                     // Port发送框
    JButton connectbtn;                       // 连接按钮
    Connectbtnpolice connectbtnpolice;        // 连接按钮监听器
    Sendbtnpolice sendbtnpolice;              // 发送按钮监听器

    // 连接按钮监听器
    private class Connectbtnpolice implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println(portfield.getText());
            if(portfield.getText().equals( "1999"))
            {
                showArea.append("Connect to server…" + "\n");
                // 连接成功以后开始创造线程
                ct = new clithread(ipfield.getText(), 1999, ClientGUI.this);
                ClientGUI.this.setthread(ct);
                showArea.append("Client connected…" + "\n");
            }
            else
            {
                showArea.append("非法端口" + "\n");
            }
        }
    }

    // 发送按钮监听器
    private class Sendbtnpolice implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            ct.sentmessage(sendfield.getText());    // 带路径的文件名
            showArea.append("发送文件: " + sendfield.getText() + "\n");
            sendfield.setText("");
        }
    }

    //构造函数
    public void setthread(clithread ct)
    {
        this.ct = ct;
    }

    public void showFileOpenDialog(Component parent, JTextField msgTextArea)
    {
        // 创建一个默认的文件选取器
        JFileChooser fileChooser = new JFileChooser();

        // 设置默认显示的文件夹为当前文件夹
        fileChooser.setCurrentDirectory(new File("."));

        // 设置文件选择的模式(只选文件、只选文件夹、文件和文件均可选)
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

        // 打开文件选择框(线程将被阻塞, 直到选择框被关闭)
        int result = fileChooser.showOpenDialog(parent);    // 正真打开选择对话框 parent就是父窗口

        if (result == JFileChooser.APPROVE_OPTION) {
            // 如果点击了"确定", 则获取选择的文件路径

            /*返回值:
             *     JFileChooser.CANCEL_OPTION: 点击了取消或关闭
             *     JFileChooser.APPROVE_OPTION: 点击了确认或保存
             *     JFileChooser.ERROR_OPTION: 出现错误*/

            // 获得被选择文件
            File file = fileChooser.getSelectedFile();
            msgTextArea.setText(file.getAbsolutePath());
        }
    }

    public ClientGUI()
    {
        super("客户端");

        // 布局
        Container contain = getContentPane();  // 获得容器面板
        contain.setLayout(new BorderLayout());

        // 实例化监听器
        connectbtnpolice = new Connectbtnpolice();
        sendbtnpolice = new Sendbtnpolice();

        // 对话文本框
        showArea = new JTextArea(10,30);
        contain.add(new JScrollPane(showArea), BorderLayout.CENTER);

        // 顶端布局
        JPanel upPanel = new JPanel();
        upPanel.setLayout(new FlowLayout());
        upPanel.add(new JLabel("Server IP:"));
        ipfield = new JTextField(15);
        ipfield.setText("127.0.0.1");
        upPanel.add(ipfield);
        upPanel.add(new JLabel("Serve Port:"));
        portfield =new JTextField(8);
        upPanel.add(portfield);
        connectbtn = new JButton("Connect");
        connectbtn.addActionListener(connectbtnpolice);
        upPanel.add(connectbtn);
        contain.add(upPanel, BorderLayout.NORTH);

        // 底端布局
        JPanel downpanel = new JPanel();
        downpanel.setLayout(new FlowLayout());  // 面板
        sendfield = new JTextField(30);//发送文本框
        JButton sendBtn = new JButton("Send");   // 发送按钮
        sendBtn.addActionListener(sendbtnpolice);
        downpanel.add(new JLabel("File Path:"));
        downpanel.add(sendfield);

        // 创建 打开文件按钮
        JButton openBtn = new JButton("打开文件");
        openBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showFileOpenDialog(ClientGUI.this, sendfield);   // 打开文件对话框,创建自己的类,第一个参数是父窗口,第二个是显示文本框
            }
        });
        downpanel.add(openBtn);
        downpanel.add(sendBtn);
        contain.add(downpanel, BorderLayout.SOUTH);

        setSize(600, 400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class clithread extends Thread
{
    Socket ct;                // 自己的套接字
    ClientGUI cGUI;           // 调用窗口显示文本
    DataInputStream in;
    DataOutputStream out;

    // 构造函数
    public clithread(String IP, int Port,  ClientGUI cgui)
    {
        try
        {
            cGUI = cgui;
            ct = new Socket(IP, Port);
            in = new DataInputStream(ct.getInputStream());
            out = new DataOutputStream(ct.getOutputStream());
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
        start();
    }

    public void run()
    {
        String filename;

        // 获取信息
        while(true)
        {
            try
            {
                filename = in.readUTF();       // 获取接收到的文件名(带路径)
                cGUI.showArea.append("接收文件:" + filename + "\n");
                System.out.println(filename);  // 先输出文件名

//                // 获取文件名(不带路径)
//                String newpath = null;   // 不带路径的文件名
//                for(int i = 0;i < filename.length();i++)
//                {
//                    char c = filename.charAt(i);
//
//                    if(c == '\\')
//                        newpath = filename.substring(i + 1);
//                }

                // 在本地创建文件
                File file = new File("C:\\Users\\dell\\Desktop\\2019215053 杨雨润\\Experiment2_Chat 作业5\\文件下载地址\\" + filename);  // 写本地文件(固定地址)
                if(!file.exists())
                    file.createNewFile();
                System.out.println("文件建好了");

                // 在本地写文件
                FileOutputStream fileOut = new FileOutputStream(file);
                byte bytes[] = new byte[1024];  // 读取的内容数据
                int len;
                while((len = in.read(bytes)) != -1)
                {
                    // 判断文件是否结束
                    String end = new String(bytes, 0, len);    // 解码,将字节转换为String
                    if(end.substring(end.length() - 5).equals("##end"))
                    {
                        fileOut.write(end.substring(0, end.length()-5).getBytes(),0,end.length()-5);
                        fileOut.flush();
                        break;
                    }

                    fileOut.write(bytes, 0, len);  // 读取一部分内容
                    fileOut.flush();                    // 刷新缓存区
                }

                // 关闭流
                fileOut.close();

            }
            catch(Exception e)
            {
                System.out.println(e);
                break;
            }
        }
    }

    // 发送消息
    public void sentmessage(String filename)
    {
        try
        {
            // 传送文件名
            out.writeUTF(filename);    // 文件名带路径

            // 打开文件
            File file = new File(filename);
            FileInputStream filein = new FileInputStream(file);   // 传送文件流

            // 开始传送文件
            byte bytes[] = new byte[1024];
            int l;
            while((l = filein.read(bytes)) > 0)       // 将数据读入bytes数组中,返回字节数
            {
                out.write(bytes, 0, l);           // 将bytes数组中的数据写出,从off开始,总共长度是l
                out.flush();
            }

            // 传送文件截至符
            out.write("##end".getBytes() , 0, 5);   // 获取字节数组

            System.out.println("文件发完了");
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }


}
public class Client
{
    public static void main(String[] args)
    {
        ClientGUI cGUI = new ClientGUI();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值