Разработка консольных java-приложений
В данной лабораторной работе разрабатывается консольное приложение для реализации простейшего приложения с использованием массивов, строк и файлов.
Указания к работе
Консольное приложение Java представляет собой откомпилированный класс, содержащий точку входа.
Рассмотрим простой пример:
Здесь класс First используется только для того, чтобы определить метод main(), который и является точкой входа и с которого начинается выполнения программы интерпретатором Java. Метод main() содержит аргументы-параметры командной строки String[] args в виде массива строк и является открытым (public) членом класса. Это означает, что метод main() виден и доступен любому классу. Ключевое слово static объявляет методы и переменные класса, используемые для работы с классом в целом, а не только с объектом класса. Символы верхнего и нижнего регистров в Java различаются, чем Java напоминает языки C/C++ и PHP.
Вывод строки «Первая программа на Java!» в примере осуществляет метод println() (ln – переход к новой строке после вывода) свойства out класса System, который доступен в программе автоматически вместе с пакетом java.lang. Приведенную программу необходимо поместить в файл, имя которого совпадает с именем класса и с расширением java. Простейший способ компиляции написанной программы – вызов строчного компилятора:
При успешной компиляции создается файл First.class. Этот файл можно запустить на исполнение из командной строки с помощью интерпретатора Java следующим образом:
Для разработки программы возможно использование и специальных средств разработчика.
Ниже рассмотрены основные классы, используемые при выполнении лабораторной работы, рассмотрен пример решения одного из заданий.
Класс java.io.File
Для работы с файлами в приложениях Java могут быть использованы классы из пакета java.io, одним из которых является класс File.
Класс File служит для хранения и обработки в качестве объектов каталогов и имен файлов. Этот класс не описывает способы работы с содержимым файла, но позволяет манипулировать такими свойствами файла, как права доступа, дата и время создания, путь в иерархии каталогов, создание, удаление, изменение имени файла и каталога и т.д.
Основные методы класса File и способы их применения рассмотрены в следующем примере.
import java.io.*; import java.util.*; public class Main < public static void main(String[] args) throws IOException /*отказ от обработки исключения в main()*/ < //с объектом типа File ассоциируется файл на диске File fp = new File( "com\\learn\\FileTest.java" ); // другие способы создания объекта //File fp = new File("\\com\\learn", "FileTest.java"); //File fp=new File("d:\\temp\\demo.txt"); //File fp=new File("demo.txt"); if(fp.isFile())/если>if(fp.createNewFile()) < System.out.println("Файл " + fp.getName() + " создан"); >if(fp.exists()) < System.out.println("temp файл "+ fp.getName() + " существует"); >else System.out.println("temp файл " + fp.getName() + " не существует"); //в объект типа File помещается каталог\директория File dir = new File( "com\\learn" ); if (dir.isDirectory())/*если объект объявлен как каталог на диске*/ System.out.println("Директория!"); if(dir.exists())/если> > > >
У каталога (директории) как объекта класса File есть дополнительное свойство – просмотр списка имен файлов с помощью методов list(), listFiles(), listRoots().
Класс System
Класс System содержит набор полезных статических методов и полей системного уровня. Экземпляр этого класса не может быть создан или получен.
Наиболее широко используемой возможностью, предоставляемой System, является стандартный вывод, доступный через переменную System.out. Стандартный вывод можно перенаправить в другой поток (файл, массив байт и т.д., главное, чтобы это был объект PrintStream, смотри документацию JSDK: http://docs.oracle.com/javase/6/docs/api/ ):
public static void main(String[] args) < System.out.println("Study Java"); try < PrintStream print = new PrintStream(new FileOutputStream("d:\\file2.txt")); System.setOut(print); System.out.println("Study well"); >catch(FileNotFoundException e) < e.printStackTrace(); >>
При запуске этого кода на экран будет выведено только:
И в файл «d:\file2.txt» будет записано:
Аналогично могут быть перенаправлен стандартный ввод System.in – вызовом System.setIn(InputStream) и поток вывода сообщений об ошибках System.err – вызовом System.setErr (по умолчанию все потоки – in, out, err – работают с консолью приложения).
Класс String
Класс String содержит основные методы для работы со строками:
В следующем примере массив символов и целое число преобразуются в объекты типа String с использованием методов этого класса.
public class DemoString < public static void main(String[] args) < char s[] = < 'J', 'a', 'v', 'a' >; int i = 2; // комментарий содержит результат выполнения кода String str = new String(s); // str ="Java" i = str.length(); // i=4 String num = String.valueOf(2); // num="2" str = str.toUpperCase(); // str="Java" num = str.concat(num); // num="Java2" str = str + "C";// str="JavaC"; char ch = str.charAt(2); // ch='V' i = str.lastIndexOf( 'A' ); // i=3 (-1 если отсутвствует ) num = num.replace('2', 'H'); // num="JavaH" i = num.compareTo(str); // i=5 ( между символами 'H' и ' С ') str.substring(0, 3).toLowerCase(); // java > >
Пример консольного java-приложения
Задание: Ввести n строк с консоли. Вывести на консоль строки и их длины, упорядоченные по возрастанию.
import java.io.IOException; import java.util.InputMismatchException; import java.util.Scanner; public class Main < public static void main(String[] args) < int n = 0; while ( true ) // ввод числа строк < System.out.println("Введите число строк"); Scanner sc1 = new Scanner(System. in ); try < n = sc1.nextInt(); break; >catch(InputMismatchException fg) < // если введенное значение не является числом System.out.print("Вы ввели не число. " ); >> // создание массива строк String[] str = new String[n]; Scanner sc2 = new Scanner(System.in); for (int i = 0; i < n; i++) < System. out.println( " Введите строку №" + (i+1)); str[i] = sc2.nextLine(); >//сортировка массива строк по длине for ( int i = 0; i < str. length -1; i++) < for (int j = i+1; j < str.length; j++) < if (str[i].length()> > int maxlength = str[0].length(); System.out.println("Строки в порядке убывания длины:"); for ( int i = 0; i < str. length ; i++) < System.out.print(str[i]); for (int j = 0; j < maxlength - str[i].length(); j++) System.out.print(" "); System. out.println( " её длина = " + str[i].length()); >> >
Задания к лабораторной работе
- Ввести n строк с консоли, найти самую короткую строку. Вывести эту строку и ее длину.
- Ввести n строк с консоли. Упорядочить и вывести строки в порядке возрастания их длин, а также (второй приоритет) значений этих их длин.
- Ввести n строк с консоли. Вывести на консоль те строки, длина которых меньше средней, также их длины.
- В каждом слове текста k-ю букву заменить заданным символом. Если k больше длины слова, корректировку не выполнять.
- В русском тексте каждую букву заменить ее номером в алфавите. В одной строке печатать текст с двумя пробелами между буквами, в следующей строке внизу под каждой буквой печатать ее номер.
- Из небольшого текста удалить все символы, кроме пробелов, не являющиеся буквами. Между последовательностями подряд идущих букв оставить хотя бы один пробел.
- Из текста удалить все слова заданной длины, начинающиеся на согласную букву.
- В тексте найти все пары слов, из которых одно является обращением другого.
- Найти и напечатать, сколько раз повторяется в тексте каждое слово.
- Найти, каких букв, гласных или согласных, больше в каждом предложении текста.
- Выбрать три разные точки заданного на плоскости множества точек, составляющие треугольник наибольшего периметра.
- Найти такую точку заданного на плоскости множества точек, сумма расстояний от которой до остальных минимальна.
- Выпуклый многоугольник задан на плоскости перечислением координат вершин в порядке обхода его границы. Определить площадь многоугольника.
ЛР №1. Консольные приложения
Как написать простое консольное приложение с аргументами на Java
В данном посте я хочу рассказать , как создать простое консольное приложение на Java с использованием библиотеки args4j.
Не давно мне дали задание написать консольную утилиту при помощи библиотеки для парсинга аргументов. Я выбрал args4j и хочу поделиться своим опытом.
Разработать консольную утилиту, которая соединяет заданные в командной строке входные текстовые файлы в выходной, указываемый после ключа -out. С ключом -u делает обратную операцию, принимая один входной файл и разбивая его на несколько. Выходной файл тоже является текстовым. Придумать для него формат, позволяющий запоминать имена входных файлов и находить их границы. Command Line: tar -u filename.txt или tar file1.txt file2.txt … -out output.txt.
Сначала надо подключить зависимость, я использовал Maven. Тут все простенько:
Теперь можно реализовать парсинг аргументов. Создадим класс Parser и добавим туда две переменные и список для остальных аргументов.
Аннотация сверху дает понять библиотеке args4j, где хранить аргументы , значения опций и всякое , в общем все прям для ленивых. Сейчас будет чуть сложнее, нужно осмыслить то , что получили из консоли:
public static void main(String[] args) < new Parser().run(args); >private void run(String[] args) < CmdLineParser parser = new CmdLineParser(this); try < parser.parseArgument(args); if ((arguments == null && out != null) || (u != null && out != null)) < System.err.println("Ошибка ввода аргументов!"); System.err.println("tar [опции. ] аргументы. "); System.err.println("\nПример: tar -u \"filename.txt\" \n tar \"file1.txt file2.txt\" -out output.txt"); throw new IllegalArgumentException(""); >if (out != null) < new Delimiter().tar(arguments.split(" "), out); >else < if((u!=null && !Objects.requireNonNull(u).exists()) )< throw new IOException("Папки или файла не существует"); >new Delimiter().tar(u); > > catch (CmdLineException | IOException e) < System.err.println(e.getMessage()); System.exit(1); >>
В данном кусочке в основном можно обойтись самой популярной комбинацией клавиш у программистов , но я все же попробую часть разжевать. В начале стоит понимать , что мои проверки могут вам не подойти (9 строчку скорее всего придется переделать) там просто проверяю правильно ли пользователь ввел аргументы и если да , то смотрю , что дальше с ними делать. Если опция -out активирована, то идем в эту часть кода:
public void tar(String[] arguments, String out) throws IOException, CmdLineException < File f = new File(out); FileWriter writer; StringBuilder builder; if (f.createNewFile()) < writer = new FileWriter(f); for (String argument : arguments) < if(new File(argument).exists()) < FileReader fr = new FileReader(argument); BufferedReader reader = new BufferedReader(fr); builder = new StringBuilder(); int countLines = 0; String temp; while ((temp = reader.readLine()) != null) < builder.append(temp).append("\n"); countLines++; >writer.write(argument + " " + countLines + "\n"); writer.write(builder.toString()); >else < System.out.println("Неверный аргумент "+ argument + "\n пример: \"text1.txt text2.txt\" -out text3.txt"); >> writer.close(); > else < throw new IOException("Не возможно создать новый файл"); >>
Предварительно создал новый класс Delimiter и написал две простенькие функции. Не думаю , что кому-то это сильно пригодится , да и тут в принципе не сложно , так что рассказывать не буду. Второй метод (просто перегрузил метод tar) :
public void tar(File u) throws IOException < FileReader fr = new FileReader(u); BufferedReader reader = new BufferedReader(fr); String buf = reader.readLine(); FileWriter writer; if(buf.matches("([A-Za-z0-9-_.]+/?)+ 5+")) < while (buf != null) < String[] data = buf.trim().split(" "); String name = data[0]; int size = Integer.parseInt(data[1]); File f = new File(name); if (f.createNewFile()) < StringBuilder builder = new StringBuilder(); writer = new FileWriter(f); for (int i = 0; i < size; i++) < builder.append(reader.readLine()).append("\n"); >writer.write(builder.toString()); writer.close(); > else < System.out.println("Файл уже существует"); >buf = reader.readLine(); > >else < reader.close(); throw new IOException("Неверные данные , нужен другой файл!"); >reader.close(); >
Эта функция тоже простая , основная идея в том , что когда файлы соединяются, метод пишет название файла, который был добавлен + число строчек в файле , а когда файлы нужно разделить , метод считывает название файла и количество строк которые нужно бездумно считывать и так далее пока файл не закончится.
Осталось самое главное
Нужно как-то собрать jar файл , чтобы запускать его из консоли. Есть два пути , один сложный и правильный , второй простой , но он не имеет ничего общего с хорошей программой. Для первого способа нужно прописывать все зависимости в manifest , но я пока для этого способа сыроват , есть второй — с помощью плагина:
--> org.apache.maven.plugins maven-assembly-plugin 3.5.0 org.apache.maven.plugins maven-assembly-plugin 3.5.0 org.spbstu.gorchatovra.Parser jar-with-dependencies assemble-all package single
Надеюсь , код , который я написал выше, хотя бы частично понятен, ну если что загуглите , я сделал все, что мог.
Вот и подошел к концу пост , надеюсь кому-то смог помочь, я программист мягко говоря начинающий , так что я открыт для предложений , готовый проект тут.