Pérdida de datos causada por la longitud de bytes chinos

Recientemente estoy escribiendo un proyecto de monitoreo de aplicaciones, usando netty como transmisión de datos. Como recién comencé a escribir, no usé Protobuf como herramienta de codificación, solo usé la propia de Netty LengthFieldBasedFrameDecodercomo herramienta de análisis de mensajes para personalizar las clases de codificación y decodificación para realizar la transmisión de datos.

Todo fue normal, como resultado, durante la prueba de ayer, el cuerpo de datos transmitido fue siempre de 16 caracteres menos, lo cual fue muy extraño.

Revisé el problema una y otra vez, y luego revisé cuidadosamente el contenido del mensaje, solo para encontrar que había 8 caracteres chinos en el mensaje. Solo entonces pensé que la longitud de bytes chinos no se puede obtener usando java.lang.Stringun length()método. Lo que debe usarse es el getBytes()método para convertir en una matriz de bytes y lengthobtener la longitud a través de los atributos de la matriz .

tal como:

"abcd".length()El resultado es:
"abcd".getBytes().lengthel resultado de 4 es: el resultado de 4 es:
"中国威武".length()el resultado de 4 es:
"中国威武".getBytes().lengthel resultado de 12 es:
"中国v5".length()el resultado de 4
"中国v5".getBytes().lengthes: 8

El ejemplo es simple, pero también puede ilustrar el problema. Aquí, la longitud de cada byte chino es 3 y las letras, números y puntuación en inglés son 1.

Entonces, en mi código de prueba, length()la longitud de los 8 caracteres chinos obtenidos con el método es 8, que es getBytes()16 menos que la longitud de la matriz de bytes del método, por lo que siempre faltan 16 caracteres durante el proceso de transmisión (la longitud del carácter en inglés es 1).

En general, debe prestar atención al convertir bytes a chino y no lo dé por sentado length(). Todavía tengo que probar más según la situación específica. Triven marca este error

Adjunta el siguiente código:

Codificador: MessageEncoder

import cn.howardliu.monitor.cynomys.net.struct.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.CharsetUtil;

public class MessageEncoder extends MessageToByteEncoder<Message> {
    
    
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
    
    
        if (msg == null || msg.getHeader() == null) {
    
    
            throw new IllegalArgumentException("the encode message is null.");
        }
        out.writeInt(msg.getHeader().getCrcCode());
        out.writeInt(msg.getHeader().getLength());
        out.writeInt(msg.getHeader().getOpaque());

        out.writeInt(msg.getHeader().getTag().length());
        out.writeCharSequence(msg.getHeader().getTag(), CharsetUtil.UTF_8);

        out.writeInt(msg.getHeader().getSysName().length());
        out.writeCharSequence(msg.getHeader().getSysName(), CharsetUtil.UTF_8);

        out.writeInt(msg.getHeader().getSysCode().length());
        out.writeCharSequence(msg.getHeader().getSysCode(), CharsetUtil.UTF_8);

        out.writeByte(msg.getHeader().getType());
        out.writeByte(msg.getHeader().getCode());
        out.writeByte(msg.getHeader().getFlagPath());

        if (msg.getBody() == null) {
    
    
            out.writeInt(0);
        } else {
    
    
            out.writeInt(msg.getBody().getBytes().length);
            out.writeCharSequence(msg.getBody(), CharsetUtil.UTF_8);
        }
        out.setInt(4, out.readableBytes() - 8);
    }
}

Decodificador: MessageDecoder

import cn.howardliu.monitor.cynomys.net.struct.Header;
import cn.howardliu.monitor.cynomys.net.struct.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.util.CharsetUtil;

public class MessageDecoder extends LengthFieldBasedFrameDecoder {
    
    
    public MessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
    
    
        super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    
    
        ByteBuf frame = (ByteBuf) super.decode(ctx, in);
        if (frame == null) {
    
    
            return null;
        }
        Message message = new Message()
                .setHeader(
                        new Header()
                                .setCrcCode(frame.readInt())
                                .setLength(frame.readInt())
                                .setOpaque(frame.readInt())
                                .setTag(frame.readCharSequence(frame.readInt(), CharsetUtil.UTF_8).toString())
                                .setSysName(frame.readCharSequence(frame.readInt(), CharsetUtil.UTF_8).toString())
                                .setSysCode(frame.readCharSequence(frame.readInt(), CharsetUtil.UTF_8).toString())
                                .setType(frame.readByte())
                                .setCode(frame.readByte())
                                .setFlagPath(frame.readByte())
                );
        if (frame.readableBytes() > 4) {
    
    
            message.setBody(frame.readCharSequence(frame.readInt(), CharsetUtil.UTF_8).toString());
        }
        return message;
    }
}

La forma en que se usa el decodificador es new MessageDecoder(1024 * 1024 * 100, 4, 4).

Pega descaradamente la dirección de este proyecto, bienvenido estrella, fork y Tucao:


Página de inicio personal: http://www.howardliu.cn

Publicación de blog personal: pérdida de datos causada por la longitud de bytes chinos

Página de inicio de CSDN: http://blog.csdn.net/liuxinghao

Publicación de blog de CSDN: pérdida de datos causada por la longitud del byte chino

Supongo que te gusta

Origin blog.csdn.net/conansix/article/details/77717976
Recomendado
Clasificación