JavaRush /Java блог /Random /Байты. Что мы считываем из файла?
Roman
33 уровень

Байты. Что мы считываем из файла?

Статья из группы Random
В общем, это информация для новичков. Когда пошла тема про считывание информации из файла, встал вопрос: если файл содержит буквы, то почему мы считываем из него цифры в виде байтов и чем является все-таки в таком случае байт. О том, что такое байт, уже достаточно хорошо написано здесь. Но, после прочтения, все равно остался вопрос механизма трансформации букв в цифры, пришлось немного поковыряться в интернете. Поэтому написанное ниже можно считать дополнением. Компьютер хранит каждый файл в виде информации состоящей из нулей и единиц в бинарной форме. Каждый файл фактически является набором байтов следующих один за другим. В типовом варианте существует два вида файлов с информацией: текстовый файл и бинарный файл. Текстовый файл содержит типовой человеческий набор читабельных символов, который мы можем открыть в любом текстовом редакторе. Бинарные файлы состоят из символов, которыми мы не привыкли оперировать в обычной жизни, соответственно требуется специальная программа,, способная их прочитать. Текстовые файлы состоят из букв, цифр и других общепринятых символов. Такие файлы имеют расширения .txt, .py, .csv и т.д. Когда мы открываем такой файл, то видим привычный набор символов, образующих слова. Хотя на самом деле это содержание внутри компьютера не хранится в таком виде. Оно хранится в виде битов, то есть 0 или 1. В различных кодировочных таблицах ASCII, UNICODE или какой другой значение каждого символа определено в бинарном виде. Соответственно, если байт может вмещать 256 символов, то каждому символу соответствует своя двоичная кодировка из нулей и единиц (восемь подряд записанных нулей или единиц дают один символ). Таким образом, когда файл открывается, текстовый редактор осуществляет перевод каждого значения ASCII в привычный нам символ и отображает его уже в привычном виде. Например, под номером 65 в бинарном виде кода ASCII идет 1000001, которое отобразится в файле латинской (не кириллица. Кириллица стартует со 192 позиции) буквой «А». То есть в системе ASCII байту со значением 1000001 соответствует значение латинской буквы «А». Каждая линия файла имеет свой знак переноса строки – EOL (End of Line). Часто этим символом (двумя символами) является «\n» (бинарное значение в ASCII: 00001010). Считав такой символ программа интерпретирует его как конец строки и переход на строку ниже. Есть другие подобные "функциональные символы". Бинарные файлы, как и текстовые, хранятся в бинарном виде, но к ним не «прилагается» программа, которая их раскодирует, то есть нет расшифровочной таблицы типа ASCII. В основном содержание таких файлов представляет собой картинки, аудио и видео, которые в свою очередь являются ужатыми версиями других файлов, например самовыполняющихся файлов (.ехе). Такие файлы (бинарные) не читаются человеком в обычном понимании, поэтому попытка открыть их привычными текстовыми редакторами отобразит кучу непонятного мусора. Соответственно для корректного чтения таких файлов выпускаются специальные программы. Бинарные файлы также хранятся в виде набора байтов, но в данном случае изменение хотя бы одного бита может сделать нечитабельным весь файл. Таблицу символов ASCII можно посмотреть здесь. Таким образом, когда мы читаем файл, то в переменную byte считываются по 8 символов (единица или ноль), которые затем могут быть конвертированы какой-либо программой типа Блокнот в читабельные символы. Источник, который помог разобраться.
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
irrisor Уровень 30
8 апреля 2024
А в таком случае как мы можем определить каким типом является файл (не зная его расширения допустим). То есть у меня в файле .txt написан английский текст - тогда зная ascii можно это легко определить такой строчкой:

if (b < 0x09 || (b > 0x0D && b < 0x20) || b > 0x7E)
     isText = false;
но что если у нас написан русский текст? Оно уже будет принимать его как за бинарный файл. Никак не могу допереть / найти информацию о том как это можно сделать. То есть моя задача стоит чтобы определить каким типом является файл: text / unicode / binary. На данный момент у меня такой код:

try {
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            File file = new File(bf.readLine());
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(bf.readLine());

            String fileType;
            byte[] buffer = new byte[2048];

            int bytesRead = fis.read(buffer);
            if (bytesRead == -1) {
                fileType = "Empty file";
            } else {
                boolean isText = true;
                for (byte b : Arrays.copyOf(buffer, bytesRead)) {
                    if (b < 0x09 || (b > 0x0D && b < 0x20) || b > 0x7E) {
                        isText = false;
                        break;
                    }
                }

                if (isText) {
                    fileType = "Text File";
                } else {
                    boolean isUnicode = (buffer[0] == (byte) 0xFE && buffer[1] == (byte) 0xFF)
                            || (buffer[0] == (byte) 0xFF && buffer[1] == (byte) 0xFE);

                    if (isUnicode) {
                        fileType = "Unicode File";
                    } else {
                        fileType = "Binary File";
                    }