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
解决方案
原代码存在几个核心问题:
- BigInteger字节顺序错误:
BigInteger(byte[])会将数组视为大端有符号整数,而AD的loginHours是按无符号字节、从左到右对应周日到周六的顺序存储,直接使用会导致bit位顺序完全颠倒。 - 小时循环范围错误:一天只有24小时(0-23),原代码循环到24会多处理一个无效小时。
- 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); } }
代码说明
- 输入验证:先检查数组长度是否为21,避免无效输入。
- 星期对应关系:AD的
loginHours前3字节对应周日,依次到最后3字节对应周六,和DateFormatSymbols的星期名称索引1-7完全匹配。 - 字节与bit映射:
- 每个天的3字节分别对应小时0-7、8-15、16-23
- 每个字节的
bit0对应该组的第1个小时,bit7对应第8个小时 - 通过
byteValue & 0xFF将字节转为无符号整数,解决Java中byte默认带符号的问题
- 位运算判断:通过右移和按位与操作,精准提取对应bit的值,判断是否允许登录。
内容的提问来源于stack exchange,提问作者ironmanAJ
相关产品推荐
相关产品推荐

