Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.example.foo;
- import static java.util.Arrays.asList;
- import java.io.InputStream;
- import java.io.OutputStream;
- /**
- * <p>
- * This demonstrates how to convert from int to byte and vice versa, if you want to ignore the sign.
- * The values then simply go from 0 to 255.
- * </p>
- *
- * <p>
- * This is needed when you want to process bytes that do not represent signed values. An example for
- * this is a stream of bytes that represent US-ASCII characters (8 bits per character). Java only
- * offers a type for 16 bit unsigned characters (UTF-16).
- * </p>
- *
- * <p>
- * The abstract class {@link OutputStream} also uses int to write. This is explained on the method
- * write: {@link java.io.OutputStream#write(int)}<br/>
- * The same is true for reading bytes using {@link InputStream}.<br/>
- * I wonder why they do not just use char instead of int. It would use less memory. Then again, it
- * doesn't really matter when you use single values or small buffers.
- * </p>
- *
- * <p>
- * Conversion rules are tricky. The specifications can be found here: <br/>
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html">JLS: Chapter 5. Conversions
- * and Promotions</a>
- * </p>
- * <p>
- * Never cast from byte to int when you process binary data. That only makes sense if you want to
- * have the same value but not the same data. Negative values will remain negative, but the binary
- * representation is different. <br/>
- * When processing the data you must not forget that Java still interprets the bytes as signed.<br/>
- * Beware of operations that result in overflows. When using an int you can simply use
- * <code>(i && 0xFF)</code> to ignore the extra bits and then cast to byte. Note that
- * <code>(i % 256)</code> may result in a negative value and should not be used for binary data.
- * </p>
- */
- public class UnsignedBytesInJava {
- public static void main(final String[] args) {
- // Some bytes. You could also use binary or hex.
- final byte min = Byte.MIN_VALUE; // = 0b1000_0000 = 0x80
- final byte negOne = -1;// = 0b1111_1111 = 0xFF
- final byte zero = 0;// = 0b0000_0000 = 0x00
- final byte one = 1;// = 0b0000_0001 = 0x01
- final byte max = Byte.MAX_VALUE; // = 0b0111_1111 = 0x7F
- // let's test all 5 values:
- for (final byte b : asList(min, negOne, zero, one, max)) {
- // So we can't just cast from byte to int because they are both signed.
- // Instead we use the binary pattern of 0xFF.
- // The & operator stands for "binary AND".
- final int asInt = byteToInt(b); // = b & 0xFF = b & 0b1111_1111
- // Java always creates strings in decimal, signed representation.
- // The only exception is the type char, which is unsigned.
- // So we get different results for byte and int, but the bits are the same.
- System.out.println("byte value: " + b);
- System.out.println("as int: " + asInt);
- // Since the same bits are set we can convert byte to a byte.
- // In this case it's ok to just cast from int to byte.
- final byte b2 = intToByte(asInt); // = (byte) i
- System.out.println("byte again: " + b2); // same as above!
- if (b != b2) // let's check that.
- throw new RuntimeException("wrong value!");
- // Now let's see if the bits really are the same.
- final String binaryStringByte = toBinaryString(b);
- System.out.println("binary byte: " + binaryStringByte);
- final String binaryStringInt = toBinaryString(asInt);
- System.out.println("binary int: " + binaryStringInt);
- // The word size is different (8 bits vs. 32 bits).
- // But the least significant bits are the same.
- // Let's check if this is true:
- if (!binaryStringInt.endsWith(binaryStringByte))
- throw new RuntimeException("binary representation not correct!");
- System.out.println("---------------------------");
- }
- }
- /**
- * Converts a byte to an int so that the 8 least significant bits are unaltered.
- *
- * @see java.lang.Byte#toUnsignedInt(byte)
- */
- private static int byteToInt(final byte b) {
- // return b & 0xFF;
- return Byte.toUnsignedInt(b);
- }
- /**
- * Converts a byte to an int to a byte. Values from 0 to 127 are the same, while values from 128
- * to 255 get mapped from -128 to -1. No other integers should be passed to this method. The 8
- * least significant bits are unaltered and the resulting value is interpreted as a signed bit.
- *
- * @throws IllegalArgumentException
- * When the value is not a byte (-128 to 127)
- * */
- private static byte intToByte(final int i) throws IllegalArgumentException {
- if (i < 0 || i > 255)
- throw new IllegalArgumentException("Thats not a byte!");
- return (byte) i;
- }
- // If you want the method to just ignore the 24 leading bits:
- // private static byte intToByte(final int i) { return (byte) (i & 0xFF); }
- /**
- * Converts value of byte to binary (ones and zeroes, eight in total). The returned string has the
- * most significant bit on the left.
- */
- private static String toBinaryString(final byte b) {
- final StringBuilder result = new StringBuilder();
- for (int x = 0; x < Byte.SIZE; x++) {
- final int p = 1 << x;
- if ((b & 0xFF & p) != 0)
- result.append('1');
- else
- result.append('0');
- if (x % 4 == 3)
- result.append(' ');
- }
- return result.reverse().toString().trim();
- }
- /**
- * Converts value of int to binary (ones and zeroes, 32 in total). The returned string has the
- * most significant bit on the left.
- */
- private static String toBinaryString(final int i) {
- final StringBuilder result = new StringBuilder();
- for (int x = 0; x < Integer.SIZE; x++) {
- final int p = 1 << x;
- if ((i & p) != 0)
- result.append('1');
- else
- result.append('0');
- if (x % 4 == 3)
- result.append(' ');
- }
- return result.reverse().toString().trim();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement