MySQL通信协议栈Java实现-(1)数据类型

最新官网MySQL通信协议栈说明地址:http://dev.mysql.com/doc/internals/en/client-server-protocol.html

1. 数据类型

1.1 整型

1.1.1 定长整型

定长整型最小位在最前,一共有如下几种定长整型:

int<1>
int<2>
int<3>
int<4>
int<6>
int<8>

例如:int<3>表示1为:

01 00 00
1.1.2 长度编码整型
int<lenenc>

根据长度不同,长度编码整型有不同的编码:
如果值<251,则存储为1字节整型
如果值≥251并<2^16,则存储为以0xfc开头+2字节整型
如果值≥2^16并<2^24,则存储为以0xfd开头+3字节整型
如果值≥2^24并<2^64,则存储为以0xfe开头+8字节整型
举例:

fa       -- 250
fc fb 00 -- 251
1.1.3 实现

Int.java:

package io.timberwolf.net.protocols.mysql.data;

import com.google.common.base.Preconditions;

import java.nio.ByteBuffer;

/**
 * MySQL protocol DataType - Integer Types
 *
 * @author Hash Zhang
 * @version 0.0.0
 * @see @http://dev.mysql.com/doc/internals/en/integer.html
 */
public class Int {
    //定长整型数据编码解码
    public static int writeLength1(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x100);
        buffer.put((byte) num);
        return 1;
    }

    public static int readLength1(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        return (int) buffer.get();
    }

    public static int writeLength2(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x10000);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        return 2;
    }

    public static int readLength2(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        int result = (int) buffer.get();
        result += ((int) buffer.get()) << 8;
        return result;
    }

    public static int writeLength3(ByteBuffer buffer, int num) {
        Preconditions.checkArgument(num < 0x1000000);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        return 3;
    }

    public static int readLength3(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        int result = (int) buffer.get();
        result += ((int) buffer.get()) << 8;
        result += ((int) buffer.get()) << 16;
        return result;
    }

    public static int writeLength4(ByteBuffer buffer, long num) {
        Preconditions.checkArgument(num < 0x100000000L);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        return 4;
    }

    public static long readLength4(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        return result;
    }

    public static int wrietLength6(ByteBuffer buffer, long num) {
        Preconditions.checkArgument(num <= 0x1000000000000L);
        buffer.put((byte) (num));
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        buffer.put((byte) (num >>> 32));
        buffer.put((byte) (num >>> 40));
        return 6;
    }

    public static long readLength6(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        result += ((long) buffer.get()) << 32;
        result += ((long) buffer.get()) << 40;
        return result;
    }

    public static int writeLength8(ByteBuffer buffer, long num) {
        buffer.put((byte) num);
        buffer.put((byte) (num >>> 8));
        buffer.put((byte) (num >>> 16));
        buffer.put((byte) (num >>> 24));
        buffer.put((byte) (num >>> 32));
        buffer.put((byte) (num >>> 40));
        buffer.put((byte) (num >>> 48));
        buffer.put((byte) (num >>> 56));
        return 8;
    }

    public static long readLength8(ByteBuffer buffer) {
        Preconditions.checkNotNull(buffer);
        long result = (long) buffer.get();
        result += ((long) buffer.get()) << 8;
        result += ((long) buffer.get()) << 16;
        result += ((long) buffer.get()) << 24;
        result += ((long) buffer.get()) << 32;
        result += ((long) buffer.get()) << 40;
        result += ((long) buffer.get()) << 48;
        result += ((long) buffer.get()) << 56;
        return result;
    }

    //长度编码整型数据编码解码
    public static int writeLengthEncoded(ByteBuffer buffer, long num) {
        if (num < 0xfb) {
            writeLength1(buffer, (int) num);
            return 1;
        } else if (num < 0x10000) {
            buffer.put((byte) 0xfc);
            writeLength2(buffer, (int) num);
            return 3;
        } else if (num < 0x10000) {
            buffer.put((byte) 0xfd);
            writeLength3(buffer, (int) num);
            return 4;
        } else {
            buffer.put((byte) 0xfe);
            writeLength8(buffer, num);
            return 9;
        }
    }

    public static long readLengthEncoded(ByteBuffer buffer) {
        int num = readLength1(buffer);
        long result = 0;
        if(num < 0xfb){
            result += num;
        } else if(num == 0xfc){
            result += readLength2(buffer);
        } else if(num == 0xfd){
            result += readLength3(buffer);
        } else{
            result +=readLength8(buffer);
        }
        return result;
    }
}


1.2 字符串类型

1.2.1定长字符串

定长字符串拥有已知的固定的长度

1.2.2null截止字符串

字符串用[00]字节截止

1.2.3变长字符串

字符串长度由另一域值决定

1.2.4长度编码字符串

长度编码整型+定长字符串(长度为前面整型代表的数值)

1.2.5剩余长度字符串

如果字符串是包最后一个元素,它的长度可以由包长度减去当前位置决定。

string<lenenc>  Protocol::LengthEncodedString
string<fix> Protocol::FixedLengthString
string<var> Protocol::VariableLengthString:
string<EOF> Protocol::RestOfPacketString
string<NUL> Protocol::NulTerminatedString
package io.timberwolf.net.protocols.mysql.data;

import com.google.common.base.Preconditions;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/**
 * MySQL protocol DataType - String Types
 *
 * @author Hash Zhang
 * @version 0.0.0
 * @see @http://dev.mysql.com/doc/internals/en/string.html
 */
public class Str {
    public static int lengthEncoded(ByteBuffer buffer, String string, String charSet) throws UnsupportedEncodingException {
        Preconditions.checkNotNull(string);
        int length = string.getBytes(charSet).length;
        length += Int.writeLengthEncoded(buffer,length);
        buffer.put(string.getBytes(charSet));
        return length;
    }
}

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值