套接字 InputStream 和 UTF-8

Dav*_*ain 4 java sockets encoding utf-8

我正在尝试与 Java 聊天。一切正常,除了特殊字符不起作用。我认为这是一个编码问题,因为我Outputstream在 UTF-8 中对字符串进行编码,如下所示:

  protected void send(String msg) {
    
        try {
          msg+="\r\n";            
          OutputStream outStream = socket.getOutputStream();              
          outStream.write(msg.getBytes("UTF-8"));
          System.out.println(msg.getBytes("UTF-8"));
          outStream.flush();
        }
        catch(IOException ex) {
          ex.printStackTrace();
        }
      }
Run Code Online (Sandbox Code Playgroud)

但在我的receive方法中,我没有找到一种方法来做到这一点:

public String receive() throws IOException {
   
    String line = "";
    InputStream inStream = socket.getInputStream();    
                
    int read = inStream.read();
    while (read!=10 && read > -1) {
      line+=String.valueOf((char)read);
      read = inStream.read();
    }
    if (read==-1) return null;
    line+=String.valueOf((char)read);       
    return line; 
    
  }
Run Code Online (Sandbox Code Playgroud)

那么有没有一种快速的方法来指定缓冲区读取的字节是用 UTF-8 编码的?

编辑:好的,我试过BufferedReader这样的:

 public String receive() throws IOException {
    
    String line = "";           
    in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));           
    String readLine = "";   
    
    while ((readLine = in.readLine()) != null) {
        line+=readLine;
    }
    
    System.out.println("Line:"+line);
    
    return line;
   
  }
Run Code Online (Sandbox Code Playgroud)

但它不起作用。似乎套接字没有收到任何东西。

hag*_*wal 6

试图为未来的访客提供更多的光线。

经验法则:服务器和客户端必须在编码方案之间同步,因为如果客户端发送使用某种编码方案编码的数据,而服务器正在使用其他编码方案读取数据,则永远无法实现预期的结果。

对于尝试测试这一点的人要注意的重要一点是不要在客户端使用 ASCII 编码(或者换句话说在客户端使用 ASCII 编码)并在服务器端使用 UTF8 进行解码(或者换句话说使用 UTF8 编码在服务器端)因为 UTF8 向后兼容 ASCII,所以可能会觉得“经验法则”是错误的,但不,它不是,所以最好在客户端使用 UTF8,在服务器端使用 UTF16,你就会明白。

使用套接字编码

我想要理解的最重要的事情是:最后通过套接字您将发送 BYTES 但这一切都取决于这些字节的编码方式

例如,如果我使用 Windows 命令提示符将输入发送到服务器(通过客户端 - 服务器套接字),那么数据将使用某种编码方案进行编码(我真的不知道是哪个),如果我使用另一个客户端将数据发送到服务器代码/程序然后我可以指定我想用于我的客户端套接字的 o/p 流的编码方案,然后所有数据将使用该编码方案转换/编码为 BYTES 并通过套接字发送。

现在,最后我仍然通过线路发送 BYTES,但这些是使用我指定的编码方案进行编码的。如果假设在服务器端,我在读取套接字的 i/p 流时使用另一种编码方案,则无法实现预期的结果,如果我在服务器上也使用相同的编码方案(与客户端的编码方案相同),那么一切都将是完美

回答这个问题

在 Java 中,有特殊的“桥接”流(在此处阅读),您可以使用它们来指定流的编码。

请注意:在 Java 中,InputStreamOutputStream是 BYTE 流,因此使用这些流读取和写入的所有内容都将是 BYTES,您不能使用InputStreamOutputStream类的对象指定编码,因此您可以使用 Java 桥接类。

下面是客户端和服务器的代码片段,我试图展示如何在客户端的输出流和服务器的输入流上指定编码

只要我在两端指定相同的编码,一切都会很完美。

客户端:

        Socket clientSocket = new Socket("abc.com", 25050);
        OutputStreamWriter clientSocketWriter = (new OutputStreamWriter(clientSocket.getOutputStream(), "UTF8"));
Run Code Online (Sandbox Code Playgroud)

服务器端:

    ServerSocket serverSocket = new ServerSocket(8001);
    Socket clientSocket = serverSocket.accept();
    // PLEASE NOTE: important thing below is I am specifying the encoding over my socket's input stream, and since Java's <<InputStream>> is a BYTE stream,  
    // so in order to specify the encoding I am using Java I/O's bridge class <<InputStreamReader>> and specifying my UTF8 encoding.
    // So, with this all my data (BYTES really) will be read from client socket as bytes "BUT" those will be read as UTF8 encoded bytes.
    // Suppose if I specify different encoding here, than what client is specifying in its o/p stream than data cannot read properly and may be all "?"
    InputStreamReader clientSocketReader = (new InputStreamReader(clientSocket.getInputStream(), "UTF8"));
Run Code Online (Sandbox Code Playgroud)