Inputstream readUTF 无法读取UTF
Inputstream readUTF can't read UTF
我在 Java 完全是菜鸟,如果这是菜鸟的错误,我深表歉意。
我正在尝试 Java NIO,我还没有达到使用非阻塞功能的阶段。我只是无法让服务器读取字符串,我知道从一侧发送字节缓冲区并试图在另一侧将其解释为字符串并不容易,但我仍然无法弄清楚我要去哪里错误的。这是代码
******************************服务器端*************** ************************
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
Client --> String --> UTF-8 字节数组 --> ByteBuffer -->Write
因为我将字节数组显式编码为 UTF-8。为什么 readUTF 无法读取?
您需要编写 DataInputStream 期望的格式。
例如
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 会将 [=11=]
作为两个字节而不是一个字节写入,而 readUTF 会将其作为 1 或 2 个字节接受。
DataInput.readUTF
方法不读取UTF-8编码的字符串,它读取DataOutput.writeUTF
创建的特定格式的数据,即与真正的 UTF-8 相似但不相同:
- 它以 16 位无符号整数开头,给出构成字符串的后续字节数
- 后面这些字节是UTF-8的修改形式,其中U+0000用两个字节表示而不是1(所以字符串的二进制表示不能包含任何0字节)和U+FFFF以上的增补字符表示为代理对,高代理和低代理分别以 3 个字节编码为 UTF-8(真正的 UTF-8 将使用总共四个字节一次性编码整个补充代码点)。
如果您正在编写真正的 UTF-8,那么您需要阅读真正的 UTF-8,如果您想要 readUTF
,那么您必须 writeUTF
。
如果你想 writeUTF
到 ByteBuffer
,那么在缓冲区周围实现一个 OutputStream
包装器非常简单,你可以反过来将其包装在 DataOutputStream
:
class ByteBufferBackedOutputStream extends OutputStream{
ByteBuffer buf;
ByteBufferBackedOutputStream( ByteBuffer buf){
this.buf = buf;
}
public synchronized void write(int b) throws IOException {
buf.put((byte) b);
}
public synchronized void write(byte[] bytes, int off, int len) throws IOException {
buf.put(bytes, off, len);
}
}
(source)
我在 Java 完全是菜鸟,如果这是菜鸟的错误,我深表歉意。 我正在尝试 Java NIO,我还没有达到使用非阻塞功能的阶段。我只是无法让服务器读取字符串,我知道从一侧发送字节缓冲区并试图在另一侧将其解释为字符串并不容易,但我仍然无法弄清楚我要去哪里错误的。这是代码
******************************服务器端*************** ************************
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
Client --> String --> UTF-8 字节数组 --> ByteBuffer -->Write
因为我将字节数组显式编码为 UTF-8。为什么 readUTF 无法读取?
您需要编写 DataInputStream 期望的格式。
例如
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 会将 [=11=]
作为两个字节而不是一个字节写入,而 readUTF 会将其作为 1 或 2 个字节接受。
DataInput.readUTF
方法不读取UTF-8编码的字符串,它读取DataOutput.writeUTF
创建的特定格式的数据,即与真正的 UTF-8 相似但不相同:
- 它以 16 位无符号整数开头,给出构成字符串的后续字节数
- 后面这些字节是UTF-8的修改形式,其中U+0000用两个字节表示而不是1(所以字符串的二进制表示不能包含任何0字节)和U+FFFF以上的增补字符表示为代理对,高代理和低代理分别以 3 个字节编码为 UTF-8(真正的 UTF-8 将使用总共四个字节一次性编码整个补充代码点)。
如果您正在编写真正的 UTF-8,那么您需要阅读真正的 UTF-8,如果您想要 readUTF
,那么您必须 writeUTF
。
如果你想 writeUTF
到 ByteBuffer
,那么在缓冲区周围实现一个 OutputStream
包装器非常简单,你可以反过来将其包装在 DataOutputStream
:
class ByteBufferBackedOutputStream extends OutputStream{
ByteBuffer buf;
ByteBufferBackedOutputStream( ByteBuffer buf){
this.buf = buf;
}
public synchronized void write(int b) throws IOException {
buf.put((byte) b);
}
public synchronized void write(byte[] bytes, int off, int len) throws IOException {
buf.put(bytes, off, len);
}
}
(source)