Чтение и запись файлов
В Java есть четыре основных абстрактных класса, реализующих потоки ввода-вывода: InputStream, OutputStream, Reader, Writer. Первые два работают с байтами, вторые – с символами.
Для работы с файлами от этих абстрактных классов созданы соответственно классы FileInputStream, FileOutputStream, FileReader, FileWriter. Они являются адаптерами для объектов класса File к «интерфейсам» InputStream, OutputStream, Reader, Writer, т. е. к их методам.
Скажем несколько слов об адаптере как паттерне, или шаблоне, проектирования. Класс-адаптер A наследуется от интерфейса B, к которому приспосабливается объект другого класса – C. Класс-адаптер A имеет поле типа класса объекта C.
Например, объект File адаптируется к потоку ввода InputStream, т. е. все, что мы хотим получить из File, в конечном итоге мы будем получать из InputStream. Фактически мы работаем с InputStream, через адаптер FileInputStream, который с одной стороны наследуется от InputStream, а с другой – имеет поле, которому присваивается объект File.
Адаптер выполняет работу по получению данных из файла и адаптации их к тому виду, который можно передать в методы InputStream. Класс-адаптер, в данном примере – FileInputStream, переопределяет методы InputStream, добавляя в них свой код.
В основной ветке сначала создается объект, для которого требуется адаптер. Затем создается переменная класса, к которому выполняется адаптация. Этой переменной присваивается объект класса-адаптера, в конструктор которого передается адаптируемый объект.
File file = new File("/home/user/pic.jpg"); InputStream fIn = new FileInputStream(file);
Часто переменную определяют самим классом-адаптером:
FileInputStream fIn = new FileInputStream(file);
В конструктор можно передать строку-адрес. Объект File будет создан внутри адаптера. Пример побайтового копирования файла:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class InputOutputStream public static void main(String[] args) throws IOException FileInputStream fileIn = new FileInputStream( "src/file/pets.png"); FileOutputStream fileOut = new FileOutputStream( "src/file/pets2.png"); while (fileIn.available() > 0) int oneByte = fileIn.read(); fileOut.write(oneByte); > fileIn.close(); fileOut.close(); > >
Если используются относительные адреса, они должны начинаться от корня проекта.
В конструктор FileOutputStream можно также передать второй аргумент true. В этом случае, если файл существует, данные в него будут добавляться. Перезаписи файла не произойдет.
Метод available() объекта класса FileInputStream возвращает количество непрочитанных байтов. Метод read() читает один байт и расширяет его до типа int. Кроме этого, есть другой метод read(), читающий массив байт в переменную-аргумент и возвращающий количество реально прочитанных байт. Метод write() также позволяет записывать блоками.
byte[] blockBytes = new byte[100]; while (fileIn.available() > 0) int qtyBytes = fileIn.read(blockBytes); fileOut.write(blockBytes, 0, qtyBytes); >
При чтении конца файла блок может содержать меньше прочитанных байт, чем размерность массива. Поэтому write() позволяет указывать срез массива.
У объектов FileOutputStream имеется метод flush(), который принудительно записывает находящиеся в буфере байты на диск. При вызове close() это происходит автоматически.
С помощью класса PrintStream также можно создать поток вывода в файл. PrintStream является наследником FilterOutputStream, который в свою очередь наследник OutputStream как и FileOutputStream.
import java.io.FileNotFoundException; import java.io.PrintStream; public class PrintStreamTest public static void main(String[] args) throws FileNotFoundException PrintStream fileOut = new PrintStream( "src/file/text.txt"); fileOut.println(10.5); fileOut.printf( "%s - %d - %f", "hi", 10, 1.1); fileOut.close(); > >
Функция printf() предназначена для форматированного вывода.
Заметим, переменная System.out является объектом типа PrintStream.
В работе с вводом-выводом также используется другой паттерн проектирования – обертка (wrapper), он же декоратор (decorator). Декоратор расширяет функциональность объекта, а не приспосабливает объект к какому-либо стороннему интерфейсу.
Поэтому класс-обертка наследуется от того же класса или интерфейса, что и оборачиваемый объект. В классе-обертке переопределяются методы оборачиваемого объекта. В методах обертки вызываются методы оборачиваемого класса и вводится дополнительная функциональность.
В основной ветке создается объект оборачиваемого класса, который передается в конструктор обертки. Внутри класса-обертки есть поле типа декорируемого класса. Этому полю присваивается переданный объект.
BufferedInputStream – класс-обертка для InputStream (наследует через FilterInputStream). В отличие от InputStream класс BufferedInputStream позволяет предварительно читать в буфер порции байт, что уменьшает количество обращений к файлу. Существует также BufferedOutputStream.
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class BufferStream public static void main(String[] args) throws IOException FileInputStream fileIn = new FileInputStream("src/file/text.txt"); BufferedInputStream bufIn = new BufferedInputStream(fileIn, 100); int i; while((i = bufIn.read())!= -1) System.out.print((char)i); > > >
Конструктор класса BufferedInputStream принимает объект InputStream или его наследника.
Хотя данные считываются блоками, метод read() извлекает их по одному. Однако в данном случае он будет извлекать их из буфера.
С помощью классов FileReader и FileWriter выполняется ввод-вывод в текстовые файлы.
FileReader reader = new FileReader( "src/file/text.txt"); FileWriter writer = new FileWriter( "src/file/text2.txt"); while (reader.ready()) int c = reader.read(); writer.write(c); > reader.close(); writer.close();
Метод ready() возвращает истину, если остались непрочитанные символы.
Читать и писать можно блоками. Также методу write() можно передать строку:
FileReader reader = new FileReader( "src/file/text.txt"); FileWriter writer = new FileWriter( "src/file/text3.txt"); char[] buff = new char[10]; while (reader.ready()) int qtySymbols = reader.read(buff); writer.write(buff, 0, qtySymbols); > writer.write("Halo"); reader.close(); writer.close();
Рассматривая ввод данных с клавиатуры, мы уже использовали класс BufferedReader, который наследуется от Reader и позволяет читать отдельные строки методом readLine(). Его также можно использовать для построчного чтения файлов:
import java.io.*; public class BufferedReaderTest public static void main(String[] args) throws IOException Reader reader = new FileReader( "src/file/text.txt"); BufferedReader buffReader = new BufferedReader(reader); while (buffReader.ready()) System.out.println( buffReader.readLine()); > reader.close(); buffReader.close(); > >
Существует и BufferedWriter.
Программирование на Java. Курс
Чтение файла с конца
Как заменить чтение строки из консоли на чтение текстового файла?
основное задание: найти частоту суффикса (например, "ing") в текстовом документе. в.
Чтение чисел из файла. Чтение после конца потока невозможно
Товарищи, помогите. В Pascal’e я не силен, так что не бейте меня ногами, но есть задача: написать.
Внешняя сортировка бинарного файла (чтение после конца файла невозможно)
Помогите отладить программу, не вижу, что здесь можно сделать. Похоже, курсор файла где-то в коде.
Вывод из файла в QTableWidget, построчное чтение с конца файла
Привет! Делаю первые шаги в Qt, собственно поэтому без проблем никуда. Моя задача на данный.
Nightwalker,
1. Читаем весь файл в колекцию
2. удаляем первых n и последних n елементов колекции
3. наслаждаемся жизнью
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public static void main(String[] args){ int dell = 2;// количество нечитаемых строк try { Scanner sc = new Scanner(new File("YourFile.txt")); ArrayListString> read = new ArrayListString>(); while(sc.hasNext()){ read.add(sc.nextLine()); } for(int i = 0; i dell; i++){ read.remove(0); read.remove(read.size() - 1); } //а дальше с колекцием делаем шо хотим, лепим стринг, записываем, издеваемся. //приятного вам допиливания. } catch (FileNotFoundException ex) { Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); } }
Считывание из файла последней строки
Надо определить последнюю строчку, и взять из нее значение 7348537A889PB5, файл всегда обновляется строки добавляются в конец файла.
Считывание строки из файла до точки
Доброго времени суток 🙂 Вопрос вот в чем, у меня есть файл с текстом. Нужно считывать текст и.
Считывание файла в массив без последней строки
Интересует вопрос, как считывать txt в list БЕЗ последней строки. Мой код который записывает txt.
Считывание последней строки со спец-символом ‘\r’ из текстового файла
Всем привет! Проблема состояла в том, что моя программа неправильно считывала последнее число в.
Функция: сравнение первой строки первого текстового файла и последней строки второго файла
Даны два текстовый файла, состоящие из некоторого количества строк. Написать функцию для сравнения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public boolean isValidFile(String filename){ try { FileInputStream fis = new FileInputStream(filename); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String str1; String str2; while ((str1 = br.readLine()) != null) { str2 = str1; } if (str1.contains("some regexp")){ return true; }else{ return false; } } catch (IOException e) { log.error("IOException occured",e); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
private String getLastLine(final File aFile) { String line = null; String tmp = null; BufferedReader in = null; try { in = new BufferedReader(new FileReader(aFile)); while ((tmp = in.readLine()) != null) { line = tmp; } } catch (FileNotFoundException exception) { LOGGER.error("", exception); } catch (IOException exception) { LOGGER.error("", exception); } finally { IOUtils.closeQuietly(in); } return line; }
На файле в 150Мбайт оба варианта мучаются около секунды, т.к. перебирают весь файл.
На базе RandomAccessFile последняя строка из того же файла получается за пару миллисекунд.
1 2 3 4 5 6 7 8 9 10 11 12 13
private static String ReadLastLine(File file) throws FileNotFoundException, IOException } return result; }
Сообщение от kotelok
private static String ReadLastLine(File file) throws FileNotFoundException, IOException RandomAccessFile raf = new RandomAccessFile(file, "r"); String result = null; long startIdx = file.length(); while (result == null return result; }
Если честно, то я про RandomAccessFile сам узнал только что, попытавшись решить эту задачу.
http://docs.oracle.com/javase/. sFile.html
На практике оказалось, что он реализует достаточно эффективный доступ доступ к файлам по позиции. По крайней мере в сравнении с последовательным перебором всех строк.
По коду — встаём в самый конец файла и пытаемся считать две строки. Если вторая считалась успешно (не null и не пустая), то значит она и есть последняя строка файла. Если не считалась, то повторяем попытку с позиции на единицу меньше, чем конец файла. И так пока не достигнем успеха.
P.S.: но там кривовато получилось. Если в файле всего одна строка или вообще строк нет, то будет беда. Сейчас доработаю.