Как я могу прочитать файл как неподписанные байты в Java? - PullRequest
6 голосов
/ 28 февраля 2011

Как я могу прочитать файл в байтах в Java?

Важно отметить, что все байты должны быть положительными, т. Е. Нельзя использовать отрицательный диапазон.

Можно ли это сделать на Java, и если да, то как?

Мне нужно умножить содержимое файла на константу. Я предполагал, что могу прочитать байты в BigInteger, а затем умножить, однако, поскольку некоторые байты являются отрицательными, я получаю 12 13 15 -12 и т. Д. И застреваю.

Ответы [ 5 ]

16 голосов
/ 28 февраля 2011

Ну, у Java нет концепции беззнаковых байтов ... тип byte всегда подписан со значениями от -128 до 127 включительно.Однако это будет прекрасно взаимодействовать с другими системами, которые работали со значениями без знака, например, код C #, записывающий байт «255», создаст файл, в котором то же значение читается как «-1» в Java.Просто будьте осторожны, и все будет в порядке.

РЕДАКТИРОВАТЬ: вы можете преобразовать подписанный байт в int со значением unsigned очень легко, используя битовую маску.Например:

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

Выполните всю свою арифметику, используя int, а затем приведите обратно к byte, когда вам нужно будет снова записать ее.

Обычно вы читаете двоичные данные изиз файлов, использующих FileInputStream или, возможно, FileChannel.

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

2 голосов
/ 26 ноября 2016

С API без знака в Java 8 у вас есть Byte.toUnsignedInt.Это будет намного чище, чем наложение и маскирование вручную.

Чтобы преобразовать int обратно в byte после того, как возиться с ним, конечно, вам просто нужен отлив (byte)value

1 голос
/ 28 февраля 2011

Вы написали в комментарии (пожалуйста, укажите такую ​​информацию в вопросе - для этого есть ссылка для редактирования):

Мне нужно иметь возможность умножить содержимое файла на константу,Я предполагал, что могу прочитать байты в BigInteger, а затем умножить, однако, поскольку некоторые байты являются отрицательными, я получаю 12 13 15 -12 и т. Д. И застреваю.

Если вы хотите использовать весь файл как BigInteger, прочитайте его в байте [] и передайте этот массив (в целом) конструктору BigInteger.

/**
 * 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);
    }
}

Затем вы можете умножить свой BigInteger и сохранить результат в новом файле (используя метод toByteArray()).

Конечно, это очень зависит от формата вашего файла - мой метод предполагает, что файлсодержит результат метода toByteArray(), а не какой-либо другой формат.Если у вас есть какой-то другой формат, пожалуйста, добавьте информацию об этом в свой вопрос.

«Мне нужно иметь возможность умножить содержимое файла на константу». кажется довольно сомнительнымцель - что ты действительно хочешь делать?

1 голос
/ 28 февраля 2011

Если внутреннее использование целочисленного типа большего размера не является проблемой, просто воспользуйтесь простым решением и добавьте 128 ко всем целым числам перед их умножением.Вместо от -128 до 127 вы получаете от 0 до 255. Добавление не сложно;)

Также помните, что арифметические и побитовые операторы в Java возвращают только целые числа, поэтому:

byte a = 0;
byte b = 1;

byte c = a | b;

выдаст ошибку времени компиляции, так как |b возвращает целое число.Вам нужно будет

byte c = (byte) a | b;

Поэтому я бы предложил просто добавить 128 ко всем вашим числам, прежде чем их умножить.

0 голосов
/ 03 декабря 2013

Некоторое тестирование показало, что это возвращает значения байтов без знака в диапазоне [0… 255] одно за другим из файла:

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

Кажется, это работает для всех байтов в диапазоне, включаяв ISO 8859-1 не определены символы.

...