简体   繁体   English

如何在Java中将布尔数组转换为二进制,反之亦然?

[英]How to convert boolean array to binary and vice versa in Java?

What is the most efficient way to output a boolean array to (and input from) a file in Java? 在Java中向布局数据输出(和输入)的最有效方法是什么? I was going to use a string with each character being either 't' or 'f' and then I thought, why not take eight time less space? 我打算用一个字符串,每个字符都是't'或'f'然后我想,为什么不减少8倍的空间?

NOTE 注意

I actually have no idea which answer is the better method, I've just chosen Peter's because I understand it. 我实际上不知道哪个答案是更好的方法,我刚刚选择了彼得,因为我理解它。 Thanks to both answerers! 感谢两位回答者!

Say you have a boolean[] 假设你有一个布尔[]

boolean[] ar = {true,false,false,true,false,true,true,true,false,true,false,false,false,true,tr‌​ue};

and you want to write this to a disk, and you don't care how its is implemented in memory. 并且您想将其写入磁盘,而不关心它在内存中的实现方式。

public static void main(String... args) throws IOException {
    boolean[] ar = {true, false, false, true, false, true, true, true, false, true, false, false, false, true, true};

    FileOutputStream out = new FileOutputStream("test.dat");
    writeBooleans(out, ar);
    out.close();

    FileInputStream in = new FileInputStream("test.dat");
    boolean[] ar2 = new boolean[ar.length]; 
    readBooleans(in, ar2);
    in.close();

    System.out.println(Arrays.toString(ar));
    System.out.println(Arrays.toString(ar2));
    System.out.println("The file size was "+new File("test.dat").length()+" bytes.");
}

private static void writeBooleans(OutputStream out, boolean[] ar) throws IOException {
    for (int i = 0; i < ar.length; i += 8) {
        int b = 0;
        for (int j = Math.min(i + 7, ar.length-1); j >= i; j--) {
            b = (b << 1) | (ar[j] ? 1 : 0);
        }
        out.write(b);
    }
}

private static void readBooleans(InputStream in, boolean[] ar) throws IOException {
    for (int i = 0; i < ar.length; i += 8) {
        int b = in.read();
        if (b < 0) throw new EOFException();
        for (int j = i; j < i + 8 && j < ar.length; j++) {
            ar[j] = (b & 1) != 0;
            b >>>= 1;
        }
    }
}

prints 版画

[true, false, false, true, false, true, true, true, false, true, false, false, false, true, true]
[true, false, false, true, false, true, true, true, false, true, false, false, false, true, true]
The file size was 2 bytes.

but if I look at how big the file actually is 但如果我看看文件实际有多大

$ ls -l test.dat
-rw-rw-r-- 1 peter peter 2 2012-02-19 14:04 test.dat
$ du -h test.dat 
4.0K    test.dat

It says the length is 2 bytes, but the disk space used is actually 4 KB. 它表示长度为2个字节,但使用的磁盘空间实际为4 KB。

Note: About 1 minute of your time is worth about the same as 80 MB of SSD (expensive disk, more for HDD) So if you don't think you will be saving at least 80 MB by using this, you could be wasting your time. 注意:大约1分钟的时间值与80 MB的SSD大致相同(昂贵的磁盘,更多用于硬盘驱动器)因此,如果你不认为使用它可以节省至少80 MB,你可能会浪费你的时间。 ;) ;)


You can use BitSet, which can take 16x less space as each character is 16-bit. 您可以使用BitSet,每个字符为16位,占用的空间可减少16倍。

Newly created, just for you. 新创造的,适合您。 I'll leave the BooleanInputStream as an excercise. 我将把BooleanInputStream作为一个BooleanInputStream Note that the first bit is now the rightmost (MSB) bit in the file (remove Byte.SIZE - 1 - in the example for other byte order, whatever you prefer). 请注意,第一位现在是文件中最右边的(MSB)位(删除Byte.SIZE - 1 -在其他字节顺序的示例中,无论您喜欢什么)。 Simply use eg DataOutputStream to write the size of the thing to file first. 只需使用例如DataOutputStream来首先将文件的大小写入文件。 10K should fit in an integer. 10K应该是一个整数。

Note that storing a boolean array of 10K elements is very inefficient memory wise, you certainly should use BitSet for that (finally, somebody who needs BitSet )! 请注意,存储10K元素的布尔数组是非常低效的内存,你当然应该使用BitSet (最后,需要BitSet )!

public final class BooleanOutputStream extends FilterOutputStream {

    private int bitIndex;
    private byte buffer;

    public BooleanOutputStream(final OutputStream out) {
        super(out);
    }

    public void writeBoolean(final boolean value) throws IOException {
        buffer ^= (value ? 1 : 0) << (Byte.SIZE - 1 - bitIndex++);
        if (bitIndex == Byte.SIZE) {
            write(buffer & 0xFF);
            buffer = 0;
            bitIndex = 0;
        }
    }

    /**
     * This is an encoder and does therefore not close the underlying stream.
     * Please close underlying stream separately.
     */
    public void close() throws IOException {
        if (bitIndex != 0) {
            out.write(buffer);
            buffer = 0;
            bitIndex = 0;
        }
    }
}

public class BooleanInputStream extends FilterInputStream {

    private int bitIndex;
    private byte buffer;

    public BooleanInputStream(final InputStream in) {
        super(in);
    }

    public boolean readBoolean() throws IOException {
        if (bitIndex == 0) {
            int b = read();
            if (b == -1) {
                throw new EOFException();
            }
            buffer = (byte) b;
        }

        boolean value = (buffer & (1 << (Byte.SIZE - 1 - bitIndex++))) != 0;
        if (bitIndex == Byte.SIZE) {
            bitIndex = 0;
        }
        return value;
    }

    /**
     * This is a decoder and therefore does not close the underlying stream.
     * Please close underlying stream separately.
     */    
    public void close() throws IOException {
        buffer = 0;
        bitIndex = 0;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM