Как писать в файл с помощью arraylist в java

Обновлено: 21.11.2024

Запись в файл в Java называется записью содержимого из значения переменной Java или объекта в текстовый или двоичный файл с использованием потоковых классов, таких как FileWrite, FileOutputStream, PrintWriter, NIO и т. д. Класс FileWriter используется для записи в текстовый файл с использованием java. BufferWriter используется для кэширования данных и плавной записи в файл. Существует несколько способов записи в текстовый файл Java. Java предоставляет несколько API для записи текста в файл. Например, писать посимвольно, построчно или побайтно.

Запись в текстовый файл на Java

В этом посте мы объяснили пять типов записи текстового файла в Java.

  • Записать текстовый файл с помощью FileWriter
  • Записать текстовый файл с помощью FileWriter построчно
  • Записать текстовый файл с помощью FileOutputStream
  • Запись текстового файла с помощью PrintWriter
  • Записать текстовый файл с помощью NIO Files

Пример файла

Файл, используемый для хранения образцов содержимого в программах, называется data/test.txt.

Запись в текстовый файл с помощью FileWriter

Класс FileWriter используется для записи в текстовый файл с помощью java. BufferWriter используется для кэширования данных и плавной записи в файл. В классе FileWriter API write() записывает содержимое в текстовый файл. Важно закрыть соединения BufferWriter и FileWriter. Если файл недоступен в указанном месте, нет прав на запись или проблема с доступом к этому файлу, будет выдано исключение.

Вывод

Запись в текстовый файл с помощью FileWriter построчно

В этом примере класс FileWriter используется для записи текстового файла. Здесь данные записываются построчно. Список массивов повторяется и читается один за другим и записывается в текстовый файл. Если мы хотим записать большой контент в один файл, читаем строку за строкой и пишем в файл вместо создания одной строки. BufferWriter будет поддерживать данные, которые должны быть отправлены быстро, и гарантирует, что при записи на постоянное запоминающее устройство, например на жесткий диск, не произойдет аппаратный сбой.

Вывод

Запись в текстовый файл с помощью FileOutputStream

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

Вывод

Запись в текстовый файл с помощью PrintWriter

Другой способ записи файла — использование класса PrintWriter. Класс PrintWriter используется для записи данных на любое печатающее устройство. Если вместо печатающего устройства настроен файл, данные сохраняются на постоянном запоминающем устройстве.

Вывод

Запись в текстовый файл с помощью NIO Files

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

Сегодня мы узнаем, как записать объект ArrayList в файл, а затем загрузить объект обратно в программу Java из этого файла. Это помогло бы нам сохранить данные для тестирования других функций, которые мы добавили в программу, без повторного ввода общих данных.

Во-первых, мы рассмотрим код ниже

<р>1. Поскольку нам нужно будет использовать множество классов внутри java.io, мы импортируем все внутри этой конкретной библиотеки.

<р>2. Создайте класс Person с 3 атрибутами, функцией-конструктором и переопределением метода toString для печати сведений об объекте, который мы инициализируем позже. Поскольку объекты этого класса будут использоваться для записи в файл и последующей загрузки обратно, нам необходимо реализовать интерфейс Serializable, чтобы указать Java, что этот класс можно сериализовать или десериализовать.

<р>3. внутри этих основных методов мы создадим 3 объекта класса Person. Затем мы создаем список людей с именами ArrayList и добавляем эти 3 объекта Person.

Теперь мы готовы записать этот Arraylist в файл.

Записать объект в файл.

Мы добавляем этот код в основной метод.

Поскольку запись и чтение данных могут вызвать ошибку, нам нужно использовать блок try-catch для обработки исключений, которые могут возникнуть.

FileOutputStream writeData = new FileOutputStream("peopledata.ser"): создает поток вывода файла для записи в файл, указанный в скобках. Вы можете указать путь к файлу, если хотите, в этом случае я просто даю имя файла, так что файл будет храниться в той же папке, что и файл .java

ObjectOutputStream writeStream = new ObjectOutputStream(writeData): ObjectOutputStream будет обрабатывать объект, который будет записан в файл, созданный FileOutputStream.

FileOutputStream и ObjectOutputStream должны объединяться для записи объекта в файл.

записьПоток.writeObject(people): скажите программе записать этот объект peple, который является ArrayList, который мы только что создали выше, в файл peopledata.ser
writeStream.flush(): использование метода flush здесь не обязательно, но рекомендуется использовать flush(), так как он сбрасывает все данные в потоке, убедитесь, что данные записаны в файл.
writeStream.close(); мы закрываем поток после завершения записи. Это также высвобождает системные ресурсы.

Откройте файл peopledata.ser и вы увидите, что там что-то написано. Не бойтесь, что вы не сможете его прочитать, Java сможет.

Чтение данных из файла

Запись завершена, теперь мы можем загрузить данные из файла для использования в нашей программе.

Добавьте приведенный ниже код к основному методу

Тем не менее, мы используем try-catch, чтобы гарантировать, что все исключения будут перехвачены.

FileInputStream readData = new FileInputStream("peopledata.ser") & ObjectInputStream readStream = new ObjectInputStream(readData): обратите внимание, что на этот раз мы используем Input вместо Ouput, так как мы хотим читать из файла в программу.

ArrayList people2 = (ArrayList) readStream.readObject(): мы создаем новый ArrayList people2 просто для того, чтобы убедиться, что это новый объект, отличный от существующего объекта people. Мы присваиваем значение, полученное из файла «peopledata.ser», и удостоверяемся, что мы преобразовали значение в ArrayList of Person.

readStream.close(): закрыть поток чтения.

System.out.println(people2.toString()): выведите новый ArrayList на консоль, чтобы убедиться, что все данные загружены правильно.

До Java 7 чтение текстового файла в ArrayList включало в себя много шаблонного кода, так как вам нужно читать файл построчно и вставлять каждую строку в ArrayList , но начиная с Java 7 вы можете использовать служебный метод Files.readAllLines() для чтения всех строк текстового файла в список. Этот метод возвращает список строк, содержащий все строки файлов. Позже вы можете преобразовать этот список в ArrayList, LinkedList или любой другой список, который вы хотите. Кстати, это четвертая статья из серии о чтении текстового файла на Java.

В предыдущих частях вы узнали, как читать файл с помощью Scanner и BufferedReader (1) . Затем чтение всего файла как строки (2) и, наконец, чтение текстового файла в массив (3). Эта программа не сильно отличается от других с точки зрения основ.

Мы по-прежнему будем использовать метод read() для решения Java 6 и будем читать весь текст, пока этот метод не вернет -1, что сигнализирует о конце файла.

Чтение текстового файла в ArrayList на Java — пример BufferedReader

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


Не забудьте закрыть BufferedReader, когда закончите, чтобы предотвратить утечку ресурсов, так как в Java 6 нет инструкции try-with-resource.

Чтение текстового файла в список на Java — пример Files.readAllLines

В Java 7 вам не нужно писать код для чтения и сохранения в ArrayList, просто вызовите метод Files.readAllLines(), и он вернет вам список String, где каждый элемент является соответствующей строкой из линия. Поскольку список представляет собой упорядоченную коллекцию, порядок строк в файле сохраняется в списке. Позже вы можете преобразовать этот список в ArrayList или любую другую реализацию.

вот пример кода для чтения текстового файла в список в JDK 7:


Метод readAllLines() принимает CharSet , вы можете использовать предопределенный набор символов, например. StandardCharsets.UTF_8 или StandardCharsets.UTF_16 . Вы также можете просмотреть эти бесплатные курсы Java, чтобы узнать больше о новых классах файловых утилит, представленных в Java 7 и 8.

Программа Java для чтения текстового файла в ArrayList

Вот полная программа на Java, демонстрирующая оба метода чтения текстового файла в ArrayList. Эта программа сначала научит вас делать это в JDK 7 или Java 8, используя метод Files.readAllLines(), а затем используя BufferedReader и ArrayList в Java 6 и более ранних версиях.

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

Затем просто щелкните правой кнопкой мыши и выберите "Запустить как программу Java". Убедитесь, что у вас есть файл .txt в пути к классам. Поскольку здесь я указал относительный путь, убедитесь, что вы поместили этот файл в каталог проекта Eclipse.

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


Это все о том, как читать текстовый файл в ArrayList в Java. Вы можете видеть, что это очень просто в Java 7 и Java 8, используя метод Files.readAllLines(). Хотя вы должны помнить о кодировке символов при чтении текстового файла в Java.

В Java 6 решение с использованием BufferedReader или Scanner также не очень сложно реализовать, но вам нужно помнить, что вы загружаете весь файл в память.

Если файл слишком большой и у вас недостаточно памяти, ваша программа умрет, выдав ошибку java.lang.OutOfMemoryError: Java Heap Space . Короче говоря, это решение подходит только для небольших файлов, для больших файлов вы всегда должны читать в потоковом режиме.

Существует множество способов чтения и записи файлов в Java.

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

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

Для этого можно использовать несколько разных подходов:

  • Файлы.readAllLines()
  • Чтение файлов
  • Сканер
  • Буферизованное чтение
  • ObjectInputStream
  • API потоков Java

Файлы.readAllLines()

Начиная с Java 7, можно очень просто загрузить все строки файла в список ArrayList:

При необходимости мы также можем указать набор символов для обработки различных форматов текста:

Files.readAllLines() автоматически открывает и закрывает необходимые ресурсы.

Сканер

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

Scanner – это простой в использовании инструмент для анализа примитивных типов и строк. Использование Scanner может быть настолько простым или сложным, насколько захочет разработчик.

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

разделитель – это последовательность символов, которую Сканер использует для разделения значений. По умолчанию в качестве разделителя используется ряд пробелов/табуляции (пробелы между значениями), но мы можем объявить собственный разделитель и использовать его для анализа данных.

Давайте посмотрим на пример файла:

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

Выполнение этого фрагмента кода даст нам ArrayList со следующими элементами:

С другой стороны, если бы мы использовали только разделитель по умолчанию (пробел), список ArrayList выглядел бы так:

Scanner имеет несколько полезных функций для анализа данных, таких как nextInt() , nextDouble() и т. д.

Важно: вызов .nextInt() НЕ вернет следующее значение int, которое можно найти в файле! Он вернет значение int только в том случае, если следующие элементы, которые сканер «сканирует», являются допустимым значением int, в противном случае будет выдано исключение. Простой способ убедиться, что исключение не возникнет, — это выполнить соответствующую проверку «имеет» — например, .hasNextInt() перед фактическим использованием .nextInt() .

Несмотря на то, что мы не видим, что при вызове таких функций, как scanner.nextInt() или scanner.hasNextDouble(), Scanner в фоновом режиме использует регулярные выражения.

Очень важно: чрезвычайно распространенная ошибка при использовании Scanner возникает при работе с файлами, состоящими из нескольких строк, и использовании .nextLine() в сочетании с .nextInt() , nextDouble() и т. д.< /p>

Давайте посмотрим на другой файл:

Часто новые разработчики, использующие Scanner, пишут такой код:

Бесплатная электронная книга: Git Essentials

Ознакомьтесь с нашим практическим руководством по изучению Git, включающим передовые практики, общепринятые стандарты и памятку. Перестаньте гуглить команды Git и на самом деле изучите их!

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

Если вы начнете отлаживать и печатать то, что отсканировали, вы увидите, что int загружен, но String s пуст.

Почему? Первое, на что следует обратить внимание, это то, что как только Scanner считывает что-то из файла, он продолжает сканирование файла, начиная с первого символа после ранее проверенных данных.

Например, если бы у нас было "12 13 14" в файле и мы вызвали .nextInt() один раз, сканер впоследствии сделал бы вид, что в файле есть только " 13 14".Обратите внимание, что пробел между «12» и «13» все еще присутствует.

Второе важное замечание: первая строка в нашем файле example.txt содержит не только число 12 , но и так называемый "символ новой строки", и на самом деле это 12\n вместо 12. .

На самом деле наш файл выглядит так:

Когда мы впервые вызываем .nextInt() , Scanner считывает только число 12 и оставляет первый \n непрочитанным.

.nextLine() затем считывает все символы, которые сканер еще не прочитал, пока не достигнет первого символа \n, который он пропускает, а затем возвращает прочитанные символы. Именно в этом проблема в нашем случае - у нас остался лишний символ \n после чтения 12 .

Поэтому, когда мы вызываем .nextLine(), мы получаем в результате пустую строку, поскольку Scanner не добавляет символ \n к возвращаемой строке.

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

Решения

  • Поскольку мы знаем, что именно не так в этом коде, мы можем жестко запрограммировать обходной путь. Мы просто «используем» символ новой строки между .nextInt() и .nextLine():
  • Учитывая, что мы знаем, как отформатирован файл example.txt, мы можем прочитать весь файл построчно и разобрать необходимые строки с помощью Integer.parseInt() :

Буферизованное чтение

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

Идея состоит в том, что когда мы вызываем .read() (или подобную операцию), мы, скорее всего, скоро снова прочитаем тот же блок данных, из которого мы только что прочитали, и поэтому "окружающие" данные сохраняются в буфер. Если бы мы хотели его прочитать, мы бы читали его непосредственно из буфера, а не с диска, что намного эффективнее.

Это подводит нас к тому, для чего хорош BufferedReader — чтению больших файлов. BufferedReader имеет значительно больший объем буферной памяти, чем Scanner (8192 символа по умолчанию и 1024 символа по умолчанию соответственно).

BufferedReader используется в качестве оболочки для других Reader, поэтому конструкторы для BufferedReader принимают в качестве параметра объект Reader, например FileReader .

Мы используем попытку с ресурсами, поэтому нам не нужно закрывать программу чтения вручную:

Рекомендуется оборачивать FileReader в BufferedReader именно из-за повышения производительности.

ObjectInputStream

ObjectInputStream следует использовать только вместе с ObjectOutputStream . Эти два класса помогают нам сохранить объект (или массив объектов) в файле, а затем легко прочитать его из этого файла.

Это можно сделать только с классами, реализующими интерфейс Serializable. Интерфейс Serializable не имеет методов или полей и служит только для определения семантики сериализуемости:

API потоков Java

Начиная с Java 8, другим быстрым и простым способом загрузки содержимого файла в ArrayList будет использование Java Streams API:

Однако имейте в виду, что этот подход, как и Files.readAllLines(), будет работать, только если данные хранятся в строках.

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

Мы можем легко сортировать/фильтровать/сопоставлять данные перед их сохранением в ArrayList:

Заключение

Существует несколько различных способов чтения данных из файла в список ArrayList. Когда вам нужно только прочитать строки как элементы, используйте Files.readAllLines ; когда у вас есть данные, которые можно легко проанализировать, используйте Scanner; при работе с большими файлами используйте FileReader, обернутый BufferedReader; при работе с массивом объектов используйте ObjectInputStream (но убедитесь, что данные были записаны с использованием ObjectOutputStream ).

ArrayList является частью структуры коллекции и присутствует в пакете java.util. Он предоставляет нам динамические массивы в Java. Хотя это может быть медленнее, чем стандартные массивы, но может быть полезно в программах, где требуется много манипуляций с массивом. Этот класс находится в пакете java.util.

Иллюстрация:

Пример. Следующая реализация демонстрирует, как создать и использовать ArrayList.

  • Создает память большего размера в памяти кучи (например, память двойного размера).
  • Копирует текущие элементы памяти в новую память.
  • Новый элемент добавлен сейчас, так как теперь доступно больше памяти.
  • Удалите старую память.
  • ArrayList наследует класс AbstractList и реализует интерфейс List.
  • ArrayList инициализируется размером. Однако размер увеличивается автоматически, если коллекция увеличивается или уменьшается, если объекты удаляются из коллекции.
  • Java ArrayList позволяет нам произвольно обращаться к списку.
  • ArrayList нельзя использовать для примитивных типов, таких как int, char и т. д. Для таких случаев нам нужен класс-оболочка.
  • ArrayList в Java можно рассматривать как вектор в C++.
  • ArrayList не синхронизирован. Его эквивалентный синхронизированный класс в Java — Vector.

Давайте подробно рассмотрим Java ArrayList. Посмотрите на изображение ниже:

  1. AbstractList: этот класс используется для реализации неизменяемого списка, для которого нужно только расширить этот класс AbstractList и реализовать только get() и size() методы.
  2. CopyOnWriteArrayList: этот класс реализует интерфейс списка. Это расширенная версия ArrayList, в которой все модификации (добавление, установка, удаление и т. д.) осуществляются путем создания новой копии списка.
  3. AbstractSequentialList: этот класс реализует интерфейс Collection и класс AbstractCollection. Этот класс используется для реализации немодифицируемого списка, для которого нужно только расширить этот класс AbstractList и реализовать только методы get() и size().

Конструкторы в ArrayList

Чтобы создать ArrayList, нам нужно создать объект класса ArrayList. Класс ArrayList состоит из различных конструкторов, которые позволяют создавать список массивов. В этом классе доступны следующие конструкторы:

<р>1. ArrayList(): этот конструктор используется для создания пустого списка массивов. Если мы хотим создать пустой ArrayList с именем arr, то его можно создать как:

<р>2. ArrayList(Collection c): Этот конструктор используется для создания списка массивов, инициализированных элементами из коллекции c. Предположим, мы хотим создать ArrayList arr, который содержит элементы, присутствующие в коллекции c, тогда его можно создать как:

<р>3. ArrayList(int capacity): Этот конструктор используется для создания списка массивов с указанием начальной емкости. Предположим, мы хотим создать ArrayList с начальным размером N, тогда его можно создать как:

Методы в Java ArrayList

Примечание. Вы также можете создать общий список ArrayList:

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