How can I read a file as unsigned bytes in Java?

只谈情不闲聊 提交于 2020-01-02 03:41:07

问题


How can I read a file to bytes in Java?

It is important to note that all the bytes need to be positive, i.e. the negative range cannot be used.

Can this be done in Java, and if yes, how?

I need to be able to multiply the contents of a file by a constant. I was assuming that I can read the bytes into a BigInteger and then multiply, however since some of the bytes are negative I am ending up with 12 13 15 -12 etc and get stuck.


回答1:


Well, Java doesn't have the concept of unsigned bytes... the byte type is always signed, with values from -128 to 127 inclusive. However, this will interoperate just fine with other systems which have worked with unsigned values for example, C# code writing a byte of "255" will produce a file where the same value is read as "-1" in Java. Just be careful, and you'll be okay.

EDIT: You can convert the signed byte to an int with the unsigned value very easily using a bitmask. For example:

byte b = -1; // Imagine this was read from the file
int i = b & 0xff;
System.out.println(i); // 255

Do all your arithmetic using int, and then cast back to byte when you need to write it out again.

You generally read binary data from from files using FileInputStream or possibly FileChannel.

It's hard to know what else you're looking for at the moment... if you can give more details in your question, we may be able to help you more.




回答2:


With the unsigned API in Java 8 you have Byte.toUnsignedInt. That'll be a lot cleaner than manually casting and masking out.

To convert the int back to byte after messing with it of course you just need a cast (byte)value




回答3:


You wrote in a comment (please put such informations in the question - there is an edit link for this):

I need to be able to multiply the contents of a file by a constant. I was assuming that I can read the bytes into a BigInteger and then multiply, however since some of the bytes are negative I am ending up with 12 13 15 -12 etc and gets stuck.

If you want to use the whole file as a BigInteger, read it in a byte[], and give this array (as a whole) to the BigInteger-constructor.

/**
 * reads a file and converts the content to a BigInteger.
 * @param f the file name. The content is interpreted as
 *   big-endian base-256 number.
 * @param signed if true, interpret the file's content as two's complement
 *                  representation of a signed number.
 *               if false, interpret the file's content as a unsigned
 *                  (nonnegative) number.
 */
public static BigInteger fileToBigInteger(File f, boolean signed)
    throws IOException
{
    byte[] array = new byte[file.length()];
    InputStream in = new FileInputStream(file);
    int i = 0; int r;
    while((r = in.read(array, i, array.length - i) > 0) {
        i = i + r;
    }
    in.close();
    if(signed) {
        return new BigInteger(array);
    }
    else {
        return new BigInteger(1, array);
    }
}

Then you can multiply your BigInteger and save the result in a new file (using the toByteArray() method).

Of course, this very depends on the format of your file - my method assumes the file contains the result of the toByteArray() method, not some other format. If you have some other format, please add information about this to your question.

"I need to be able to multiply the contents of a file by a constant." seems quite a dubious goal - what do you really want to do?




回答4:


If using a larger integer type internally is not a problem, just go with the easy solution, and add 128 to all integers before multiplying them. Instead of -128 to 127, you get 0 to 255. Addition is not difficult ;)

Also, remember that the arithmetic and bitwise operators in Java only returns integers, so:

byte a = 0;
byte b = 1;

byte c = a | b;

would give a compile time error since a | b returns an integer. You would have to to

byte c = (byte) a | b;

So I would suggest just adding 128 to all your numbers before you multiply them.




回答5:


Some testing revealed that this returns the unsigned byte values in [0…255] range one by one from the file:

Reader bytestream = new BufferedReader(new InputStreamReader(
        new FileInputStream(inputFileName), "ISO-8859-1"));
int unsignedByte;
while((unsignedByte = bytestream.read()) != -1){
    // do work
}

It seems to be work for all bytes in the range, including those that no characters are defined for in ISO 8859-1.



来源:https://stackoverflow.com/questions/5144080/how-can-i-read-a-file-as-unsigned-bytes-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!