Напишите побитовый файл в java [duplicate]

Еще одна вариация (работает ли она с IE?):

String.prototype.reverse = function() {
    for (i=1,s=""; i<=this.length; s+=this.substr(-i++,1)) {}
    return s;
}

EDIT:

Это без использования встроенных функций:

String.prototype.reverse = function() {
    for (i=this[-1],s=""; i>=0; s+=this[i--]) {}
    return s;
}

Примечание: этот [-1] содержит длину строки.

Однако невозможно изменить строку на месте, поскольку присвоение отдельным элементам массива не работает с объектом String (защищенный?). То есть вы можете назначать, но результирующая строка не изменяется.

5
задан Eternal Noob 19 November 2010 в 01:06
поделиться

9 ответов

Невозможно напрямую читать / записывать отдельные биты, наименьший блок, который вы можете читать / записывать, - это байт.

Вы можете использовать стандартные побитовые операторы для управления байт, так, например, для получения младших 2 бит байта вы бы

byte b = in.readByte();
byte lowBits = b&0x3;

устанавливали низкие 4 бита в 1 и записывали байт:

b |= 0xf;
out.writeByte(b);

(Примечание, ради эффективности вы можете читать / писать байтовые массивы, а не одиночные байты)

4
ответ дан nos 18 August 2018 в 01:02
поделиться
  • 1
    Кажется, мне придется читать / писать байты и изучать побитовые операции ... Спасибо всем за ответы .... – Eternal Noob 19 November 2010 в 01:11
  • 2
    Спасибо, нос, за пункт эффективности ... – Eternal Noob 19 November 2010 в 01:12
  • 3
    По верификации b и 0x3 не только сохраняются два младших значимых бита в младших битах? – user 2 April 2016 в 07:18
  • 4
    На самом деле я думаю, что это не решение, потому что вы не можете писать байт, когда просто хотите записать три бита (по запросу). Вам придется записывать бит до тех пор, пока по крайней мере один байт не будет заполнен. Эта часть отсутствует. – U. Windl 9 May 2018 в 09:07

Да и нет. На большинстве современных компьютеров байт является наименьшей адресной единицей памяти, поэтому вы можете читать и записывать только все байты за раз. Тем не менее, вы всегда можете использовать побитовые операторы для управления битами внутри байта.

2
ответ дан casablanca 18 August 2018 в 01:02
поделиться
  • 1
    Это сложнее, чем это (манипулировать битами в пределах одного байта). – U. Windl 9 May 2018 в 09:11

Нижеприведенный код должен работать

    int[] mynumbers = {3,4};
    BitSet compressedNumbers = new BitSet(mynumbers.length*3);
    // let's say you encoded 3 as 101 and 4 as 010
    String myNumbersAsBinaryString = "101010"; 
    for (int i = 0; i < myNumbersAsBinaryString.length(); i++) {
        if(myNumbersAsBinaryString.charAt(i) == '1')
            compressedNumbers.set(i);
    }
    String path = Resources.getResource("myfile.out").getPath();
    ObjectOutputStream outputStream = null;
    try {
        outputStream = new ObjectOutputStream(new FileOutputStream(path));
        outputStream.writeObject(compressedNumbers);
    } catch (IOException e) {
        e.printStackTrace();
    }
0
ответ дан cgl 18 August 2018 в 01:02
поделиться
  • 1
    В вашем решении просто используется BitSet вместо байта, но на самом деле не является решением проблемы. – U. Windl 9 May 2018 в 09:14

Afaik не существует функции для этого в Java API. Однако вы можете, конечно, прочитать байт, а затем использовать функции манипуляции бит. То же самое касается написания.

1
ответ дан Jan Thomä 18 August 2018 в 01:02
поделиться

Переместился на https://github.com/jinahya/bit-io

. Посмотрите на http://jinahya.googlecode.com/ svn / trunk / com.googlecode.jinahya / bit-io / src / main / java / com / googlecode / jinahya / io /

<dependency>
  <!-- resides in central repo -->
  <groupId>com.googlecode.jinahya</groupId>
  <artifactId>bit-io</artifactId>
  <version>1.0-alpha-13</version>
</dependency>

Это небольшая удобная библиотека для чтения / запись произвольной длины бит с помощью Java.

final InputStream stream;
final BitInput input = new BitInput(new BitInput.StreamInput(stream));

final int b = input.readBoolean(); // reads a 1-bit boolean value
final int i = input.readUnsignedInt(3); // reads a 3-bit unsigned int
final long l = input.readLong(47); // reads a 47-bit signed long

input.align(1); // 8-bit byte align; padding


final WritableByteChannel channel;
final BitOutput output = new BitOutput(new BitOutput.ChannelOutput(channel));

output.writeBoolean(true); // writes a 1-bit boolean value
output.writeInt(17, 0x00); // writes a 17-bit signed int
output.writeUnsignedLong(54, 0x00L); // writes a 54-bit unsigned long

output.align(4); // 32-bit byte align; discarding
1
ответ дан Jin Kwon 18 August 2018 в 01:02
поделиться

InputStreams и OutputStreams - потоки байтов.

Чтобы прочитать бит, вам нужно будет прочитать байт, а затем использовать манипуляции с битами, чтобы проверить интересующие вас биты. Аналогично, для записи битов вам нужно написать байты, содержащие нужные вам биты.

2
ответ дан Laurence Gonsalves 18 August 2018 в 01:02
поделиться

Невозможно сделать это напрямую. Меньшие единицы компьютеров могут обрабатывать байты (даже булевы занимают байты). Однако вы можете создать собственный класс потока, который упаковывает байт с нужными битами, а затем записывает его. Затем вы можете создать оболочку для этого класса, у которого функция записи принимает некоторый интегральный тип, проверяет, что она находится между 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 с битовыми операторами и, таким образом, избежать для изменения ввода, но я не думаю, что это трудно.

Кроме того, вы, вероятно, заметили, что нет локального способа обнаружить, что последний бит был прочитан в этой реализации, но я really не хотят думать , что hard.

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.");
    }

}
4
ответ дан M.J. Rayburn 18 August 2018 в 01:02
поделиться
  • 1
    Вы должны знать, что если число бит не кратно 8, последний байт будет заполнен нулями. Это может вызвать некоторые ошибки, если они не обрабатываются. – user 22 September 2016 в 15:08
  • 2
    Я боюсь, что использование массива логических выражений для битов довольно неэффективно. – U. Windl 9 May 2018 в 09:09

Если вы просто записываете биты в файл, класс BitSet класса Java может стоить взглянуть. Из javadoc:

Этот класс реализует вектор бит, который растет по мере необходимости. Каждый компонент битового набора имеет логическое значение. Биты BitSet индексируются неотрицательными целыми числами. Отдельные индексированные биты могут быть проверены, установлены или очищены. Один BitSet может использоваться для изменения содержимого другого BitSet с помощью логических логических И, логических включений OR и логических исключающих операций OR.

Вы можете преобразовать BitSets в long [] и byte [ ] для сохранения данных в файл.

0
ответ дан Soupy 18 August 2018 в 01:02
поделиться

Биты упакованы в байтах, и кроме VHDL / Verilog я не видел языка, который позволяет добавлять отдельные биты в поток. Загрузите свои биты и упакуйте их в байты для записи с использованием буфера и битмаскинга . Сделайте обратное для чтения, т. Е. Держите указатель в своем буфере и увеличивайте его, когда вы возвращаете индивидуально маскированные биты.

1
ответ дан whatnick 18 August 2018 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: