Inputstream readUTF无法读取UTF

时间:2015-01-23 10:34:39

标签: java sockets nio eofexception

我是Java的总菜鸟,如果这是一个菜鸟错误,请道歉。 我正在尝试使用Java NIO,我还没有进入使用非阻塞功能的阶段。我只是无法让服务器读取字符串,我知道从一侧发送Bytebuffer并尝试在另一侧将其解释为String并不容易,但我仍然无法弄清楚我要去哪里错误。这是代码

*****************************服务器端**************** **********************

class MyBlockingServer extends Thread
{
    private int M_PortNumber;
    private ServerSocket M_ServerSocket;

    MyBlockingServer(int PortNumber)
    {
        M_PortNumber = PortNumber;
        try {
            M_ServerSocket = new ServerSocket(M_PortNumber);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void run()
    {
        int my_number = 0;
        while(true)
        {
            try {
                Socket Server = M_ServerSocket.accept();


                DataInputStream inputStream = new DataInputStream(Server.getInputStream());
                System.out.println("[SERVER]" +inputStream.readUTF());


                DataOutputStream outputStream = new DataOutputStream(Server.getOutputStream());
                outputStream.writeUTF("Thanks for connection, you suck tata" + " "+ my_number);

                my_number++;
                Server.close();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    void socket_close()
    {
        try {
            M_ServerSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

public class JavaBlocking
{

    public static void main(String []args)
    {
        MyBlockingServer Server = new MyBlockingServer(8000);
        try {
            Server.start();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

*******************************客户端************** *******************

public class JavaChannels 
{

    public static void main(String []args)
    {
        SocketChannel client_channel = null;

        try {
            client_channel = SocketChannel.open();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("[Client] Socket channel open");

        try {
            client_channel.connect(new InetSocketAddress("127.0.0.1",8000));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("[Client] Socket channel connected");

        ByteBuffer my_buffer = ByteBuffer.allocate(48);
        my_buffer.clear();

        try {
            my_buffer.put("WHY_YOU_NO_WORK".getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }

        my_buffer.flip();

        try {
            int bytes_written = client_channel.write(my_buffer);

            while(my_buffer.hasRemaining())
            {
                bytes_written = client_channel.write(my_buffer);
            }

            System.out.println("[Client] Wrote "+ bytes_written +" bytes");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("[Client] Socket channel write finished");

        my_buffer.clear();
        my_buffer.flip();


        try {
            client_channel.read(my_buffer);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        System.out.println("[Client] server says" + new String(my_buffer.array()));

        try {
            client_channel.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}

我不断得到的错误是

  

java.io.EOFException at   java.io.DataInputStream.readFully(DataInputStream.java:197)at   java.io.DataInputStream.readUTF(DataInputStream.java:609)at   java.io.DataInputStream.readUTF(DataInputStream.java:564)at   netty_tutorial.blocking.MyBlockingServer.run(JavaBlocking.java:39)

这以某种方式告诉我,readUTF不是读取UTF格式而是其他东西。

总结我正在做的是

服务器 - >的readUTF

客户 - >字符串 - > UTF-8中的字节数组 - > ByteBuffer - >写

因为我明确地将字节数组编码为UTF-8。为什么readUTF无法读取它?

2 个答案:

答案 0 :(得分:3)

DataInput.readUTF方法没有读取UTF-8编码的字符串,它以DataOutput.writeUTF创建的特定格式读取数据,这类似于但是与真正的UTF-8不同:

  • 以16位无符号整数开头,给出构成字符串
  • 的后续字节数
  • 这些后续字节是UTF-8的修改形式,其中U + 0000以两个字节而不是1表示(因此字符串的二进制表示不能包含任何0个字节),并且表示U + FFFF以上的补充字符作为代理对,高和低代理分别以3个字节编码为UTF-8(真正的UTF-8将使用总共4个字节一次编码整个补充代码点)。

如果您正在编写真正的UTF-8,那么您需要阅读真正的UTF-8,如果您想要readUTF,那么您必须writeUTF

如果你想要writeUTFByteBuffer,那么在缓冲区周围实现一个OutputStream封装非常简单,你可以将其换成{{1} }}:

DataOutputStream

source

答案 1 :(得分:1)

您需要编写DataInputStream期望的格式。

e.g。

public static void writeUTF(ByteBuffer bb, String text) {
    byte[] bytes = text.getBytes("UTF-8");
    if (bytes.length > 1 << 16)
        throw new IllegalArgumentException();
    bb.putShort((short) bytes.length);
    bb.write(bytes);
}

注意:虽然writeUTF会将\0写为两个字节而不是一个,但readUTF会将其接受为1或2个字节。