java -- Big Endian and Little Endian 大端和小端概念讲解及如何转换

本文详细介绍了字节顺序的概念,包括大端和小端的定义。大端存储高阶字节在前,小端则相反。网络字节序通常使用大端。Java文件始终以大端存储,而C语言默认使用小端。可以通过ByteOrder.nativeOrder()检查系统的字节顺序,并使用ByteBuffer进行转换。字节顺序影响多字节数据类型的存储,如在某些文件格式中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是大端、小端?

字节是计算机中数据处理的基本单位。
计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。
计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(word)。一个字通常由一个或多个(一般是字节的整数位)字节构成。
但并非所有计算机都以相同的顺序存储由多字节值组成的字节。考虑一个由2个字节组成的16位因特网。存储该值有两种方式

  • Little Endian 小端: 低阶字节存储在起始地址(A),高阶字节存储在下一个地址(A + 1)
  • Big Endian 大端:高阶字节存储在起始地址(A),低阶字节存储在下一个地址(A + 1)

网络字节顺序: 为了允许具有不同字节顺序约定的计算机相互通信,Internet协议为在网络上传输的数据指定了规范的字节顺序约定。
network order 即网络序,默认网络传输字节为大端

小端和大端是存储多字节数据类型(int、float等)的两种方式

  • 计算机内存由正整数地址引用。在计算机内存中,把最低有效字节放在最高有效字节之前存储数字是“自然的”。
    “自然”顺序,即在内存中较低有效字节出现在较高有效字节之前。自然顺序是采用小端方式存储
    • 基于英特尔的处理器是小端。ARM处理器是小端处理器。
  • 但许多供应商,如IBM、CRAY和Sun,更喜欢采用相反的顺序存储数据,即采用大端方式存储。
  • 双端处理器可以在小端和大端两种模式下运行。当前的一代ARM处理器是双端处理器。

根据这些定义,一种32位数据模式,它被视为32位无符号整数。“高阶”字节是2的最大次方:231,…, 224。“低阶”字节是2的最小次方: 27,…, 20
示例如下:

  • MSB:全称为Most Significant Bit,在二进制数中属于最高有效位,MSB是最高加权位,与十进制数字中最左边的一位类似。
  • LSB:全称为Least Significant Bit,在二进制数中意为最低有效位,

一般来说,MSB位于二进制数的最左侧,LSB位于二进制数的最右侧。
在这里插入图片描述
在这里插入图片描述

字节顺序是否影响文件格式?

  • 以1字节为基本单位的文件格式独立于字节顺序,例如ASCII文件。
  • 其他文件格式使用一些固定的端顺序格式,例如JPEG文件以大端顺序格式存储。
  • java 全部为大端(与平台无关): Java二进制文件中的所有内容都以大端顺序存储。这意味着如果您只使用Java,那么所有文件在所有平台(Mac、PC、UNIX等)上的处理方式都是相同的。
  • C语言默认是小端模式:用C语言编写的程序通常使用 小端顺序

如何知道机器的字节次序

How to Know the Endian-ness?
在Java中,我们可以使用ByteOrder.nativeOrder()方法来获取CPU使用的字节顺序。在使用Intel CPU 或 AMD CPU时,输出结果都是小端顺序

ByteOrder byteOrder = ByteOrder.nativeOrder();

System.out.println(byteOrder);   //LITTLE_ENDIAN

如何进行大小端的转换

在java中,可以基于ByteBuffer提供的order方法,进行大小端的转换
如处理网络字节流时,先针对获取的byte[] 进行 buffer.order(ByteOrder.BIG_ENDIAN);

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class SimpleDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10);
        byteBuffer.put("Test".getBytes(StandardCharsets.UTF_8));
        byteBuffer.flip();
        System.out.println(Arrays.toString(convert(byteBuffer, ByteOrder.BIG_ENDIAN)));

        byteBuffer.flip();
        System.out.println(Arrays.toString(convert(byteBuffer, ByteOrder.LITTLE_ENDIAN)));
    }


    /**
     * 必须调用完后flip()才可以调用此方法
     * @param byteBuffer
     * @param bo
     * @return
     */
    public static byte[] convert(ByteBuffer byteBuffer, ByteOrder bo) {
        byteBuffer.order(bo);
        int len = byteBuffer.limit() - byteBuffer.position();
        byte[] bytes = new byte[len];

        if (byteBuffer.isReadOnly()) {
            return null;
        } else {
            byteBuffer.get(bytes);
        }
        return bytes;
    }

}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

enjoy编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值