Общая инкапсуляция байтов Java

Java

christmas.jpg

1. Java-байты

Байт (байт) — это основной тип данных в Java, байт содержит 8 бит (битов), а диапазон значений байта — от -128 до +127.

Связь между byte и другими базовыми типами в Java:

базовый тип Занятые байты Примечание
byte 1
short 2
int 4
long 8
char 2
float 4
double 8
boolean 1, 4 «Спецификация виртуальной машины Java» дает определение 4 байта и 1 байта логического массива в зависимости от того, реализована ли виртуальная машина в соответствии со спецификацией.

2. Часто используемые пакеты

Из-за рабочих отношений я инкапсулировал библиотеку, которая манипулирует байтами.

адрес гитхаба:GitHub.com/Zonda71…

2.1 Особенности байткита:

  • Поддерживает несколько способов создания байтов
  • Поддерживает операции с байтовыми массивами и байтовыми буферами.
  • Поддержка неизменяемых объектов: ByteArrayBytes, ByteBufferBytes.
  • Поддержка Transformer: встроенная копия, контакт, реверс, xor и, или нет, также поддерживает пользовательский Transformer
  • Поддержка хэша: встроенный md5, sha1, sha256
  • Поддержка преобразования в шестнадцатеричную строку
  • Поддержка общих операций чтения и записи mmap: readByte/writeByte, readBytes/writeBytes, readInt/writeInt, readLong/writeLong, readDouble/writeDouble, readObject/writeObject
  • Поддержка сериализации объектов, десериализации, глубокого копирования
  • Не зависит ни от какой сторонней библиотеки

bytes.png

Bytes — это интерфейс с тремя классами реализации: ByteArrayBytes, ByteBufferBytes и MmapBytes. Среди них первые два класса реализации являются объектами Immutable.

2.2 Поддержка неизменяемых объектов

Неизменяемые объекты (неизменяемые объекты), то есть после того, как объект создан, его состояние (данные объекта, то есть значение свойств объекта) не может быть изменено.

Его преимущества:

  • Простота сборки, тестирования и использования
  • потокобезопасность
  • Защитное копирование не требуется при использовании в качестве свойства класса
  • Хорошо работает с клавишами карты и элементами набора

2.3 Поддержка хэш-шифрования

Зашифровать byte[] в байтах. В интерфейс Bytes включены следующие функции по умолчанию:

    /**
     * 使用md5加密
     * @return
     */
    default Bytes md5() {

        return transform(new MessageDigestTransformer("MD5"));
    }

    /**
     * 使用sha1加密
     * @return
     */
    default Bytes sha1() {

        return transform(new MessageDigestTransformer("SHA-1"));
    }

    /**
     * 使用sha256加密
     * @return
     */
    default Bytes sha256() {

        return transform(new MessageDigestTransformer("SHA-256"));
    }

Для модульного теста:

    @Test
    public void testHash() {

        Bytes bytes = ByteArrayBytes.create("hello world");

        assertEquals("5eb63bbbe01eeed093cb22bb8f5acdc3", bytes.md5().toHexString());
        assertEquals("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", bytes.sha1().toHexString());
        assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9", bytes.sha256().toHexString());
    }

2.4 Сериализация, десериализация, глубокая копия

Поддерживает сериализацию, десериализацию и глубокое копирование объектов. В интерфейс Bytes включены следующие статические функции:

    /**
     * 序列化对象,转换成字节数组
     * @param obj
     * @return
     */
    static byte[] serialize(Object obj) {
        byte[] result = null;
        ByteArrayOutputStream fos = null;

        try {
            fos = new ByteArrayOutputStream();
            ObjectOutputStream o = new ObjectOutputStream(fos);
            o.writeObject(obj);
            result = fos.toByteArray();
        } catch (IOException e) {
            System.err.println(e);
        } finally {

            IOUtils.closeQuietly(fos);
        }

        return result;
    }

    /**
     * 反序列化字节数字,转换成对象
     * @param bytes
     * @return
     */
    static Object deserialize(byte[] bytes) {
        InputStream fis = null;

        try {
            fis = new ByteArrayInputStream(bytes);
            ObjectInputStream o = new ObjectInputStream(fis);
            return o.readObject();
        } catch (IOException e) {
            System.err.println(e);
        } catch (ClassNotFoundException e) {
            System.err.println(e);
        } finally {

            IOUtils.closeQuietly(fis);
        }

        return null;
    }

    /**
     * 通过序列化/反序列化实现对象的深拷贝
     * @param obj
     * @param <T>
     * @return
     */
    static <T> T cloneObject(T obj) {
        
        return (T) deserialize(serialize(obj));
    }

Для модульного теста:

    @Test
    public void testSerializeAndDeserialize() {

        User u = new User();
        u.name = "tony";
        u.password = "123456";

        byte[] bytes = Bytes.serialize(u);

        User newUser = (User)Bytes.deserialize(bytes);
        assertEquals(u.name, newUser.name);
        assertEquals(u.password,newUser.password);
    }

    @Test
    public void testDeepCopy() {

        User u = new User();
        u.name = "tony";
        u.password = "123456";

        User newUser = Bytes.cloneObject(u);
        System.out.println(u);
        System.out.println(newUser);
        assertNotSame(u,newUser);
        assertNotSame(u.name,newUser.name);
    }

После выполнения testDeepCopy() адреса u и newUser отличаются,u.nameиnewUser.nameАдреса памяти, на которые указывают, также отличаются.

com.safframework.bytekit.domain.User@2b05039f
com.safframework.bytekit.domain.User@17d10166

2.5 копия, контакт, реверс

копирование, контакт, реверс - все это использует Transformer. В класс AbstractBytes включите следующие функции:

    @Override
    public Bytes copy() {

        return transform(new CopyTransformer(0, size()));
    }

    @Override
    public Bytes copy(int offset, int length) {

        return transform(new CopyTransformer(offset, length));
    }

    @Override
    public Bytes contact(byte[] bytes) {

        return transform(new ConcatTransformer(bytes));
    }

    @Override
    public Bytes reverse() {

        return transform(new ReverseTransformer());
    }

Для модульного теста:

    @Test
    public void testContact() {

        Bytes bytes = ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        assertEquals(bytes.toString(), "hello world tony");
    }

    @Test
    public void testCopy() {

        Bytes bytes = ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        assertEquals(bytes.toString(), bytes.copy().toString());
    }

    @Test
    public void testReverse() {

        Bytes bytes = ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        assertEquals(bytes.toString(), bytes.reverse().reverse().toString());
    }

2.6 Битовые манипуляции

xor и, или, не также являются способами использования Transformer. В класс AbstractBytes включите следующие функции:

    @Override
    public Bytes xor(byte[] bytes) {

        return transform(new BitWiseOperatorTransformer(bytes,BitWiseOperatorTransformer.Mode.XOR));
    }

    @Override
    public Bytes and(byte[] bytes) {

        return transform(new BitWiseOperatorTransformer(bytes, BitWiseOperatorTransformer.Mode.AND));
    }

    @Override
    public Bytes or(byte[] bytes) {

        return transform(new BitWiseOperatorTransformer(bytes, BitWiseOperatorTransformer.Mode.OR));
    }

    @Override
    public Bytes not(byte[] bytes) {

        return transform(new BitWiseOperatorTransformer(bytes, BitWiseOperatorTransformer.Mode.NOT));
    }

Для модульного теста:

    @Test
    public void testBitWise() {

        ByteBufferBytes bytes = (ByteBufferBytes)ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        assertEquals(bytes.toString(), bytes.and(bytes.toByteArray()).or(bytes.toByteArray()).toString());
        assertEquals(bytes.toString(), bytes.not(bytes.toByteArray()).not(bytes.toByteArray()).toString());
        assertEquals(bytes.toString(), bytes.xor(bytes.toByteArray()).xor(bytes.toByteArray()).toString()); //两次xor 返回本身
    }

2.7 Кодирование и декодирование Base64

    @Test
    public void testBase64() {

        ByteBufferBytes bytes = (ByteBufferBytes)ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        String base64 = new String(bytes.encodeBase64());
        assertEquals(bytes.toString(), new String(Bytes.parseBase64(base64)));
    }

2.8 Байты преобразованы в массив байтов

    @Test
    public void testToByteArray() {

        Bytes bytes = ByteBufferBytes.create("hello world").contact(" tony".getBytes());

        assertEquals(bytes.toString(), new String(bytes.toByteArray()));
    }

3. Работа с ммап

mmap в Linux — это способ отображения файлов памяти.

mmap сопоставляет файл или другой объект с памятью. Файл отображается на нескольких страницах. Если размер файла не является суммой размеров всех страниц, неиспользуемое пространство последней страницы будет обнулено. mmap очень полезен в системе вызовов отображения пользовательского пространства. Системный вызов mmap предназначен для сопоставления открытого файла с пользовательским пространством процесса.Системный вызов mmap позволяет процессам совместно использовать память, отображая один и тот же обычный файл. После того, как обычный файл отображается в адресное пространство процесса, процесс может получить доступ к файлу, как если бы он обращался к обычной памяти, без вызова read(), write() и других операций.

import com.safframework.bytekit.domain.User;
import com.safframework.bytekit.jdk.mmap.MmapBytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static junit.framework.TestCase.assertEquals;

/**
 * Created by tony on 2018-12-24.
 */
public class MmapBytesTest {

    private MmapBytes mmapBytes;
    private String file;

    @Before
    public void setUp() {

        file = "test";
        mmapBytes = new MmapBytes(file, (long) 1024 * 10); // 10M
    }

    @Test
    public void testWriteAndRead() throws Exception {

        mmapBytes.writeInt(12);
        mmapBytes.writeInt(34);
        mmapBytes.writeByte((byte) 5);
        mmapBytes.writeBytes(("this is tony").getBytes());
        mmapBytes.writeLong(6666L);
        mmapBytes.writeDouble(3.14d);

        assertEquals(12, mmapBytes.readInt());
        assertEquals(34, mmapBytes.readInt());
        assertEquals((byte) 5, mmapBytes.readByte());
        assertEquals("this is tony", new String(mmapBytes.readBytes(12)));
        assertEquals(6666L, mmapBytes.readLong());
        assertEquals(3.14d, mmapBytes.readDouble());
    }

    @Test
    public void testObject() throws Exception {

        User u = new User();
        u.name = "tony";
        u.password = "123456";

        mmapBytes.writeObject(u);

        User temp = (User)mmapBytes.readObject(117);

        assertEquals(u.name, temp.name);
        assertEquals(u.password, temp.password);
    }

    @Test
    public void testFree() throws Exception {

        mmapBytes.writeInt(12);
        mmapBytes.writeInt(34);
        mmapBytes.writeByte((byte) 5);

        mmapBytes.free();

        mmapBytes = new MmapBytes(file, (long) 1024 * 10); // 10M
        mmapBytes.writeInt(67);

        assertEquals(67, mmapBytes.readInt());
    }

    @After
    public void tearDown() {
        mmapBytes.free();
    }
}

4. Резюме

bytekitЭто библиотека инструментов для манипулирования байтами, которая не зависит ни от какой сторонней библиотеки. Он инкапсулирует работу массива байтов и ByteBuffer и поддерживает чтение и запись, обычно используемые mmap.

Конечно, он также может инкапсулировать ByteString protobuf или Parcel в Android, просто реализовав интерфейс Bytes.

Использованная литература:

  1. Вы действительно знаете, сколько байтов занимает логический тип в Java?

Стек технологий Java и Android: еженедельно обновляйте и публикуйте оригинальные технические статьи, добро пожаловать, чтобы отсканировать QR-код общедоступной учетной записи ниже и подписаться, и с нетерпением ждем роста и развития вместе с вами.