Как считывать байты из файла в одну строку с помощью ReadAllBytes?

#java #file #binary #ascii

#java #файл #двоичный #ascii

Вопрос:

Я беру класс алгоритмов, где мы должны реализовать сжатие LZW в Java. Я решил использовать для этого структуру данных Trie, и я уже реализовал Trie и заставил его работать.

Теперь я хотел бы прочитать байты из файла, преобразовать их в дополненный двоичный файл (00000001 вместо 01), а затем сохранить их в моем Trie. Мне нужна помощь не для проверки, а скорее для чтения содержимого файла.

Я пробовал использовать ReadAllBytes для чтения содержимого и добавления каждого преобразованного байта в StringBuilder, но когда я делаю это, я получаю StringBuilder, полный 48 и 49. Я думаю, что мои двоичные данные преобразуются в ASCII, чего я не хочу. Мне просто нужна строка с 1 и 0.

Я заставил приведенный ниже метод работать, но он полагается на ArrayList вместо строки. Он также не использует ReadAllBytes и работает очень медленно. (Я не смог заставить ReadAllBytes работать, это просто дает мне бесконечный цикл). Мы будем оцениваться по производительности.

     File file = new File(path);

    ArrayList<String> codes = new ArrayList<String>();

    try (FileInputStream fileInputStream = new FileInputStream(file)) {
        int singleCharInt;
        while ((singleCharInt = fileInputStream.read()) != -1) {
            codes.add(Integer.toBinaryString((singleCharInt amp; 0xFF)   0x100).substring(1));
        }
    }

    return codes;
 

Спасибо за ваше время!

Ответ №1:

все мои дополненные двоичные значения были преобразованы в ASCII! Таким образом, моя строка была заполнена цифрами 48, 49 и т.д. вместо исходной даты.

Это звучит так, как будто вы хотите просто прочитать файл. Прежде чем вы сможете прочитать его, вам нужно будет знать, в какой кодировке он находится. Вы не можете определить ни по файлу, ни по расширению (по крайней мере, обычно), вы должны были бы знать. Если вы не знаете, то UTF-8 — хороший вариант, и это значение по умолчанию для Files API.

 Path p = Paths.get("/path/to/file.txt");
String string = Files.readString(p);
 

Это все, что вам нужно сделать. Не нужно вмешиваться readAllBytes . Если вы должны (что вы действительно должны делать, только если у вас вообще нет файла, а есть что-то еще в форме InputStream):

 String s;
try (InputStream in = ...) {
    s = new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
 

Комментарии:

1. Моя ошибка, я хотел сказать «вместо исходных данных».

2. Причина ReadAllBytes заключается в том, что я реализую сжатие LZW. Я хочу прочитать байты и преобразовать их в их двоичные эквиваленты, чтобы сохранить их в дереве.

3. Я отредактировал свой вопрос, чтобы предоставить свой контекст и детали.

Ответ №2:

Вы можете использовать StringBuffer StringBuilder класс or для получения конечного результата строки.

 StringBuffer buffer = new StringBuffer();

try (FileInputStream fileInputStream = new FileInputStream(file)) {
    int singleCharInt;
    while ((singleCharInt = fileInputStream.read()) != -1) {
        buffer.append(Integer.toBinaryString((singleCharInt amp; 0xFF)   0x100));
    }
}

// Result: buffer.toString()
 

Комментарии:

1. Это было бы невероятно медленно .

2. Сам вопрос OPs является проблемой, а не этим решением. На самом деле это именно то, для чего работает OP, И это самый быстрый. Поэтому я бы не стал понижать голос. Просто концепция OP уже нарушена.

3. @JayC667 Нет, это невероятно медленно: вы не вызываете single read() в необработанном FileInputStream, это буквально в 1000 раз или более медленнее, чем использование буферов или чтение фрагментов за раз. Жесткие диски не могут считывать отдельные байты, они могут считывать только фрагменты за раз, поэтому read() считывает весь фрагмент, выбрасывает все данные, кроме одного байта. Просто… попробуй. Прямо сейчас. Скажем, в файле объемом 1 ГБ. Это займет много времени.

4. Опять же, как я уже говорил ранее, вы не упомянули о каких-либо проблемах с производительностью в своем первоначальном опубликованном вопросе (когда был отправлен этот ответ). Таким образом, вы не должны ожидать ответа с полным учетом. Ответ — это то, чего вы хотите в своем вопросе. Если вы хотите что-то еще, вам следует отредактировать свой вопрос, а не оставлять ответ с отрицательным ответом!

5. @rzwitserloot Я знаю, я знаю. Но даже чтение отдельных байтов обычно происходит лишь примерно в 40.000 раз медленнее, чем массовые операции. Это все равно не было бы главной проблемой в концепции. И это можно было бы легко смягчить, используя BufferedInputStream.

Ответ №3:

Вы можете получить btyeCode из файла, подобного этому;

 public static byte[] readFileNio(String physicalPath) throwsFileNotFoundException, IOException{ 
  RandomAccessFile aFile = new RandomAccessFile(physicalPath,"r");
  FileChannel inChannel = aFile.getChannel();
  ByteBuffer buffer = ByteBuffer.allocate((int)inChannel.size());
  inChannel.read(buffer);
  buffer.flip();
  inChannel.close();
  aFile.close();
  return buffer.array();
}
 

затем вы можете записать байт-код в любое конкретное место

 Files.write(newPath, readFileNio(fromPath), StandardOpenOption.CREATE_NEW);
 

для сжатия используйте ZipOutputStream