Читайте также:
|
|
Как вы знаете, метод print1n() предоставляет удобные средство для вывода на консоль различных типов данных, в частности целых чисел и чисел с плавающей точкой. Он автоматически преобразует числовые значения в формат, пригодный для восприятия пользователем. Однако в Java нет метода, который читал бы строки, представляющие числовые значения, и конвертировал их во внутренний двоичный формат. Например, не существует варианта read(), который читал бы строку "100" и автоматически преобразовывал бы в целое число, пригодное для хранения в переменной типа int. Однако есть другие средства, позволяющие решить данную задачу. Проще всего сделать это с помощью оболочек типов.
Кроме того, в оболочках также содержатся методы, предназначенные для преобразования строк, представляющих числа в соответствующие двоичные эквиваленты. Эти методы приведены ниже. Каждый из них возвращает двоичное значение, соответствующее строке.
Оболочка типа | Метод преобразования |
Double | static double parseDouble(String str) throws NumberFormatException |
Float | static float parseFloat(String str) throws NumberFormatException |
Long | static long parseLong(String str) throws NumberFormatException |
Integer | static int parseInt(String str) throws NumberFormatException |
Short | static short parseShort(String str) throws NumberFormatException |
Byte | static byte parseByte(String str) throws NumberFormatException |
Оболочки целочисленных типов также предоставляют дополнительный метод разбора, позволяющий задавать основание системы счисления.
Методы разбора позволяют без труда преобразовать во внутренний формат числовые значения, прочитанные в виде строк с клавиатуры или из текстового файла. Программа, код которой приведен ниже, демонстрирует использование методов parseInt() и parseDouble(). Данная программа находит среднее арифметическое для набора чисел, введенных пользователем. Сначала пользователю предлагается указать количество значений, предназначенных для обработки. Затем программа читает число, используя метод readLine(), и с помощью метода parseInt() преобразует строку в целочисленное значение. Далее происходит ввод значений и преобразование их в тип double с помощью parseDouble().
/* Данная программа находит среднее арифметическое
* для набора чисел, введенных пользователем */
import java.io.*;
class AvgNums
{
public static void main(String args[])
throws IOException
{
// Создание объекта BufferedReader
// связанного с System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System. in));
String str;
int n;
double sum = 0.0;
double avg, t;
System. out. print("How many numbers will you enter: ");
str = br.readLine();
Try
{
// Преобразование строки в целое число
n = Integer. parseInt (str);
}
catch (NumberFormatException exc)
{
System. out. println("Invalid format");
n = 0;
}
System. out. println("Enter " + n + " values.");
for (int i=0; i < n; i++)
{
System. out. print(": ");
str = br.readLine();
Try
{
// Преобразование строки в тип double
t = Double. parseDouble (str);
}
catch (NumberFormatException exc)
{
System. out. println("Invalid format");
t = 0.0;
}
sum += t;
}
avg = sum / n;
System. out. println("Average is " + avg);
}
}
Классы оболочек для простых типов предоставляют ряд методов, помогающих интегрировать данные типы в иерархию объектов. Например, различные наборы данных, предусмотренные в библиотеке Java, в частности отображения, списки и множества, работают только с объектами. Таким образом, чтобы сохранить целочисленное значение в списке, его надо преобразовать в объект. Оболочки типов также предоставляют метод compareTo(), который сравнивает текущее значение с указанным, метод equals(), проверяющий равенство двух объектов, а также методы, возвращающие значение объекта в различных форматах.
Процесс инкапсуляции значения в оболочке типа называется упаковкой (boxing). До появления J2SE 5 упаковка производилась вручную, т.е. программист явным образом создавал экземпляр класса оболочки для требуемого значения. Например, чтобы инкапсулировать значение 100 в объект типа Integer необходима была следующая строка кода:
integer iOb = new Integer(100);
В данном примере явно создается объект Integer, в который помещается рачение 100, и ссылка на этот объект присваивается переменной iOb.
Процесс извлечения значения из объекта оболочки называется распаковкой (unboxing). До появления J2SE 5 распаковка также производилась вручную, т.е. программист явным образом вызывал метод, возвращающий значение, инкапсулированное в объекте. Например, чтобы вручную распаковать объект iOb и поместить результат в переменную int, надо было выполнить следующую команду:
int i = iOb.intValue();
Здесь метод intValue() возвращает значение, инкапсулированное в объекте iOb в формате int. Сказанное выше демонстрирует программа, приведенная ниже.
// Упаковка и распаковка значений вручную
class Wrap
{
public static void main(String args[])
{
// Упаковка значения производится вручную
Integer iOb = new Integer(100);
// Распаковка значения производится вручную
int i = iOb.intValue();
System. out. println(i + " " + iOb); // displays 100 100
}
}
Данная программа упаковывает целочисленное значение 100 в объект Integer, на который ссылается переменная iOb. Для извлечения упакованного числа вызывается метод intValue(). Полученное значение сохраняется в переменной i. В конце программы выводятся значения переменных i и iOb, каждое из которых равно 100.
Аналогичная процедура использовалась в программах для упаковки и распаковки значений, начиная с ранних версий Java. Данный подход не очень удобен. Более того, создание объектов вручную может сопровождаться ошибками. В настоящее время, с появлением автоупаковки и автораспаковки, работа с оболочками типов существенно упростилась.
Проект FileHelp.java
В проекте 4.1 был создан класс Help, позволяющий отображать информацию об операторах Java. Справочная информация хранилась в самом классе, и пользователь выбирал требуемые сведения из меню. Несмотря на то, что созданная система выполняет свои функции, подход, который был использован при ее разработке, далек от идеала. Например, для того, чтобы добавить или изменить какие-либо данные, необходимо модифицировать исходный код программы. Кроме того, выбирать пункт меню по его номеру не очень удобно, а если количество пунктов велико, такой способ и вовсе непригоден. Сейчас мы устраним имеющиеся недостатки путем размещения справочной информации на диске. В новом варианте системы справочные данные будут находиться в файле. Это будет обычный текстовый файл, который можно изменять, не затрагивая код программы. Для того чтобы получить информацию по некоторому вопросу, надо ввести название темы. Система будет искать соответствующий раздел в файле. Если поиск окончится успешно, информация будет выведена на экран.
Последовательность действий
1. Создайте файл для хранения справочной информации, который будет использовать система. Это должен быть обычный текстовый файл, организованный следующим образом:
#название_темы_1 Информация по теме
#название_темы_2 Информация по теме
#название_темы_3 Информация по теме
Имя каждой темы располагается в отдельной строке и предваряется символом #. Наличие специального символа в строке (в данном случае #) позволяет программе быстро найти начало раздела. После названия темы может располагаться любая информация. После окончания одного раздела и перед началом другого должна находиться пустая строка. Кроме того, в конце строк, содержащихся в файле, не должны находиться лишние пробелы. Ниже приведен пример простого файла со справочной информацией, который можно использовать совместно с новой версией справочной системы. B нем хранятся сведения об операторах Java.
#if
if(condition) statement;
else statement;
#switch
switch(expression) {
case constant:
statement sequence
break;
//...
}
#for
for(init; condition; iteration) statement;
#while
while(condition) statement;
#do
do {
statement;
} while (condition);
#break
break; or break label;
#continue
continue; or continue label;
Назовите этот файл helpfile.txt.
2. Создайте файл FileHelp.java.
3. Начните новый вариант класса Help следующими строками кода:
class Help {
String helpfile; // Имяфайласосправочнойинформацией
Help(String fname) {
helpfile = fname;
}
Имя файла со справочной информацией передается конструктору класса Help и запоминается в переменной экземпляра helpfile. Поскольку каждый экземпляр Help содержит отдельную копию переменной helpfile, они могут работать с разными файлами. Таким образом, можно создавать разные наборы справочных файлов, посвященные различным темам.
4. Добавьте к классу Help метод helpon(), код которого показан ниже. Этот метод извлекает информацию по указанной теме.
// Отображениеразделасправочнойсистемы
boolean helpon(String what) {
FileReader fr;
BufferedReader helpRdr;
int ch;
String topic, info;
try {
fr = new FileReader(helpfile);
helpRdr = new BufferedReader(fr);
}
catch (FileNotFoundException exc) {
System. out. println("Help file not found.");
return false;
}
try {
do {
// Чтениесимволовдопоявлениязнака #
ch = helpRdr.read();
// Проверканазваниятемы
if (ch == '#') {
topic = helpRdr.readLine();
if (what.compareTo(topic) == 0) { // found topic
do {
info = helpRdr.readLine();
if (info!= null) System. out. println(info);
} while ((info!= null) &&
(info.compareTo("")!= 0));
return true;
}
}
} while (ch!= -1);
}
catch (IOException exc) {
System. out. println("File error.");
try {
helpRdr.close();
}
catch (IOException exc2) {
System. out. println("Error closing file.");
}
return false;
}
try {
helpRdr.close();
}
catch (IOException exc) {
System. out. println("Error closing file.");
}
return false; // Названиетемыненайдено
}
B первую очередь обратите внимание на то, что в методе helpon() обрабатываются все исключения, связанные с вводом-выводом, поэтому в заголовке метода не указано ключевое слово throws. Благодаря такому подходу упрощается задача разработчика методов, использующих helpon(). B вызывающем методе достаточно обратиться к helpon(), и нет необходимости включать этот вызов в блок try/catch.
Для открытия файла со справочной системой используется класс FileReader, оболочкой которого является класс BufferedReader. Поскольку в файле содержится текст, использование символьных потоков позволяет более эффективно интернационализировать систему.
Метод helpon() работает следующим образом. Строка, содержащая имя темы, передается методу в качестве параметра. Метод открывает файл со справочной информацией. Затем производится поиск в файле, т.е. проверяется соответствие между содержимым переменной what и названием темы. Как вы помните, в файле заголовок темы предваряется символом #, поэтому метод сначала ищет данный символ. Когда символ найден, производится сравнение следующего за ним названия темы с содержимым переменной what. Если строки совпадают, то отображается информация по данной теме. Если заголовок темы найден, то метод helpon() возвращает значение true. B противном случае метод возвращает значение false.
5. В классе Help также содержится метод getSelection (). Он предлагает задать тему и возвращает строку, введенную пользователем.
// Получениетемы
String getSelection() {
String topic = "";
BufferedReader br = new BufferedReader(
new InputStreamReader(System. in));
System. out. print("Enter topic: ");
try {
topic = br.readLine();
}
catch (IOException exc) {
System. out. println("Error reading console.");
}
return topic;
}
B теле данного метода создается объект BufferedReader, который связывается с потоком System.in. Затем он запрашивает имя темы, принимает его и возвращает вызывающему методу.
6. Полностью код программы, реализующей справочную систему с сохранением информации на диске, приведен ниже.
/*
* Проект 2.
* Справочнаясистема,
* использующаядляхраненияинформациифайлнадиске
*/
import java.io.*;
/*
* В классе Help открываетсяфайлсосправочнойинформацией,
* производитсяпоискназваниятемы, а затемотображаются
* данныепоэтойтеме. Обратитевниманиенато, что в данном
* классеподдерживаютсявсеисключения, в результате
* вызывающийкодосвобождаетсяотэтойобязанности
* */
class Help {
String helpfile; // Имяфайласосправочнойинформацией
Help(String fname) {
helpfile = fname;
}
// Отображениеразделасправочнойсистемы
boolean helpon(String what) {
FileReader fr;
BufferedReader helpRdr;
int ch;
String topic, info;
try {
fr = new FileReader(helpfile);
helpRdr = new BufferedReader(fr);
}
catch (FileNotFoundException exc) {
System. out. println("Help file not found.");
return false;
}
try {
do {
// Чтениесимволовдопоявлениязнака #
ch = helpRdr.read();
// Проверканазваниятемы
if (ch == '#') {
topic = helpRdr.readLine();
if (what.compareTo(topic) == 0) { // found topic
do {
info = helpRdr.readLine();
if (info!= null) System. out. println(info);
} while ((info!= null) &&
(info.compareTo("")!= 0));
return true;
}
}
} while (ch!= -1);
}
catch (IOException exc) {
System. out. println("File error.");
try {
helpRdr.close();
}
catch (IOException exc2) {
System. out. println("Error closing file.");
}
return false;
}
try {
helpRdr.close();
}
catch (IOException exc) {
System. out. println("Error closing file.");
}
return false; // Названиетемыненайдено
}
// Получениетемы
String getSelection() {
String topic = "";
BufferedReader br = new BufferedReader(
new InputStreamReader(System. in));
System. out. print("Enter topic: ");
try {
topic = br.readLine();
}
catch (IOException exc) {
System. out. println("Error reading console.");
}
return topic;
}
}
// Демонстрацияработысправочнойсистемы
// с сохранениемфайловнадиске
class FileHelp {
public static void main(String args[]) {
Help hlpobj = new Help("helpfile.txt");
String topic;
System. out. println("Try the help system. " +
"Enter 'stop' to end.");
do {
topic = hlpobj.getSelection();
if (!hlpobj.helpon(topic))
System. out. println("Topic not found.\n");
} while (topic.compareTo("stop")!= 0);
}
}
Вопросы для самоконтроля
http://depositfiles.com/ru/files/r77p8ok45
1. Почему в языке Java определяются байтовые и символьные потоки?
2. Вы знаете, что с консоли вводится текстовая информация, данные такого же типа выводятся на консоль. Почему в Java для обмена с консолью до сих пор используются байтовые потоки?
3. Как открыть файл для чтения байтов?
4. Как открыть файл для чтения символов?
5. Как открыть файл для обеспечения произвольного доступа?
6. Как преобразовать строку "123.23" в двоичный эквивалент?
7. Напишите программу, которая будет копировать текстовые файлы. Модифицируйте ее так, чтобы все пробелы заменялись дефисами. Используйте при написании программы классы, представляющие байтовые потоки.
8. Перепишите программу, созданную в результате ответа на предыдущий вопрос, так, чтобы в ней использовались классы, представляющие символьные потоки.
9. На какой тип потока ссылается переменная System.in?
10. Что возвращает метод read() класса InputStream при достижении конца потока?
11. Поток какого типа используется для чтения двоичных данных?
12. Классы Reader и Writer находятся наверху иерархии классов, предназначенных для
Дата добавления: 2015-07-10; просмотров: 168 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Чтение символов | | | БРОНХИАЛЬНАЯ АСТМА |