- Чтение и запись файлов
- Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Re: Java работа с файлами
- Работа с Java в командной строке
- От простого к .
- Один файл
- Отделяем бинарные файлы от исходников
- Используем пакеты
- Если в программе несколько файлов
- Если удивляет результат
- Хорошо бы протестировать
- Создадим библиотеку
- Надо узнать, что у библиотеки внутри
- Лучше снабдить библиотеку документацией
- Можно подписать jar-архив
- Использование библиотеки
- Собираем программу
- Первый способ
- Второй способ
- Третий способ
- Запуск исполняемого jar-файла
- Как быть с приложениями JavaEE
Чтение и запись файлов
В 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 будет создан внутри адаптера. Пример побайтового копирования файла:
Если используются относительные адреса, они должны начинаться от корня проекта.
В конструктор FileOutputStream можно также передать второй аргумент true. В этом случае, если файл существует, данные в него будут добавляться. Перезаписи файла не произойдет.
Метод available() объекта класса FileInputStream возвращает количество непрочитанных байтов. Метод read() читает один байт и расширяет его до типа int. Кроме этого, есть другой метод read(), читающий массив байт в переменную-аргумент и возвращающий количество реально прочитанных байт. Метод write() также позволяет записывать блоками.
При чтении конца файла блок может содержать меньше прочитанных байт, чем размерность массива. Поэтому write() позволяет указывать срез массива.
У объектов FileOutputStream имеется метод flush(), который принудительно записывает находящиеся в буфере байты на диск. При вызове close() это происходит автоматически.
С помощью класса PrintStream также можно создать поток вывода в файл. PrintStream является наследником FilterOutputStream, который в свою очередь наследник OutputStream как и FileOutputStream.
Функция printf() предназначена для форматированного вывода.
Заметим, переменная System.out является объектом типа PrintStream.
В работе с вводом-выводом также используется другой паттерн проектирования – обертка (wrapper), он же декоратор (decorator). Декоратор расширяет функциональность объекта, а не приспосабливает объект к какому-либо стороннему интерфейсу.
Поэтому класс-обертка наследуется от того же класса или интерфейса, что и оборачиваемый объект. В классе-обертке переопределяются методы оборачиваемого объекта. В методах обертки вызываются методы оборачиваемого класса и вводится дополнительная функциональность.
В основной ветке создается объект оборачиваемого класса, который передается в конструктор обертки. Внутри класса-обертки есть поле типа декорируемого класса. Этому полю присваивается переданный объект.
BufferedInputStream – класс-обертка для InputStream (наследует через FilterInputStream). В отличие от InputStream класс BufferedInputStream позволяет предварительно читать в буфер порции байт, что уменьшает количество обращений к файлу. Существует также BufferedOutputStream.
Конструктор класса BufferedInputStream принимает объект InputStream или его наследника.
Хотя данные считываются блоками, метод read() извлекает их по одному. Однако в данном случае он будет извлекать их из буфера.
С помощью классов FileReader и FileWriter выполняется ввод-вывод в текстовые файлы.
Метод ready() возвращает истину, если остались непрочитанные символы.
Читать и писать можно блоками. Также методу write() можно передать строку:
Рассматривая ввод данных с клавиатуры, мы уже использовали класс BufferedReader, который наследуется от Reader и позволяет читать отдельные строки методом readLine(). Его также можно использовать для построчного чтения файлов:
Источник
Java работа с файлами
Подскажите, пожалуйста, есть ли в Java более-менее удобные библиотеки для работы с файловой системой. Ну файлики там скопировать-переместить-удалить. Не плохо бы и рекурсивную обработку каталогов там увидеть. И кроссплатформенно все это дело бы.
Что-то поискал в гугле — пока не нашел ничего приличного.
Re: Java работа с файлами
> Ну файлики там скопировать-переместить-удалить.
Re: Java работа с файлами
Re: Java работа с файлами
>> Ну файлики там скопировать-переместить-удалить.
Удалить можно, переместить с горем пополам (в пределах одной файловой системы) тоже.
А скопировать? Никак? Только прочитать поток байт и записать в новый файл??
Re: Java работа с файлами
Re: Java работа с файлами
> А в чём проблема?
Да нет, проблемы нет, просто я никогда не писал на Java и подобный метод показался мне странным.
Т.е. это стандартный метод копирования файлов? Я как-то видел тут — на лоре — топик, в котором обсуждали файловый менеджер на Java. Получается, что и целые каталоги он копирует рекурсивным применением этого метода и созданием подкаталогов?
Re: Java работа с файлами
А как вы копировали каталоги на том языке на котором вы писали раньше?
Re: Java работа с файлами
Re: Java работа с файлами
мне тоже странно. зачем трасферить? почему не примитив ОС аля файл.цп(«сюда»)? это вечная беда явы: все делается в общем случае и примитивные задачи становятся сложными :/
Re: Java работа с файлами
Это совсем не беда. Общность дает свои немалые приемущества. Когда долго программируешь на яве. Если понять яву и привыкнуть к ней, то некоторые вещи можно делать и без документации. Они просто становятся интуитивно понятными. Плюс, конечно, хорошая IDE с автокомплитом.
Re: Java работа с файлами
это огромная беда! ява разучивает решать проблемы здесь и сейчас. мне нужно скопировать файл. почему я должен таскать байты, а не ось? почему питон может, а жабе мешает общность? более того, в том же питоне файл можно скопировать как раз-таки без документации.
и об интуитивности. почему для того, чтоб свинговая таблца выходила из режима редактирования при потере фокуса, я должен ей сказать
никакой автокомплит не поможет, этот воркэраунд тянется с 1.4
Re: Java работа с файлами
> это огромная беда! ява разучивает решать проблемы здесь и сейчас. мне нужно скопировать файл. почему я должен таскать байты, а не ось?
А как ось будет копировать файлы? Я чего то упустил, уже появился такой системный вызов?
Претензии конечно логичные и правильные, но, по сути, подобный метод пишется один раз в каких-нибудь Utils-ах и проблема забывается. Главное — чтобы все знали про этот метод 🙂
Re: Java работа с файлами
конечно же, формально, ось не копирует:) и конечно же, подобный метод уйдет в утилсы. но в том же питоне оно есть сразу.
ЗЫ я не фанат питона, и большая част мною написанного кода — жабная
Re: Java работа с файлами
Тут с вами нельзя не согласится. Некоторые вещи в Java сделаны не то что бы совсем очевидно, но согласитесь, Java, как язык, достаточно стройна. Возможно есть неочевидности. Но где их нет?
Я не защищаю ни Sun, ни Java, но мне кажется, что вы черезчур категоричны.
Источник
Работа с Java в командной строке
От простого к .
Каждая программа обычно содержится в отдельном каталоге. Я придерживаюсь правила создавать в этом каталоге по крайней мере две папки: src и bin. В первой содержатся исходные коды, во второй — результат компиляции. В данных папках будет структура каталогов, зависящая от пакетов.
Один файл
Можно сделать и без лишних папок.
Берем сам файл HelloWorld.java.
Переходим в каталог, где лежит данный файл, и выполняем команды.
В данной папке появится файл HelloWorld.class. Значит программа скомпилирована. Чтобы запустить
Отделяем бинарные файлы от исходников
Теперь сделаем тоже самое, но с каталогами. Создадим каталог HelloWorld и в нем две папки src и bin.
Компилируем
Здесь мы указали, что бинарные файлы будут сохраняться в отдельную папку bin и не путаться с исходниками.
Используем пакеты
А то, вдруг, программа перестанет быть просто HelloWorld-ом. Пакетам лучше давать понятное и уникальное имя. Это позволит добавить данную программу в другой проект без конфликта имен. Прочитав некоторые статьи, можно подумать, что для имени пакета обязательно нужен домен. Это не так. Домены — это удобный способ добиться уникальности. Если своего домена нет, воспользуйтесь аккаунтом на сайте (например, ru.habrahabr.mylogin). Он будет уникальным. Учтите, что имена пакетов должны быть в нижнем регистре. И избегайте использования спецсимволов. Проблемы возникают из-за разных платформ и файловых систем.
Поместим наш класс в пакет с именем com.qwertovsky.helloworld. Для этого добавим в начало файла строчку
В каталоге src создадим дополнительные каталоги, чтобы путь к файлу выглядел так: src/com/qwertovsky/helloworld/HelloWorld.java.
Компилируем
В каталоге bin автоматически создастся структура каталогов как и в src.
Если в программе несколько файлов
HelloWorld.java
Calculator.java
Adder.java
Ошибка возникла из-за того, что для компиляции нужны файлы с исходными кодами классов, которые используются (класс Calculator). Надо указать компилятору каталог с файлами с помощью ключа -sourcepath.
Компилируем
Если удивляет результат
Есть возможность запустить отладчик. Для этого существует jdb.
Сначала компилируем с ключом -g, чтобы у отладчика была информация.
Отладчик запускает свой внутренний терминал для ввода команд. Справку по последним можно вывести с помощью команды help.
Указываем точку прерывания на 9 строке в классе Calculator
Запускаем на выполнение.
Чтобы соориентироваться можно вывести кусок исходного кода, где в данный момент находится курссор.
Узнаем, что из себя представляет переменная а.
Выполним код в текущей строке и увидим, что sum стала равняться 2.
Поднимемся из класса Adder в вызвавший его класс Calculator.
Удаляем точку прерывания
Можно избежать захода в методы, используя команду next.
Проверяем значение выражения и завершаем выполнение.
Хорошо бы протестировать
Запускаем. В качестве разделителя нескольких путей в classpath в Windows используется ‘;’, в Linux — ‘:’. В консоли Cygwin не работают оба разделителя. Возможно, должен работать ‘;’, но он воспринимается как разделитель команд.
Создадим библиотеку
Класс Calculator оказался полезным и может быть использован во многих проектах. Перенесем всё, что касается класса Calculator в отдельный проект.
Измените также назавания пакетов в исходных текстах. В HelloWorld.java нужно будет добавить строку
Делаем архив jar
С помощью ключа -C мы запустили программу в каталоге bin.
Надо узнать, что у библиотеки внутри
Можно распаковать архив zip-распаковщиком и посмотреть, какие классы есть в библиотеке.
Информацию о любом классе можно получить с помощью дизассемблера javap.
Из результата видно, что класс содержит кроме пустого конструктора, ещё один метод sum, внутри которого в цикле вызывается метод add класса Adder. По завершении метода sum, вызывается Adder.getSum().
Без ключа -c программа выдаст только список переменных и методов (если использовать -private, то всех).
Лучше снабдить библиотеку документацией
Изменим для этого класс калькулятора.
Документацию можно создать следующей командой. При ошибке программа выдаст список возможных опций.
В результате получиться следующее
Можно подписать jar-архив
Если требуется подписать свою библиотеку цифровой подписью, на помощь придут keytool и jarsigner.
Генерируем подпись.
Генерируем Certificate Signing Request (CSR)
Содержимое полученного файла отправляем в центр сертификации. От центра сертификации получаем сертификат. Сохраняем его в файле (например, qwertokey.cer) и импортируем в хранилище
Файл qwertokey.cer отправляем всем, кто хочет проверить архив. Проверяется он так
Использование библиотеки
Есть программа HelloWorld, которая использует библиотечный класс Calculator. Чтобы скомпилировать и запустить программу, нужно присоединить библиотеку.
Компилируем
Собираем программу
Это можно сделать по-разному.
Первый способ
Здесь есть тонкости.
В строке
не должно быть пробелов в конце.
Вторая тонкость описана в [3]: в этой же строке должен стоять перенос на следующую строку. Это если манифест помещается в архив сторонним архиватором.
Программа jar не включит в манифест последнюю строку из манифеста, если в конце не стоит перенос строки.
Ещё момент: в манифесте не должно быть пустых строк между строками. Будет выдана ошибка «java.io.IOException: invalid manifest format».
При использовании команды echo надо следить только за пробелом в конце строки с main-class.
Второй способ
В данном способе избегаем ошибки с пробелом в main-class.
Третий способ
Включили код нужной библиотеки в исполняемый файл.
Запуск исполняемого jar-файла
Файл calculator.jar исполняемым не является. А вот helloworld.jar можно запустить.
Если архив был создан первыми двумя способами, то рядом с ним в одном каталоге должна находится папка lib с файлом calculator.jar. Такие ограничения из-за того, что в манифесте в class-path указан путь относительно исполняемого файла.
При использовании третьего способа нужные библиотеки включаются в исполняемый файл. Держать рядом нужные библиотеки не требуется. Запускается аналогично.
Как быть с приложениями JavaEE
Аналогично. Только библиотеки для компиляции нужно брать у сервера приложений, который используется. Если я использую JBoss, то для компиляции сервлета мне нужно будет выполнить примерно следующее
Структура архива JavaEE-приложения должна соответствовать определенному формату. Например
Способы запуска приложения на самом сервере с помощью командной строки для каждого сервера различны.
Надеюсь, данная статья станет для кого-нибудь шпаргалкой для работы с Java в командной строке. Данные навыки помогут понять содержание и смысл Ant-скриптов и ответить на собеседовании на более каверзные вопросы, чем «Какая IDE Вам больше нравится?».
Источник