m0_70035249 2024-05-26 01:54 采纳率: 57.1%
浏览 19
已结题

流式socket文件传输答疑

在使用流式socket传输文件时遇到问题,读取到文件后只在终端输出乱码,不保存在工作目录是为什么?

package chatroomTCP;

import java.io.*;
import java.net.Socket;

public class MyStreamSocket extends Socket {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public MyStreamSocket(String host, int port) throws IOException {
        socket = new Socket(host, port);
        InputStream inputStream = socket.getInputStream();
        this.in = new BufferedReader(new InputStreamReader(inputStream));
        OutputStream outputStream = socket.getOutputStream();
        this.out = new PrintWriter(new OutputStreamWriter(outputStream));
    }

    public MyStreamSocket(Socket socket) throws IOException {
        this.socket = socket;
        InputStream inputStream = socket.getInputStream();
        this.in = new BufferedReader(new InputStreamReader(inputStream));
        OutputStream outputStream = socket.getOutputStream();
        this.out = new PrintWriter(new OutputStreamWriter(outputStream));
    }

    public String receiveMessage() throws IOException {
        return in.readLine();
    }

    public void sendMessage(String message) {
        out.println(message);
        out.flush();
    }

    public DataOutputStream getOut() throws IOException {
        return new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    }

    public DataInputStream getIn() throws IOException {
        return new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    }

    public void closeStreams() {
        try {
            if (in != null) in.close();
            if (out != null) out.close();
            if (socket != null) socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

```java
package chatroomTCP;

import java.io.*;
import java.util.Scanner;

public class ClientSocket {
    private File file = null;
    private DataInputStream in = null;
    private DataOutputStream out = null;
    private long lengths = -1;
    private MyStreamSocket myStreamSocket;
    private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    private void connect() {
        try {
            myStreamSocket = new MyStreamSocket("localhost", 12345);
            System.out.println("******欢迎来到聊天室******");
            while (true) {
                if (myStreamSocket != null && !myStreamSocket.isClosed()) {
                    out = myStreamSocket.getOut();
                    in = myStreamSocket.getIn();
                    getServerInfo();
                } else {
                    myStreamSocket = new MyStreamSocket("localhost", 12345);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 接收服务端输出流作为输入流 从服务端发送图片
    private void getServerInfo() {
        try {
            while (true) {
                long lengths = in.readLong();// 读取图片文件的长度
                if (lengths > 0) {
                    String fileName = in.readUTF();
                    byte[] bt = new byte[(int) lengths];// 创建字节数组
                    for (int i = 0; i < bt.length; i++) {
                        bt[i] = in.readByte();// 读取字节信息并存储到字节数组
                    }
                    File img = new File(String.valueOf(Math.random()) + fileName);
                    OutputStream out = new DataOutputStream(new FileOutputStream(img));
                    out.write(bt);
                    System.out.println("文件接收成功!!");
                }
            }
        } catch (Exception e) {
        } finally {
            try {
                if (in != null) {
                    in.close();// 关闭流
                }
                if (myStreamSocket != null) {
                    myStreamSocket.close(); // 关闭套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private void sendInfo() {
        while (true) { // 循环发送
            try {
                String string = reader.readLine();
                if (string.equalsIgnoreCase("send files")) { // 若为send files进行下一步
                    sendFile();
                } else {
                    myStreamSocket.sendMessage(string);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    // 写入输出流 发送文件
    private void sendFile() {
        try {
            System.out.println("请输入要发送的文件路径:");
            String filePath = reader.readLine();
            file = new File(filePath);
            DataInputStream inStream = null;// 定义数据输入流对象
            if (file != null) {
                lengths = file.length();// 获得选择图片的大小
                inStream = new DataInputStream(new FileInputStream(file));// 创建输入流对象
            } else {
                System.out.println("没有选择文件。");
                return;
            }
            out.writeLong(lengths);// 将文件的大小写入输出流 对应服务器的输入流
            out.writeUTF(file.getName());
            byte[] bt = new byte[(int) lengths];// 创建字节数组
            int len = -1;
            while ((len = inStream.read(bt)) != -1) {// 将图片文件读取到字节数组
                out.write(bt);// 将字节数组写入输出流
            }
            System.out.println("文件发送成功!!");
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ClientSocket client = new ClientSocket();
        new Thread(new Runnable() {
            @Override
            public void run() {
                client.connect(); // 调用方法
            }
        }).start();
        //此线程用发送消息给服务器
        new Thread(new Runnable() {
            @Override
            public void run() {
                client.sendInfo(); // 调用连接方法
            }
        }).start();
    }
}



package chatroomTCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class Server {
    static ArrayList<Socket> sockets = new ArrayList<>(); //将接收到的socket变成一个集合
    public static void main(String[] args) throws IOException {
        // 创建服务端
        ServerSocket ss = new ServerSocket(12345); // 创建ServerSocket对象,绑定监听的端口
        while (true) {
            try {
                Socket accept = ss.accept(); // accept()方法监听客户端的请求 等待客户端连接
                sockets.add(accept); // 连接后加入列表
                System.out.println("连接成功!!");
                //多个服务器线程进行对客户端的响应
                Thread thread = new Thread(new ServicesThread(accept));
                thread.start();
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        ss.close();
    }
    // 向所有客户端发送消息,除了当前客户端
    public static void sendToAllExceptCurrent(String message, Socket currentSocket) {
        for (Socket socket : sockets) {
            if (!socket.equals(currentSocket)) {
                try {
                    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                    out.println(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
package chatroomTCP;

import java.io.*;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ServicesThread extends Server implements Runnable {
    Socket socket;
    String socketName;
    private DataInputStream in = null;
    private DataOutputStream out = null;
    private long lengths = -1; // 图片文件的大小

    ServicesThread(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            // 有客户端加入发送通知
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            socketName = socket.getRemoteSocketAddress().toString();
            LocalDateTime join = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String joinTime = join.format(formatter);
            System.out.println("客户端@" + socketName + " 已于 " + joinTime + " 加入聊天");
            sendToAllExceptCurrent("客户端@" + socketName + " 已于 " + joinTime + " 加入聊天", socket);

            while (true) {
                MyStreamSocket mss = new MyStreamSocket(socket);
                String line = mss.receiveMessage(); // 输入流

                if (line == null || line.isEmpty()) {
                    continue;
                } else if (line.endsWith(".txt") || line.endsWith(".docx") || line.endsWith(".pdf") || line.endsWith(".csv") || line.endsWith(".html") ||
                        line.endsWith(".jpg") || line.endsWith(".png") || line.endsWith(".gif") || line.endsWith(".bmp") || line.endsWith(".svg")) {
                    in = new DataInputStream(mss.getIn());// 获得输入流对象
                    out = new DataOutputStream(mss.getOut());// 获得输出流对象
                    getClientInfo();
                } else if (line.equalsIgnoreCase("886")) {
                    System.out.println("客户端@" + socketName + " 已退出聊天");
                    Server.sendToAllExceptCurrent("客户端@" + socketName + " 已退出聊天", socket);
                    sockets.remove(socket);
                    break;
                } else {
                    LocalDateTime messageTime = LocalDateTime.now();
                    DateTimeFormatter formatter_1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    String messageTimeFor = messageTime.format(formatter_1);
                    String message = "客户端@" + socketName + " / " + messageTimeFor + ":" + line;
                    System.out.println(message);
                    sendToAllExceptCurrent(message, socket);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void getClientInfo() {
        try {
            while (true){
                // 读取数据文件大小
                long lengths = in.readLong();
                if(lengths>0){
                    String fileName=in.readUTF();
                    // 创建字节数组
                    byte[] bt = new byte[(int) lengths];
                    for (int i = 0; i < bt.length; i++) {
                        bt[i] = in.readByte();// 读取字节信息并存储到字节数组
                    }
                    File img=new File(String.valueOf(Math.random())+fileName);
                    OutputStream out=new DataOutputStream(new FileOutputStream(img));
                    out.write(bt);
                    System.out.println("文件接收成功!!");
                }
            }
        } catch (Exception e) {
        } finally {
            try {
                if (in != null) {
                    in.close();// 关闭流
                }
                if (socket != null) {
                    socket.close(); // 关闭套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


遇到的问题如图:

img

  • 写回答

12条回答 默认 最新

  • churuxu 2024-05-26 11:12
    关注

    两大问题
    1.流不是这么用的,不能随时构造一个,读一部分再close,是要跟socket保存同样的生命周期
    2.通信协议格式设计有问题,字符串跟文件可以弄成都是发整数+数据,统一处理

    代码修改示例如下,主要修改点

    1. 所有Socket输入输出都通过MyStreamSocket操作,不额外创建流
    2. 在MyStreamSocket中实现区分收发字符串和收发二进制文件内容
    package chatroomTCP;
     
    import java.io.*;
    import java.util.Scanner;
     
    public class ClientSocket {
        private File file = null;
        private DataInputStream in = null;
        private DataOutputStream out = null;
        private long lengths = -1;
        private MyStreamSocket myStreamSocket;
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
     
        public ClientSocket() throws IOException{
            myStreamSocket = new MyStreamSocket("localhost", 12345);
        }
    
        private void connect() {
            try {
                
                System.out.println("******欢迎来到聊天室******");
                while (true) {
                    if (myStreamSocket != null ) {
                        //out = myStreamSocket.getOut();
                        //in = myStreamSocket.getIn();
                        getServerInfo();
                    } else {
                        myStreamSocket = new MyStreamSocket("localhost", 12345);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 接收服务端输出流作为输入流 从服务端发送图片
        private void getServerInfo() {
            try {
                while (true) {
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
            } finally {
                try {
                    if (in != null) {
                        in.close();// 关闭流
                    }
                    if (myStreamSocket != null) {
                        myStreamSocket.close(); // 关闭套接字
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        private void sendInfo() {
            while (true) { // 循环发送
                try {
                    String string = reader.readLine();
                    if (string.equalsIgnoreCase("send files")) { // 若为send files进行下一步
                        sendFile();
                    } else {
                        myStreamSocket.sendMessage(string);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // 写入输出流 发送文件
        private void sendFile() {
            try {
                System.out.println("请输入要发送的文件路径:");
                String filePath = reader.readLine();
                myStreamSocket.sendMessage(filePath);
                myStreamSocket.sendFile(filePath);
               
                System.out.println("文件发送成功!!");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
     
        public static void main(String[] args) {
            try {
                ClientSocket client = new ClientSocket();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                       client.connect(); // 调用方法
                    }
                }).start();
                //此线程用发送消息给服务器
            
                client.sendInfo(); // 调用连接方法
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    package chatroomTCP;
     
    import java.io.*;
    import java.net.Socket;
    import java.nio.charset.Charset;
     
    public class MyStreamSocket  {
        private Socket socket;
        //private BufferedReader in;
        //private PrintWriter out;
    
        private DataInputStream in;
        private DataOutputStream out;
    
        public MyStreamSocket(String host, int port) throws IOException {
            socket = new Socket(host, port);
            InputStream inputStream = socket.getInputStream();
            //this.in = new BufferedReader(new InputStreamReader(inputStream));
            OutputStream outputStream = socket.getOutputStream();
            //this.out = new PrintWriter(new OutputStreamWriter(outputStream));
            in = new DataInputStream(inputStream);
            out = new DataOutputStream(outputStream);
        }
     
        public MyStreamSocket(Socket socket) throws IOException {
            this.socket = socket;
            InputStream inputStream = socket.getInputStream();
            //this.in = new BufferedReader(new InputStreamReader(inputStream));
            OutputStream outputStream = socket.getOutputStream();
            //this.out = new PrintWriter(new OutputStreamWriter(outputStream));
            in = new DataInputStream(inputStream);
            out = new DataOutputStream(outputStream);
        }
     
        public String getName(){
            return socket.getRemoteSocketAddress().toString();
        }
    
        public String receiveMessage() throws IOException {
            //return in.readUTF();
            byte[] data = receiveBytes();
            return new String(data, "UTF-8");
        }
    
        public void sendMessage(String message) throws IOException {
            byte[] data = message.getBytes("UTF-8");
            sendBytes(data);
        }
     
        public byte[] receiveBytes() throws IOException {        
            int len = in.readInt();
            return in.readNBytes(len);
        }
    
        public void sendBytes(byte[] data) throws IOException {        
            out.writeInt(data.length);
            out.write(data);
        }   
    
        public void receiveFile(String filename) throws IOException {
            FileOutputStream outputStream = new FileOutputStream(filename);
            int len = in.readInt();
            byte[] data = in.readNBytes(len);
            outputStream.write(data);
            outputStream.close();
        }
    
        public void sendFile(String filename) throws IOException {
            FileInputStream inputStream = new FileInputStream(filename);
            byte[] data = inputStream.readAllBytes();
            out.writeInt(data.length);
            out.write(data);
            inputStream.close();
        }
    
        public void close() {
            try {
                if (in != null) in.close();
                if (out != null) out.close();
                if (socket != null) socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    package chatroomTCP;
     
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Vector;
     
    public class Server {
        static ArrayList<MyStreamSocket> sockets = new ArrayList<>(); //将接收到的socket变成一个集合
        public static void main(String[] args) throws IOException {
            // 创建服务端
            ServerSocket ss = new ServerSocket(12345); // 创建ServerSocket对象,绑定监听的端口
            while (true) {
                try {
                    Socket accept = ss.accept(); // accept()方法监听客户端的请求 等待客户端连接
                    
                    MyStreamSocket mss = new MyStreamSocket(accept);
                    sockets.add(mss); // 连接后加入列表
                    System.out.println("连接成功!!");
                    //多个服务器线程进行对客户端的响应
                    Thread thread = new Thread(new ServicesThread(mss));
                    thread.start();
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                }
            }
            ss.close();
        }
        // 向所有客户端发送消息,除了当前客户端
        public static void sendToAllExceptCurrent(String message, MyStreamSocket currentSocket) {
            for (MyStreamSocket socket : sockets) {
                if (!socket.equals(currentSocket)) {
                    try {
                        //PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        //out.println(message);
                        socket.sendMessage(message);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
     
        // 向所有客户端发送消息,除了当前客户端
        public static void sendToAllExceptCurrent(byte[] message, MyStreamSocket currentSocket) {
            for (MyStreamSocket socket : sockets) {
                if (!socket.equals(currentSocket)) {
                    try {
                        //PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        //out.println(message);
                        socket.sendBytes(message);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } 
    }
     
    
    package chatroomTCP;
     
    import java.io.*;
    import java.net.Socket;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
     
    public class ServicesThread extends Server implements Runnable {
        //Socket socket;
        String socketName;
        private DataInputStream in = null;
        private DataOutputStream out = null;
        private long lengths = -1; // 图片文件的大小
        private MyStreamSocket mss;
     
        ServicesThread(MyStreamSocket socket) throws IOException{
            //this.socket = socket;
            mss = socket;
        }
     
        public void run() {
            try {
                // 有客户端加入发送通知
                //BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //socketName = socket.getRemoteSocketAddress().toString();
                socketName = mss.getName();
                LocalDateTime join = LocalDateTime.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String joinTime = join.format(formatter);
                System.out.println("客户端@" + socketName + " 已于 " + joinTime + " 加入聊天");
                sendToAllExceptCurrent("客户端@" + socketName + " 已于 " + joinTime + " 加入聊天", mss);
                
                while (true) {
                    
                    String line = mss.receiveMessage(); // 输入流
     
                    if (line == null || line.isEmpty()) {
                        continue;
                    } else if (line.endsWith(".txt") || line.endsWith(".docx") || line.endsWith(".pdf") || line.endsWith(".csv") || line.endsWith(".html") ||
                            line.endsWith(".jpg") || line.endsWith(".png") || line.endsWith(".gif") || line.endsWith(".bmp") || line.endsWith(".svg")) {
                        //in = new DataInputStream(mss.getIn());// 获得输入流对象
                        //out = new DataOutputStream(mss.getOut());// 获得输出流对象
                        getClientInfo();
                    } else if (line.equalsIgnoreCase("886")) {
                        System.out.println("客户端@" + socketName + " 已退出聊天");
                        Server.sendToAllExceptCurrent("客户端@" + socketName + " 已退出聊天", mss);
                        sockets.remove(mss);
                        break;
                    } else {
                        LocalDateTime messageTime = LocalDateTime.now();
                        DateTimeFormatter formatter_1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                        String messageTimeFor = messageTime.format(formatter_1);
                        String message = "客户端@" + socketName + " / " + messageTimeFor + ":" + line;
                        System.out.println(message);
                        sendToAllExceptCurrent(message, mss);
                    }
                }
     
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    mss.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
     
        private void getClientInfo() throws IOException{
            try {
                byte[] data = mss.receiveBytes();
                sendToAllExceptCurrent(data, mss);
                FileOutputStream outputStream = new FileOutputStream(Math.random() + ".png");
                outputStream.write(data);
                outputStream.close();
                
            } catch (Exception e) {
            } finally {
               
            }
        }
    }
     
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(11条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月26日
  • 已采纳回答 5月26日
  • 创建了问题 5月26日

悬赏问题

  • ¥200 如何使用postGis实现最短领规划?
  • ¥15 pyinstaller打包错误
  • ¥20 cesm的气溶胶排放文件
  • ¥15 逐月累计,月份不连续,补齐月份
  • ¥15 应用简单的Python代码完成一个学生成绩管理系统
  • ¥15 用matlab求微分方程初值问题
  • ¥15 vscode下编写第三方库opencv与pcl代码时没有代码提示
  • ¥15 能够跑通不报错,如何解决?(标签-matlab)
  • ¥15 MOS在RDS较大,频率高时开关波形异常
  • ¥15 SCENIC分析报错求解答