Question

Pour un projet, je dois convertir une chaîne binaire en (un tableau de) octets et l'écrire dans un fichier binaire.

Dis que j'ai une phrase convertie en une chaîne de code en utilisant un codage de Huffman. Par exemple, si la phrase était: "bonjour" h = 00 e = 01, l = 10, o = 11

Ensuite, la représentation de chaîne serait 0001101011.

Comment puis-je convertir en un octet? <- Si cette question n'a pas de sens, il est parce que je sais peu de choses sur bits / octet décalage au niveau du bit et tout ce qui a à voir avec la manipulation de 1 et 0.

Était-ce utile?

La solution

Si vous voulez vraiment (ou doivent) la création d'une représentation de chaîne de bits, vous pouvez diviser la chaîne en sous-chaînes de longueur 8 (méfiez-vous de la dernière qui est pas nécessairement la longueur 8).

entier  présente un procédé de représentations de chaîne parse, une séquence de « 0 » et « 1 'peut être analysée en appelant avec radix = 2.

static int parseInt(String s, int radix) 

analyse l'argument de chaîne d'un entier signé dans la base spécifiée par le second argument.

-

EDIT: Selon les commentaires Byte.parseByte est le chemin à parcourir.

Autres conseils

Voici un simple, mais la mise en œuvre probablement inefficace:

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class BitOutputStream extends FilterOutputStream {

  private int bits = 0;
  private int n = 0;
  private long totalBits = 0;

  public BitOutputStream(OutputStream out) {
    super(out);
  }

  private void writeSingleBit(int bit) throws IOException {
    bits = (bits << 1) | (bit & 1);
    n++;
    totalBits++;
    if (n == 8) {
      super.write(bits);
      bits = 0;
      n = 0;
    }
  }

  /**
   * Writes the <i>numberOfBits</i> lower bits of <i>bitsToWrite</i> to the
   * output stream, starting with the most significant bit.
   */
  public void writeBits(int bitsToWrite, int numberOfBits) throws IOException {
    for (int i = numberOfBits - 1; i >= 0; i--) {
      int bit = bitsToWrite >> i;
      writeSingleBit(bit);
    }
  }

  @Override
  public void write(byte[] b, int off, int len) throws IOException {
    for (int i = 0; i < len; i++)
      writeBits(b[off + i], 8);
  }

  @Override
  public final void write(int b) throws IOException {
    writeBits(b, 8);
  }

  @Override
  public final void flush() throws IOException {
    writeBits(0, (8 - n) & 0x07);
  }

  /**
   * Returns the number of bits that have been written to this bitstream.
   */
  public long getTotalBits() {
    return totalBits;
  }
}

Et le test unitaire correspondant:

import static org.junit.Assert.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.junit.Test;

public class BitOutputStreamTest {

  @Test
  public void hello() throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    BitOutputStream bos = new BitOutputStream(baos);
    bos.writeBits(0x00, 2);
    bos.writeBits(0x01, 2);
    bos.writeBits(0x02, 2);
    bos.writeBits(0x02, 2);
    bos.writeBits(0x03, 2);
    assertEquals(10, bos.getTotalBits());
    bos.close();
    assertEquals(16, bos.getTotalBits());
    assertArrayEquals(new byte[] { 0x1A, (byte) 0xC0 }, baos.toByteArray());
  }
}

Ce code ne sort pas les bits dans la représentation de chaîne que vous voulez, mais quand vous voulez les écrire dans un flux à base d'octets plus tard, est le chemin à parcourir.

Mise à jour (2010-09-25): Correction d'un bug dans la méthode write(byte[], int, int). J'ai oublié d'ajouter off à l'index du tableau.

Pourquoi avez-vous besoin de se convertir en une « chaîne binaire » d'abord? Il suffit d'aller directement à l'écriture d'octets en sortie.

Conceptuellement ce que vous faites est de bits d'écriture dans un byte, jusqu'à ce que vous avez rempli un byte. Cela se fait avec un décalage de bits. Pour ajouter un 1 bit au bas d'une valeur que vous faites quelque chose comme:

b = (b << 1) | 1;

et puis une fois que vous avez rempli un octet dont vous avez besoin pour développer votre byte[] de sortie pour faire place à une autre jusqu'à ce que fait. Vous pouvez utiliser ByteArrayOutputStream pour cela aussi, pour byte progressivement sortie, puis obtenir un byte[] plus tard.

Je peux vous indiquer à de classe qui vous permet d'ajouter des morceaux et ensuite obtenir la pensée octets résultant plus tard, il est la création d'un tableau de ints au lieu d'octets. Vous pouvez l'utiliser comme un exemple.

L'encodage d'une chaîne en enchaînant les représentations de chaîne bot les séquences de bits représentant les caractères individuels, puis transformer cela en un octet semble à nouveau comme un moyen très coûteux de faire les choses.

Vous pouvez regarder dans Preon à la place. Preon a tout d'abord abstraction BitChannel qui vous empêche d'avoir à se soucier de beaucoup de vous déplacer. Vous pouvez simplement écrire des séquences de bits à la BitChannel. Il gardera une trace du « pointeur bit » interne, et tout traduire en octets en aval.

BitChannel channel = new OutputStreamBitChannel(...);
channel.write(1, 0); // 0 = 'h'
channel.write(2, 1); // 01 = 'e'
channel.write(3, 2); // 10 = 'l'
channel.write(4, 2); // 11 = '0'

Cependant, dans l'idéal, vous seriez en mesure d'utiliser les abstractions plus au niveau de PREON (Preon contraignant) qui vous empêcher d'avoir à traiter avec vous-même tout . Il serait tout simplement besoin d'une annotation sur votre chaîne.

@BoundHuffmanCoded String toBeEncoded = "hello";

... et Preon prendrait en charge le reste. Maintenant, rappelez-vous, c'est le cas idéal, et Preon n'a pas cette annotation encore . Mais il est possible d'enregistrer un codec pour vous-même. Gardez un oeil sur ce bien, puisque c'est quelque chose qui va certainement aller dans une version future de Preon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top