You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现将字节数组转换为Active Directory登录时间布尔表

问题描述

我正在处理Active Directory相关工作,用户登录时间以布尔表形式存储(对应get_loginHours方法)。获取到的是一个长度为21的byte数组:

  • 每3字节对应一天的登录权限
  • 1字节包含8个bit,bit为0表示拒绝登录,bit为1表示允许登录
  • 3字节共24位,对应一天24小时

我需要通过该数组检查7天共168位的登录权限,但不知道如何将字节数组转换为bit并校验。之前尝试的代码无效,代码如下:

public static void displayHours(byte[] hours) {
        final String[] DAYS = DateFormatSymbols.getInstance().getWeekdays();    
        BigInteger bi = new BigInteger(hours);
        
        for (int day = 1; day <= 7; day++) {
            System.out.printf("Hours allowed for %s%n", DAYS[day]);
            for (int hour = 0; hour <= 24; hour++) {
                int bit = day * 7 + hour;
                boolean allowed = bi.testBit(bit);
                System.out.printf("\tLogin permitted for hour %d?: %b%n", hour, allowed);
            }
        }
    }

字节数组输出示例:-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-10-1


解决方案

原代码存在几个核心问题:

  1. BigInteger字节顺序错误:BigInteger(byte[])会将数组视为大端有符号整数,而AD的loginHours是按无符号字节、从左到右对应周日到周六的顺序存储,直接使用会导致bit位顺序完全颠倒。
  2. 小时循环范围错误:一天只有24小时(0-23),原代码循环到24会多处理一个无效小时。
  3. bit位计算逻辑错误:原代码的day *7 + hour完全不符合AD的存储规则。

以下是正确的实现函数:

import java.text.DateFormatSymbols;

public class ADLoginHoursParser {
    public static void displayLoginHours(byte[] loginHours) {
        // 验证输入数组长度:必须是21字节(7天×3字节/天)
        if (loginHours == null || loginHours.length != 21) {
            System.err.println("无效的loginHours数组:必须为21字节长度");
            return;
        }

        // 获取星期名称:索引1=周日,2=周一...7=周六,对应AD的存储顺序
        final String[] WEEKDAYS = DateFormatSymbols.getInstance().getWeekdays();

        // 遍历7天:0=周日,1=周一...6=周六
        for (int dayIndex = 0; dayIndex < 7; dayIndex++) {
            String dayName = WEEKDAYS[dayIndex + 1];
            System.out.printf("允许登录时段:%s%n", dayName);

            // 当前天的起始字节索引:每3字节对应一天
            int startByteIndex = dayIndex * 3;

            // 遍历当天24小时(0-23)
            for (int hour = 0; hour < 24; hour++) {
                // 计算当前小时所在的字节偏移:每字节对应8小时
                int byteOffset = hour / 8;
                int currentByteIndex = startByteIndex + byteOffset;

                // 计算当前小时对应的bit位:每字节的bit0对应该字节的第1个小时
                int bitPosition = hour % 8;

                // 将byte转为无符号int,避免负数干扰
                int byteValue = loginHours[currentByteIndex] & 0xFF;

                // 检查对应bit是否为1(允许登录)
                boolean isAllowed = (byteValue >> bitPosition & 1) == 1;

                System.out.printf("\t%d点:%s%n", hour, isAllowed ? "允许登录" : "拒绝登录");
            }
        }
    }

    // 测试示例
    public static void main(String[] args) {
        // 模拟用户提供的字节数组(补全为21个字节)
        byte[] testHours = {
                -1, -1, -1, -1, -1, -1, -1, -1, -1,
                -1, -1, -1, -1, -1, -1, -1, -1, -1,
                10, -1, -1
        };
        displayLoginHours(testHours);
    }
}

代码说明

  1. 输入验证:先检查数组长度是否为21,避免无效输入。
  2. 星期对应关系:AD的loginHours前3字节对应周日,依次到最后3字节对应周六,和DateFormatSymbols的星期名称索引1-7完全匹配。
  3. 字节与bit映射:
    • 每个天的3字节分别对应小时0-7、8-15、16-23
    • 每个字节的bit0对应该组的第1个小时,bit7对应第8个小时
    • 通过byteValue & 0xFF将字节转为无符号整数,解决Java中byte默认带符号的问题
  4. 位运算判断:通过右移和按位与操作,精准提取对应bit的值,判断是否允许登录。

内容的提问来源于stack exchange,提问作者ironmanAJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:15:32