OK, because I like puzzling and because the Java language could have more support for this kind of low level array operations. I've coined the term bitgets to indicate the character representation of a 0 and 1, and a method toBitgets
to print all 8 bits of a byte.
This class also uses some regex fu to make sure that the parsed string has the exact representation that was requested of it: 8 bitgets followed by a space or the end of the input.
import static java.nio.charset.StandardCharsets.US_ASCII;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class S2B2S {
public S2B2S() {
}
public void toBitgets(StringBuilder sb, byte b) {
for (int i = 0; i < Byte.SIZE; i++) {
sb.append('0' + ((b >> (Byte.SIZE - i - 1))) & 1);
}
}
public String encode(String s) {
byte[] sdata = s.getBytes(US_ASCII);
StringBuilder sb = new StringBuilder(sdata.length * (Byte.SIZE + 1));
for (int i = 0; i < sdata.length; i++) {
if (i != 0) {
sb.append(' ');
}
byte b = sdata[i];
toBitgets(sb, b);
}
return sb.toString();
}
public String decode(String bs) {
byte[] sdata = new byte[(bs.length() + 1) / (Byte.SIZE + 1)];
Pattern bytegets = Pattern.compile("([01]{8})(?: |$)");
Matcher bytegetsFinder = bytegets.matcher(bs);
int offset = 0, i = 0;
while (bytegetsFinder.find()) {
if (bytegetsFinder.start() != offset) {
throw new IllegalArgumentException();
}
sdata[i++] = (byte) Integer.parseInt(bytegetsFinder.group(1), 2);
offset = bytegetsFinder.end();
}
if (offset != bs.length()) {
throw new IllegalArgumentException();
}
return new String(sdata, US_ASCII);
}
public static void main(String[] args) {
String hello = "Hello";
S2B2S s2b2s = new S2B2S();
String encoded = s2b2s.encode(hello);
System.out.println(encoded);
String decoded = s2b2s.decode(encoded);
System.out.println(decoded);
}
}