0
点赞
收藏
分享

微信扫一扫

解释Python中的PEP 8是什么 为什么它很重要

念川LNSC 2024-06-02 阅读 4

在原有基础上加入文件的传输功能。

从客户端传送到服务器后,服务器接受文件,再转发给其他客户端,客户端接受后服务器删除文件。

涉及文件的读取与关闭。

1.原来传输的改进

1.1服务器需要区分传输的是文件还是信息。

        在传输之前先传输一个0/1让其判断是否为文件,其中0表示文件。

2.客服端clint:

        在里面添加了一个传输文件的方法outputFIle();

File类只存储文件的相关信息,如文件路径等等。因此文件的传输需要将文件的内容发送过去。

使用fileinputstream来读取文件的信息,DataOutputStream其有一些便捷的方式将数据转化为字节流,用他来传输文件内容。

现将文件的名字,以及群聊或者私聊及其对象传送过去,接着写入文件。定义一个1024大小的字节数组。使用read方法进行读取,此方法返回读取的长度。当读完文件后返回-1。读取1024字节大小后使用dos.write()写入。最后需要关闭文件的读取流,释放资源。

public void outputFile(File file,int index){
        try {
            //让其判断是文件还是信息
            os.write(0);//表示文件
            fis = new FileInputStream(file);
            dos = new DataOutputStream(os);
            //文件名,大小等属性
            dos.writeUTF(file.getName());
            dos.flush();//确保数据立即发送
            //发送群聊或者私聊
            String s;
            if (IMG[1] == 0) {
                s = IMG[1]+"";
            } else {
                s = PORT.get(index);
            }
            dos.writeUTF(s);
            dos.flush();
            dos.writeLong(file.length());
            dos.flush();
            //传输文件
            System.out.println("传输文件");
            byte[] bytes = new byte[1024];
            int length ;
            //读取文件file,并传输
            while((length = fis.read(bytes,0, bytes.length)) != -1){//每次读取1024个字节
                dos.write(bytes,0,length);
                dos.flush();
            }
            //释放文件读取流
            fis.close();
            System.out.println("发送成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

2.2按钮监听

在按钮中增添了发送文件的按钮。

并创建一个文件选择器的对象,选择文件后记录在file中,并调用上诉发送文件的方法。

else if (ae.equals("发送文件")) {
            System.out.println("发送文件");
            JFileChooser jfc = new JFileChooser();
            int result = jfc.showOpenDialog(null);
            if (result == JFileChooser.APPROVE_OPTION) {
                File file = jfc.getSelectedFile();
                //发送给服务器
                int index = groupOrPrivate();
                clint.outputFile(file, index);
            }
        }

2.3服务端的接受线程:

与发送类似先判断是消息还是文件,调用对应方法。

@Override
    public void run() {
        while (true) {
            try {
                int type = is.read();
                if (type == 1) {//消息
                    getMsg();
                } else if (type == 0) {//文件
                    saveFile();

                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

存储文件方法saveFile();

与写入类似,只不过使用datainputstream进行读取,fileoutputstream进行写入。

接受到文件名后存入fileName中 与大小后 创建相应文件名对象。同读取文件方法类似的写入方法。不过需要判断已经接受字节的大小,来停止文件的接受。因为接受文件的传输没有读取返回的-1。也可以使用接受到特定的字节时停止。最后关闭文件输出流。

public void saveFile() {
        try {
            System.out.println("接受文件");
            dis = new DataInputStream(is);
            String fileName = dis.readUTF();
            long fileLength = dis.readLong();
            File file = new File("C:\\Users\\15697\\IdeaProjects\\Pro24\\src\\ChatV3\\Client\\GetFile" + File.separatorChar + fileName);
            fos = new FileOutputStream(file);
            System.out.println("检测到文件名为:" + fileName + "开始接受文件");
            byte[] bytes = new byte[1024];
            int length;
            long readLength = 0;
            while ((length = dis.read(bytes, 0, bytes.length)) != -1) {
                fos.write(bytes, 0, length);
                fos.flush();
                readLength +=length;
                if(readLength >= fileLength){
                    break;
                }
            }
            //关闭文件输出流
            fos.close();
            System.out.println("文件接受完毕");
            sendMsg("-----接受到文件:"+fileName+"请查看------");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

服务端:

发送给客户端数据同样再加上消息还是文件的判定。

同时接受信息与客户端接受信息一致,需要接受文件。接受后还需要发送给指定用户。

 @Override
    public void run() {
        while (true) {
            getIMG();
        }
    }

    //接受消息
    public void getIMG() {
        try {
            int type = is.read();//判断文件 还是信息
            if (type == 1) {
                System.out.println("接受消息");
                getMessage();
            } else if (type == 0) {
                System.out.println("为文件");
                //接受文件
                getFile();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

getFile();先进行文件的获取,接着判断接受的对象名s为0则是群聊,其他的则是其他客户端的端口号。为群聊则调用

groupOutputFile(file);

私聊则调用先确定私聊的对象接着调用

outputFile(file);

即可。

public void getFile() {
        try {
            dis = new DataInputStream(is);
            String fileName = dis.readUTF();
            String s = dis.readUTF();//私发用户
            System.out.println("对象:" + s);
            long fileLength = dis.readLong();

            File file = new File("C:\\Users\\15697\\IdeaProjects\\Pro24\\src\\ChatV3\\Server\\temFile" + File.separatorChar + fileName);
            fos = new FileOutputStream(file);
            System.out.println("检测到文件名为:" + fileName + "开始接受文件");
            byte[] bytes = new byte[1024];
            int length;
            long readLength = 0;
            while ((length = dis.read(bytes, 0, bytes.length)) != -1) {//客户端读取-1时以及停止所以未发送过来,因此会陷入while中等待读取,需要我们加入一个-1
                fos.write(bytes, 0, length);
                fos.flush();
                readLength += length;
                if(readLength >= fileLength){
                    break;
                }
            }
            System.out.println("文件接受完毕");
            //接受发送对象
            //dis.close();
            if (s.equals("0")) {//群聊
                System.out.println("群发文件");
                //文件群聊发送
                groupOutputFile(file);
            } else {
                //私发
                int size = sockets.size();
                for (int i = 0; i < size; i++) {
                    System.out.println("查找私发文件对象");
                    Socket temSocket = sockets.poll();
                    if (s.equals(String.valueOf(temSocket.getPort()))) {//给私聊对象发送
                        //发送信号给客户端是否接受文件
                        os = temSocket.getOutputStream();
                        outputFile(file);
                        //删除文件
                       deleteFile(file);
                    }
                    sockets.offer(temSocket);
                }
                //发送给消息对象
                os = socket.getOutputStream();
                output("文件发送成功");


            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } 
    }
public synchronized void groupOutputFile(File file) {
        try {
            int size = sockets.size();
            for (int i = 0; i < size; i++) {
                System.out.println("多少个用户端:" + sockets.size());
                Socket temSocket = sockets.poll();
                os = temSocket.getOutputStream();
                outputFile(file);
                sockets.offer(temSocket);
            }
            //删除文件
            deleteFile(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
public void outputFile(File file) {
        try {

            //让其判断是文件还是信息
            os.write(0);//表示文件
            fis = new FileInputStream(file);
            dos = new DataOutputStream(os);

            //文件名,大小等属性
            dos.writeUTF(file.getName());
            dos.flush();//确保数据立即发送
            dos.writeLong(file.length());
            dos.flush();
            //传输文件
            System.out.println("传输文件");
            byte[] bytes = new byte[1024];
            int length;
            //读取文件file,并传输
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {//每次读取1024个字节
                dos.write(bytes, 0, length);
                dos.flush();
            }
            System.out.println("发送成功");
            fis.close();
            fos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } 
    }
public void deleteFile(File file){
        //删除文件
        if(file.exists()){
            boolean isdelete = file.delete();
            if(isdelete){
                System.out.println("文件已接受,删除文件成功");
            }else {
                System.out.println("文件正在被使用,删除失败");
            }
        }
    }

即可完成文件的传输。

注:文件的的写入与读取后将相应流关闭。关闭后服务器才能删除缓存文件。

举报

相关推荐

0 条评论