Исключения - Exceptions Ни одна программа никогда не работает правильно в 100% случаев, и разработчики языка Java учли это. Рассмотрим встроенный в платформу Java механизмам обработки ситуаций, когда код работает не совсем так, как планировалось. Исключение - это событие, которое происходит во время выполнения программы, нарушая нормальный ход выполнения ее инструкций. Все исключения в Java являются объектами. Поэтому они могут порождаться не только автоматически при возникновении исключительной ситуации, но и создаваться самим программистом. Иерархия классов исключений: Исключения делятся на несколько классов, но все они имеют общего предка — класс Throwable. Его потомками являются подклассы Исключения (Exceptions) Exception и Error. являются результатом проблем в программе, которые в принципе решаемы и предсказуемы. Например, произошло деление на ноль в целых(Errors) числах.представляют Ошибки собой более серьёзные проблемы, которые, не следует пытаться обрабатывать в собственной программе, поскольку они связаны с Типы исключений Контролируемые исключения (checked) Неконтролируемые исключения (unchecked), к которым относятся ошибки (Errors) Исключения времени выполнения (RuntimeExceptions), потомок класса Exception Контролируемые исключения представляют собой ошибки, которые можно и нужно обрабатывать в программе, к этому типу относятся все потомки класса Exception (но не RuntimeException). Они проверяются компилятором (то есть компилятор проверяет, что ваш код где-то обрабатывает их, а Eclipse будет этому способствовать). Обработка исключений ― важная часть Javaпрограммирования. По сути, вы помещаете свой код в блок try (что означает: "попробуем так и посмотрим, вызовет ли это исключение") и используете его для вылавливания исключений разного типа. Обработка исключения может быть произведена с помощью операторов try…catch, либо передана внешней части программы. Например, метод может передавать возникшие в нём исключения выше по иерархии вызовов, сам его не обрабатывая. Пример RuntimeException Неконтролируемые исключения не требуют обязательной обработки, однако, при желании, можно обрабатывать исключения класса RuntimeException. class Main { public static void main(String[] args) { int a = 4; System.out.println(a/0); } } Exception in thread "main" java.lang.ArithmeticException: / by zero at Main.main(Main.java:4) Обработка ошибки class Main { public static void main(String[] args) { int a = 4; try { System.out.println(a/0); } catch (ArithmeticException e) { System.out.println("Произошла недопустимая арифметическая операция"); } } } Обработка исключений общая форма блока обработки исключений. try { …. // блок кода } // Exception e; можно создать объект throw(e) // возбуждение исключения catch (ТипИсключения1 е) { // обработчик исключений типа // ТипИсключения1 } catch (ТипИсключения2 е) { // обработчик исключений типа //ТипИсключения2 throw(e) // повторное возбуждение //исключения } finally { } Обработка исключений Сначала выполняется код, заключенный в фигурные скобки оператора try. Если во время его выполнения не происходит никаких нештатных ситуаций, то далее управление передается за закрывающую фигурную скобку последнего оператора catch, ассоциированного с данным оператором try. Если в пределах try возникает исключительная ситуация, то далее выполнение кода производится по одному из нижеперечисленных сценариев: Обработка исключений Производится выполнение блока кода, ассоциированного с данным catch Если код в этом блоке завершается нормально, то и весь оператор try завершается нормально. Если код в catch завершается нештатно, то и весь try завершается нештатно по той же причине. Если возникла исключительная ситуация, класс которой не указан в качестве аргумента ни в одном catch, то выполнение всего try завершается нештатно. Обработка исключений Оператор finally предназначен для того, чтобы обеспечить гарантированное выполнение какого-либо фрагмента кода, вне зависимости от того, возникла ли исключительная ситуация Если блок finally завершается ненормально, то весь try завершится ненормально по той же причине. Обработка исключений Программист сам может явно сгенерировать ошибку с помощью оператора throw. public int calculate (int theValue) throws Exception { if( theValue < 0) { throw new Exception( "Some descriptive info"); } } Блоки try, catch и finally вместе образуют “капкан для ловли исключений". Сначала код, который может вызвать исключение, заключается в оператор try. Если это срабатывает, управление сразу передается блоку catch, или обработчику исключений. Когда оба оператора выполнены, управление передается блоку finally, независимо от того, имело ли место исключение. "Поймав" исключение, можно попытаться аккуратно обойти его или же выйти из программы (или метода), выводя соответствующее сообщение. Файлы - введение Файлы Долгосрочное хранение больших объемов данных Данные во внешней памяти продолжают существовать после завершения программы Файлы хранятся на устройствах вторичны памяти Магнитные диски Оптические диски Магнитная лента Файлы последовательного и прямого доступа Иерархия данных Наименьшая единица данных в компьютере - bit Bit принимает значения 0 или1 Bit является сокращением от “binary digit” Программисты работают с с единицами данных более высокого уровня Десятичные цифры: (0-9) Символы: (A-Z и a-z) Специальные символов : (e.g., $, @, %, &, *, (, ), -, +, “, :, ?, /, etc.) Java использует символы Unicode, состоящие из f 2 байт Байт имеет длину 8 bits Поля (Java переменные экземпляра) Состоят из символов или байт Имеют смысл Иерархия данных Иерархия данных Элементы данных в компьютере формируют иерархию Преобразование отbits, к символам, к полям, и т.д. Записи Состоят из нескольких полей Реализуются как класс в Java Файл является группой связанных записей Одно поле в каждой записи является ключом записи Ключ записи – уникальный идентификатор записи Последовательный файл Записи хранятся упорядоченными по ключу Иерархия данных Judy Judy 01001010 1 Bit Sally Black Tom Blue Judy Green Iris Orange Randy Red Green File Record Field Byte (ASCII character J) Работа с файлами Java рассматривает файл как поток байтов Т.О. Для работы с файлом в Java-приложении необходимо использовать т.н. потоки ввода-вывода (streams), которые преобразуют входящие байты из файлов (при чтении) в типы языка Java и наоборот при записи (значения типов в файл) Потоки ввода/вывода используются для передачи данных в файлы, на консоль или в сетевые соединения (System.in, System.out, System.err Потоки представляют собой объекты соответствующих классов. Класс java.io.File служит для хранения и обработки в качестве объектов каталогов и имен файлов и не поддерживает методов для работы с содержимым файла Класс File позволяет манипулировать такими свойствами файла, как права доступа, дата и время создания, путь в иерархии каталогов, создание, удаление файла, изменение его имени и каталога и т.д.. Буферирование Буферирование (Buffering) производительность I/O Копии каждый вывода в области памяти называют буфер Каждый буфер выводится на диск однажды Улучшает Один длительное обращение к диску требует меньше времени чем несколько коротких обращений BufferedOutputStream буфер для вывода BufferedInputStream буфер для ввода Работа с файлами разделителями, применяемыми при записи пути к файлу: для системы Unix – “/”, а для Windows – “\\”. классе File имеются константы: public static final String separator; public static final char separatorChar; С помощью этих полей можно задать путь, универсальный для любой системы: File myFile = new File(File.separator + ”com” + File.separator + ”temp.txt” ); Методы файла Методы File Method boolean canRead() Description Returns true if a file is readable; false otherwise. boolean canWrite() boolean exists() Returns true if a file is writable; false otherwise. Returns true if the name specified as the argument to the File constructor is a file or directory in the specified path; false otherwise. Returns true if the name specified as the argument to the File constructor is a file; false otherwise. Returns true if the name specified as the argument to the File constructor is a directory; false otherwise. Returns true if the arguments specified to the File constructor indicate an absolute path to a file or directory; false otherwise. boolean isFile() boolean isDirectory() boolean isAbsolute() String getAbsolutePath() Returns a string with the absolute path of the file or directory. String getName() String getPath() String getParent() Returns a string with the name of the file or directory. Returns a string with the path of the file or directory. Returns a string with the parent directory of the file or directory— that is, the directory in which the file or directory can be found. long length() long lastModified() Returns the length of the file, in bytes. If the File object represents a directory, 0 is returned. Returns a platform-dependent representation of the time at which the file or directory was last modified. The value returned is useful only for comparison with other values returned by this method. String[] list() Returns an array of strings representing the contents of a directory. Потоки В программу поступает входной поток (input stream) символов в кодировке Unicode (16 бит) или просто байтов, воспринимаемый в программе методами read() потока. Из программы выводится выходной поток (output stream) символов или байтов с использованием методов write(), print () или println() потока. При этом не важно, куда направлен поток: на консоль, на принтер, в файл или в сеть, методы write () и print () ничего об этом не знают. Байтовые InputStream и OutputStream При работе с файлами используются подклассы абстрактных классов InputStream и OutputStream, а именно, FileInputStream и FileOutputStream, конструкторы которых открывают поток и связывают его с соответствующим физическим файлом. Для чтения байта или массива байтов используются абстрактные методы read() , и read(byte[] b) класса InputStream. Поток System.in, как встроенный объект подкласса InputStream, позволяет вводить данные с консоли (клавиатуры) Метод возвращает значение 1, если достигается конец потока данных, и поэтому возвращаемое значение имеет тип int, а не byte. Метод write(int b) класса OutputStream записывает один байт в поток вывода. Оба этих метода блокируют поток до тех пор, пока байт не будет записан или прочитан. Обработка исключений вида try-catch при использовании методов чтения и записи является обязательной Диаграммы (byte) Диаграммы байтовых потоков для ввода и вывода FilterInputStream и FilterOutputStream используются как шаблоны для настройки классов InputStream и OutputStream BufferedInputStream и BufferedOutputStream присоединяют к потоку буфер для ускорения последующего доступа Диаграммы символьного В/В Потоки Character считывают (Reader и его подклассы) и записывают (Writer и его подклассы) 16битные символы в формате Unicode. Чтение по одному символу из файла Создать объект FileReader для файла для считывания . В цикле вызывать метод read() и считывать по одному символу за раз до конца файла. InputStreamReader на FileInputStream Запись в файл Создать объект FileOutputStream для файла, в который нужно записывать данные. Вызывать метод write() для записи последовательности символов. Стандартные потоки Система ввода/вывода языка Java содержит стандартные потоки ввода (in), вывода(out) и вывода ошибок (err ). Класс System пакета java.lang содержит поле in, которое является ссылкой на объект класса InputStream, и поля out, err – ссылки на объекты класса PrintStream, объявленные со спецификаторами public static in, out и err и являющиеся стандартными потоками ввода, вывода и вывода ошибок, соответственно. Эти потоки связаны с консолью (in - клавиатура, out и err – дисплей) но могут быть переназначены на другое устройство. Т.е. вместо клавиатуры можно вводить из, например, файла, также и выводить в файл Пример переопределения Scanner Переопределение потоков Аналогичным образом можно переопределить сами входные и выходные потоки, связывая их с файлами. В частности, для каждого потока в классе System существует следующие статические методы: public static void setIn(InputStream in) для переназначения стандртного входного потока. При этом in определяет новый стандартный входной поток; public static void setOut(PrintStream out) для переназначения стандартного выходного потока. При этом out определяет новый стандартный выходной поток. Используя эти методы можно переопределять входной и выходной потоки, связывая их с файлами. Переопределение стандартных потоков Привет, Java Сообщение об исключении Ввод-Вывод текстовой информации Для назначения вывода текстовой информации в произвольный поток следует использовать класс PrintWriter, являющийся подклассом абстрактного класса Writer. Для наиболее удобного вывода информации в файл (или в любой другой поток) следует организовать следующую последовательность инициализации потоков с помощью класса PrintWriter: new PrintWriter(new BufferedWriter(new FileWriter(new File("file.txt")))); В результате класс BufferedWriter выступает классом-оберткой для класса FileWriter при выводе в файл, так же как и класс BufferedReader для FileReader при чтении из файла. new BufferedReader(new FileReader(new File("file.txt")))); После соединения этого потока с файлом на диске посредством символьного потока BufferedWriter и удобного средства записи в файл FileWriter появляется возможность выполнять запись текстовой информации с помощью обычных методов println(), print(), printf(), format(), write(), append(). Ввод символов из файла Для ввода из файла удобно использовать не байтовый, а символьный поток. В этой ситуации для ввода используется подкласс BufferedReader абстрактного класса Reader и методы read() и readLine() для чтения символа и строки соответственно. Этот поток для организации чтения из файла обычно инициализируется объектом класса FileReader в виде: new BufferedReader(new FileReader(new File("file.txt"))); Ввод символов из файла