Нет способа сделать это напрямую. Самая маленькая единица, которую компьютеры могут обрабатывать, - это байт (даже логические значения занимают байт). Однако вы можете создать собственный класс потока, который упаковывает байт с нужными битами, а затем записывает его. Затем вы можете сделать обертку для этого класса, функция записи которой принимает некоторый целочисленный тип, проверяет, что он находится между 0 и 7 (или -4 и 3 ... или что-то еще), извлекает биты таким же образом, как класс BitInputStream (ниже) делает и делает соответствующие вызовы метода записи BitOutputStream. Вы можете подумать, что вы могли бы просто сделать один набор классов потоков ввода-вывода, но 3 не входит в 8 равномерно. Так что, если вам нужна оптимальная эффективность хранения и вы не хотите работать усердно, вы застряли с двумя уровнями абстракции. Ниже приведен класс BitOutputStream, соответствующий класс BitInputStream и программа, обеспечивающая их работу.
import java.io.IOException;
import java.io.OutputStream;
class BitOutputStream {
private OutputStream out;
private boolean[] buffer = new boolean[8];
private int count = 0;
public BitOutputStream(OutputStream out) {
this.out = out;
}
public void write(boolean x) throws IOException {
this.count++;
this.buffer[8-this.count] = x;
if (this.count == 8){
int num = 0;
for (int index = 0; index < 8; index++){
num = 2*num + (this.buffer[index] ? 1 : 0);
}
this.out.write(num - 128);
this.count = 0;
}
}
public void close() throws IOException {
int num = 0;
for (int index = 0; index < 8; index++){
num = 2*num + (this.buffer[index] ? 1 : 0);
}
this.out.write(num - 128);
this.out.close();
}
}
Я уверен, что есть способ упаковать int с помощью побитовых операторов и, таким образом, избежать необходимости переворачивать ввод, но я не думаю, что так сложно думать.
Кроме того, вы, вероятно, заметили, что нет локального способа определить, что последний бит был прочитан в этой реализации, но я действительно не хочу думать , что трудно .
import java.io.IOException;
import java.io.InputStream;
class BitInputStream {
private InputStream in;
private int num = 0;
private int count = 8;
public BitInputStream(InputStream in) {
this.in = in;
}
public boolean read() throws IOException {
if (this.count == 8){
this.num = this.in.read() + 128;
this.count = 0;
}
boolean x = (num%2 == 1);
num /= 2;
this.count++;
return x;
}
public void close() throws IOException {
this.in.close();
}
}
Возможно, вы это знаете, но вам следует поместить BufferedStream между вашим BitStream и FileStream, иначе это займет вечность.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
class Test {
private static final int n = 1000000;
public static void main(String[] args) throws IOException {
Random random = new Random();
//Generate array
long startTime = System.nanoTime();
boolean[] outputArray = new boolean[n];
for (int index = 0; index < n; index++){
outputArray[index] = random.nextBoolean();
}
System.out.println("Array generated in " + (double)(System.nanoTime() - startTime)/1000/1000/1000 + " seconds.");
//Write to file
startTime = System.nanoTime();
BitOutputStream fout = new BitOutputStream(new BufferedOutputStream(new FileOutputStream("booleans.bin")));
for (int index = 0; index < n; index++){
fout.write(outputArray[index]);
}
fout.close();
System.out.println("Array written to file in " + (double)(System.nanoTime() - startTime)/1000/1000/1000 + " seconds.");
//Read from file
startTime = System.nanoTime();
BitInputStream fin = new BitInputStream(new BufferedInputStream(new FileInputStream("booleans.bin")));
boolean[] inputArray = new boolean[n];
for (int index = 0; index < n; index++){
inputArray[index] = fin.read();
}
fin.close();
System.out.println("Array read from file in " + (double)(System.nanoTime() - startTime)/1000/1000/1000 + " seconds.");
//Delete file
new File("booleans.bin").delete();
//Check equality
boolean equal = true;
for (int index = 0; index < n; index++){
if (outputArray[index] != inputArray[index]){
equal = false;
break;
}
}
System.out.println("Input " + (equal ? "equals " : "doesn't equal ") + "output.");
}
}