Как читать данные из java-файла

Обновлено: 04.07.2024

Java предоставляет API java.nio.file для чтения и записи файлов. Класс InputStream является надклассом всех классов, представляющих входной поток байтов.

1.2. Чтение файла в Java

Чтобы прочитать текстовый файл, вы можете использовать метод Files.readAllBytes. Использование этого метода показано в следующем листинге.

Чтобы прочитать текстовый файл построчно в структуру списка типа String, вы можете использовать метод Files.readAllLines.

Files.readAllLines использует кодировку символов UTF-8. Это также гарантирует, что файл будет закрыт после прочтения всех байтов или в случае возникновения исключения.

1.3. Чтение и фильтрация построчно

Метод Files.lines позволяет читать файл построчно, предлагая поток. Этот поток можно фильтровать и отображать. Files.lines не закрывает файл после того, как его содержимое прочитано, поэтому его следует заключить в оператор try-with-resource.

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

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

В следующем примере извлекается строка, начинающаяся с "Bundle-Version:", из файла MANIFEST.MF, расположенного в папке META-INF. Он удаляет префикс и удаляет все начальные и конечные пробелы.

1.4. Написание файла на Java

Чтобы записать файл, вы можете использовать следующий метод:

1,5. Список всех файлов и подкаталогов с помощью Files.list()

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

1.6. Как определить текущий каталог

2. Упражнение: чтение и запись файлов

Создайте новый проект Java с именем com.vogella.java.files. Создайте следующий класс FilesUtil.java.

Чтобы протестировать эти методы, создайте текстовый файл с именем file.txt с некоторым содержимым в папке вашего проекта. Создайте следующий основной класс и запустите его.

3. Пример: рекурсивный список всех файлов каталога

Java 8 предоставляет хороший поток для обработки всех файлов в дереве.

4. Пример: удаление каталога со всеми подкаталогами и файлами

Чтобы удалить каталог и все его содержимое.

5. Чтение ресурсов из вашего проекта/банки

Вы можете считывать ресурсы из своего проекта или файла jar через цепочку методов .getClass().getResourceAsStream() из любого объекта.

Значительное количество программного обеспечения так или иначе основано на обработке данных. Программное обеспечение, созданное для воспроизведения музыки, обрабатывает музыкальные файлы, а программное обеспечение, созданное для обработки изображений, обрабатывает файлы изображений. Приложения, работающие в Интернете и на мобильных устройствах, такие как Facebook, WhatsApp и Telegram, обрабатывают информацию о пользователях, хранящуюся в файловых базах данных. Их всех объединяет то, что они так или иначе считывают данные и манипулируют ими. Кроме того, обрабатываемые данные в конечном итоге сохраняются в каком-либо формате в одном или нескольких файлах.

Чтение с клавиатуры

С самого начала этого курса мы использовали класс Scanner для чтения пользовательского ввода. Блок, в котором считываются данные, представляет собой цикл while-true, в котором чтение заканчивается на определенном входе.

В приведенном выше примере мы передаем системный ввод ( System.in ) в качестве параметра конструктору класса Scanner. В текстовых пользовательских интерфейсах ввод пользователя направляется во входной поток по одной строке за раз, что означает, что информация отправляется для обработки каждый раз, когда пользователь вводит новую строку.

Введенные пользователем данные считываются в виде строки. Например, если бы мы хотели обрабатывать входные данные как целые числа, нам пришлось бы преобразовать их в другую форму. Ниже приведен пример программы - она ​​считывает ввод от пользователя до тех пор, пока пользователь не введет "конец". Пока пользовательский ввод не «конец», ввод обрабатывается как целое число — в этом случае число просто печатается.

Файлы и файловая система

Файлы — это наборы данных, хранящиеся на компьютерах. Эти файлы могут содержать, среди прочего, текст, изображения, музыку или любую их комбинацию. Формат файла определяет содержимое файла, а также программу, необходимую для чтения файла. Например, PDF-файлы читаются с помощью программы, подходящей для чтения PDF-файлов, а музыкальные файлы читаются с помощью программы, подходящей для чтения музыкальных файлов. Каждая из этих программ создается людьми, и создатели этих программ, т. е. программисты, также определяют формат файла как часть работы.

В компьютерах есть несколько разных программ для просмотра файлов. Эти программы специфичны для операционной системы. Все программы, используемые для просмотра файлов, так или иначе используют файловую систему компьютера.

Наша среда разработки предоставляет нам возможность просматривать файлы проекта.В NetBeans вы можете просмотреть все файлы, прикрепленные к проекту, выбрав вкладку «Файлы», которая находится там же, где и вкладка «Проекты». Если вкладку не удается найти, ее можно открыть из меню «Окно». Если щелкнуть проект, чтобы открыть его, отобразятся все его файлы.

Конкретный формат хранения файлов

Файлы существуют на жестком диске компьютера, который на самом деле представляет собой большой набор единиц и нулей, т. е. битов. Информация состоит из этих битов, например, одна переменная типа int занимает 32 бита (то есть 32 единицы или нуля). Современные жесткие диски размером в терабайт содержат около 8 триллионов битов (выписанное число равно 8 000 000 000 000). В этом масштабе одно целое число очень мало.

Файлы могут находиться практически в любом месте на жестком диске, даже разделенные на несколько частей. Файловая система компьютера отвечает за отслеживание расположения файлов на жестком диске, а также за предоставление возможности создавать новые файлы и изменять их. Основная обязанность файловой системы — абстрагирование истинной структуры жесткого диска; пользователю или программе, использующей файл, не нужно заботиться о том, как и где этот файл на самом деле хранится.

Чтение из файла

Чтение файла выполняется с помощью класса Scanner. Когда мы хотим прочитать файл с помощью класса Scanner, мы указываем путь к файлу, который мы хотим прочитать, в качестве параметра конструктору класса. Путь к файлу можно получить с помощью команды Java Paths.get, которой передается имя файла в строковом формате в качестве параметра: Paths.get("filename.extension") .

После создания объекта Scanner, считывающего файл, файл можно прочитать с помощью цикла while. Чтение продолжается до тех пор, пока не будут прочитаны все строки файла, т. е. пока сканер не найдет больше строк для чтения. Чтение файла может привести к ошибке, и именно по этой причине процесс требует отдельных блоков — один для попытки, а другой для отлова потенциальных ошибок. Мы вернемся к теме обработки ошибок позже.

Файл читается из корня проекта по умолчанию (при вызове нового Scanner(Paths.get("file.txt"))), т.е. из папки, содержащей папку src и файл pom.xml (и возможно и другие файлы). Содержимое этой папки можно проверить с помощью вкладки "Файлы" в NetBeans.

В приведенном ниже примере мы читаем все строки файла "file.txt", которые затем добавляются в список ArrayList.

Пустая строка в файле

Иногда пустая строка попадает в файл. Пропустить пустую строку можно с помощью команды continue и isEmpty -метода строки.

В приведенном ниже примере мы читаем из файла

Чтение данных очень просто.

Чтение данных определенного формата из файла

Мир полон данных, которые связаны с другими данными — они образуют коллекции. Например, личная информация может включать имя, дату рождения и номер телефона. С другой стороны, адресная информация может включать страну, город, почтовый адрес, почтовый номер и т. д.

Данные часто хранятся в файлах определенного формата. Одним из таких форматов, который нам уже знаком, является формат значений, разделенных запятыми (CSV), т. е. данные, разделенные запятыми.

Программа работает следующим образом:

Введите имя и возраст через запятую: virpi,19 Имя: virpi Возраст: 19 Введите имя и возраст через запятую: jenna,21 Имя: jenna Возраст: 21 Введите имя и возраст через запятую: ada, 20 Имя: Ада Возраст: 20

Чтение тех же данных из файла records.txt будет выглядеть так:

Чтение объектов из файла

Создание объектов на основе данных, считанных из файла, очень просто. Предположим, что у нас есть класс с именем Person , а также предыдущие данные.

Чтение объектов можно сделать следующим образом:

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

Не забудьте проверить свои баллы по шарику в правом нижнем углу материала!

Java предоставляет несколько способов чтения файлов. Каждый из этих методов подходит для чтения разных типов файлов в разных ситуациях. Некоторые лучше подходят для чтения более длинных файлов, другие — для чтения более коротких и т. д.

В этом руководстве мы будем использовать следующие классы Java для чтения файлов

  • Буферизованное чтение
  • Файлы
  • Сканер

На протяжении всего руководства мы используем файл, хранящийся в каталоге src, где путь к файлу — src/file.txt .

Сохраните несколько строк текста в этом файле, прежде чем продолжить.

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

Чтение текстовых файлов в Java с помощью BufferedReader

Класс BufferedReader считывает поток ввода символов.Он буферизует символы в буфере с размером по умолчанию 8 КБ, чтобы сделать процесс чтения более эффективным. Если вы хотите прочитать файл построчно, хорошим выбором будет использование BufferedReader.

BufferedReader эффективен при чтении больших файлов.

Метод readline() возвращает null при достижении конца файла.

Чтение файла в кодировке UTF-8 в Java с помощью BufferedReader

Мы можем использовать класс BufferedReader для чтения файла в кодировке UTF-8.

На этот раз мы передаем объект InputStreamReader при создании экземпляра BufferedReader.

Использование класса файлов Java для чтения файла

Класс Java Files, представленный в Java 7 в Java NIO, полностью состоит из статических методов, которые работают с файлами.

Используя класс Files, вы можете прочитать все содержимое файла в массив. Это делает его хорошим выбором для чтения небольших файлов.

Давайте посмотрим, как мы можем использовать класс Files в обоих этих сценариях.

Чтение небольших файлов в Java с помощью класса Files

Метод readAllLines() класса Files позволяет считывать все содержимое файла и сохранять каждую строку в массиве в виде строк.

Вы можете использовать класс Path для получения пути к файлу, поскольку класс Files принимает объект Path файла.

Вы можете использовать readAllBytes() для извлечения данных, хранящихся в файле, в массив байтов, а не в массив строк.

Чтение больших файлов в Java с помощью класса Files

Если вы хотите прочитать большой файл с помощью класса Files, вы можете использовать метод newBufferedReader() для получения экземпляра класса BufferedReader и читать файл построчно с помощью BufferedReader .

Чтение файлов с помощью Files.lines()

В Java 8 в классе Files появился новый метод для чтения всего файла в поток строк.

Чтение текстовых файлов в Java с помощью сканера

Класс Scanner разбивает содержимое файла на части, используя заданный разделитель, и считывает его часть за частью. Этот подход лучше всего подходит для чтения контента, разделенного разделителем.

Например, класс Scanner идеально подходит для чтения списка целых чисел, разделенных пробелами, или списка строк, разделенных запятыми.

Разделителем по умолчанию для класса Scanner является пробел. Но вы можете установить разделитель на другой символ или регулярное выражение. Он также имеет различные методы next, такие как next() , nextInt() , nextLine() и nextByte() для преобразования содержимого в различные типы.

В приведенном выше примере мы устанавливаем разделитель на пробел и используем метод next() для чтения следующей части содержимого, разделенной пробелом.

Чтение всего файла

Вы можете использовать класс Scanner для одновременного чтения всего файла без запуска цикла. Вы должны передать «\\Z» в качестве разделителя для этого.

Заключение

Как вы видели в этом руководстве, Java предлагает множество методов чтения текстовых файлов, которые вы можете выбрать в зависимости от характера стоящей перед вами задачи. Вы можете использовать BufferedReader для чтения больших файлов построчно.

Если вы хотите прочитать файл, содержимое которого разделено разделителем, используйте класс Scanner.

Также вы можете использовать класс Java NIO Files для чтения как маленьких, так и больших файлов.

Похоже, в Java есть разные способы чтения и записи данных файлов.

Я хочу прочитать данные ASCII из файла. Каковы возможные способы и их различия?

Я также не согласен с закрытием как "неконструктивным". К счастью, это вполне может быть закрыто как дубликат. Хорошие ответы, например. в Как создать строку из содержимого файла?, Как проще всего прочитать файл в строку?, Каковы самые простые классы для чтения файлов?

это так интересно, что в python нет ничего похожего на "read()" для чтения всего файла в строку

28 ответов 28

Мой любимый способ чтения небольшого файла — использование BufferedReader и StringBuilder. Это очень просто и по делу (хотя и не особенно эффективно, но достаточно хорошо для большинства случаев):

Некоторые отмечают, что после Java 7 вам следует использовать функции try-with-resources (т. е. автоматическое закрытие):

Когда я читаю такие строки, я обычно все равно хочу выполнить некоторую обработку строк для каждой строки, поэтому я выбираю эту реализацию.

И еще проще с Java 7:

Я сделал небольшую поправку, чтобы перестать добавлять новую строку ( \n ), если достигнута последняя строка. код в то время как (строка! = ноль) < sb.append (строка); строка = br.readLine(); // Добавлять новую строку только в том случае, если curline НЕ является последней строкой.. if(line != null) < sb.append("\n"); >> код

Для повышения производительности всегда вызывайте sb.append('\n') вместо sb.append("\n"), так как char добавляется к StringBuilder быстрее, чем String

FileReader может генерировать FileNotFoundException, а BufferedRead может генерировать IOException, поэтому вам придется их перехватывать.

ASCII – это текстовый файл, поэтому для чтения вы должны использовать Readers. Java также поддерживает чтение из двоичного файла с помощью InputStreams.Если считываемые файлы огромны, вы можете использовать BufferedReader поверх FileReader для повышения производительности чтения.

Прочитайте эту статью о том, как использовать Reader

Я также рекомендую вам скачать и прочитать эту замечательную (но бесплатную) книгу под названием Thinking In Java

В Java 7:

В Java 8:

Будет ли сохранен порядок строк при использовании "Files.lines(..).forEach(. )". Насколько я понимаю, после этой операции порядок будет произвольным.

Files.lines(…).forEach(…) не сохраняет порядок строк, а выполняется параллельно, @Dash. Если порядок важен, вы можете использовать Files.lines(…).forEachOrdered(…) , который должен сохранить порядок (хотя не проверял).

@Palec, это интересно, но можете ли вы процитировать документацию, где говорится, что Files.lines(. ).forEach(. ) выполняется параллельно? Я думал, что это только тот случай, когда вы явно делаете поток параллельным, используя Files.lines(. ).parallel().forEach(. ) .

Моя первоначальная формулировка не является пуленепробиваемой, @KlitosKyriacou. Дело в том, что forEach не гарантирует никакого порядка и причина в простоте распараллеливания. Если нужно сохранить порядок, используйте forEachOrdered .

Проще всего использовать класс Scanner в Java и объект FileReader. Простой пример:

Scanner имеет несколько методов чтения строк, чисел и т. д. Дополнительную информацию об этом можно найти на странице документации по Java.

Например, чтение всего содержимого в строку:

Также, если вам нужна определенная кодировка, вы можете использовать ее вместо FileReader:

@JesusRamos Не совсем так, почему ты так думаешь? Что в этом проще, чем while ((line = br.readLine()) != null) < sb.append(line); >?

Вот простое решение:

Или читать как список:

Еще один способ сделать это без использования внешних библиотек:

Этот метод предполагает, что read() заполняет буфер; что количество символов равно количеству байтов; что количество байтов помещается в память; и что количество байтов соответствует целому числу. -1

@HermesTrismegistus Я привел четыре причины, почему это неправильно. Штефан Райх совершенно прав, соглашаясь со мной.

Мне пришлось сравнивать разные способы. Я прокомментирую свои выводы, но, короче говоря, самый быстрый способ — использовать старый добрый BufferedInputStream вместо FileInputStream. Если необходимо прочитать много файлов, то три потока сократят общее время выполнения примерно вдвое, но добавление большего количества потоков будет постепенно снижать производительность, пока выполнение с двадцатью потоками не займет в три раза больше времени, чем с одним потоком.

Предполагается, что вы должны прочитать файл и сделать что-то осмысленное с его содержимым. В примерах здесь читаются строки из журнала и подсчитываются те, которые содержат значения, превышающие определенный порог. Итак, я предполагаю, что однострочный Java 8 Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";")) не вариант .

Я тестировал на Java 1.8, Windows 7, а также на SSD и HDD.

Я написал шесть различных реализаций:

rawParse: используйте BufferedInputStream вместо FileInputStream, а затем обрежьте строки, считывая байт за байтом. Это превосходит любой другой однопоточный подход, но может быть очень неудобным для файлов, отличных от ASCII.

lineReaderParse: используйте BufferedReader вместо FileReader, читайте построчно, разделяйте строки, вызывая String.split(). Это примерно на 20 % медленнее, чем у rawParse.

lineReaderParseParallel: то же самое, что и lineReaderParse, но использует несколько потоков. Это самый быстрый вариант во всех случаях.

nioFilesParse: используйте java.nio.files.Files.lines()

nioAsyncParse: используйте AsynchronousFileChannel с обработчиком завершения и пулом потоков.

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

Это среднее время чтения 204 файлов по 4 МБ каждый на четырехъядерном i7 и SSD-накопителе. Файлы создаются "на лету", чтобы избежать кэширования диска.

Я обнаружил, что разница между SSD и HDD оказалась меньше, чем я ожидал, поскольку SSD примерно на 15 % быстрее. Это может быть связано с тем, что файлы создаются на нефрагментированном жестком диске и считываются последовательно, поэтому вращающийся диск может работать почти как твердотельный накопитель.

Меня удивила низкая производительность реализации nioAsyncParse. Либо я что-то не так реализовал, либо многопоточная реализация с использованием NIO и обработчиком завершения работает так же (или даже хуже), чем однопоточная реализация с API java.io. Более того, асинхронный синтаксический анализ с CompletionHandler намного длиннее в строках кода и сложнее для правильной реализации, чем прямая реализация на старых потоках.

Теперь за шестью реализациями следует класс, содержащий их все, а также параметризуемый метод main(), который позволяет играть с количеством файлов, размером файла и степенью параллелизма. Обратите внимание, что размер файлов варьируется плюс минус 20%. Это делается для того, чтобы избежать какого-либо эффекта из-за того, что все файлы имеют одинаковый размер.

Читайте также: