Лекция Входни и изходни потоци. Писане във файл и четене от



Дата10.04.2018
Размер97.25 Kb.




Лекция 4. Входни и изходни потоци. Писане във файл и четене от

файл. Решаване на уравнението за топлопроводност.

Обикновенно една програма се нуждае от входна информация, извършва някакви действия и произвежда изходни резултати. Java програмите извършват входно-изходните операции чрез потоци. Потоците се реализират чрез иерархия от класове съдържащи се в пакета java.io. В Java има два вида типа потоци: байтови и символни. Класовете за байтови потоци са подкласове на два основни абстрактни класа за входен поток InputStream и за изходен поток OutputStream. Класовете за символни потоци са подкласове на два основни абстрактни класа за входен поток Reader и за изходен поток Writer. Символите в Java са от тип Unicode, което за разлика от ASCII-символите позволява използването на символи от различни езици.

Има различни начини за да се въвеждат данни в програмата:



  • Чрез параметрите на главния метод, ако програмата стартира от командния ред.

  • Чрез клавиатурата, с помощта на класовете Scanner или BufferedReader, които използват входния поток System.in.

  • Чрез графичен интърфейс, например чре текстово поле.

  • Чрез четене на данни от файл с помощта на класа BufferedReader или на класа FileReader.

Извеждането на резултати от програмата също може да става по различни начини:

  • Извеждане на екрана с помощта на изходния поток System.out.

  • Извеждане на данни в прозорец чрез графичен интърфейс.

  • Чрез записване на данни във файл с помощта на класа PrintWriter или на класа FileWriter.

Въвеждане на данни чрез параметрите на главния метод

Ограничено количество данни могат да се вкарват от командния ред чрез параметрите на главния метод. Това се илюстрира от следния пример:



Ако компилираме горния код и стартираме програмата от командния ред, можем да зададем стойности на поредните елементи на текстовия масив args[], който е единствен аргумент на главния метод. Примерно, ако стартираме програмата от командния ред със следната команда:

Java CommandLine Sofia 1164

Изходът на програмат ще бъде следният:

First argument : Sofia

Second argument: 1164

Трябва да се отбележи, че тук 1164 е низ от символи, и ако трябва да се използва като число е необходимо да се превърне от низ в съоветния тип число.

Въвеждане на данни от клавиатурата

Ще разгледаме понятието поток на данни (stream) и класовете BufferedReader и InputStreamReader. Потокът от входни данни осъществява връзката на пpограмата с входно външно устройство, диск или клавиатура, докато изходният поток извежда резултатите от програмата в изходни външни устройства, диск или монитор, както е показано на фиг.1. Трите основни потоци in, out, err (входен поток, изходен поток и поток на грешките) са членове на вградения клас System както е показано на фиг.2.



фиг.1 Входни и изходни потоци



Фиг.2 Трите основни вида потоци

Дадената по-долу примерна програма чете текст, въведен от клавиатурата и го извежда на екрана.

Забележете че се въвежда стандартния пакет за вход-изход import java.io.*;. Задължително да се използва израза throws IOException в главния метод. Това позволява да се открие грешка във входния или изходния поток и да се върне изключение (exception). Връщането на изключение като минимум извежда съобщение за грешка е приключва нормално и безопасно програмата. Изключенията ще бъдат подробно разгледани в една от следващите лекции.

Изходният поток може да се пренасочи от екрана към файл при стартиране на програмата от командния ред. Например ако програмата се казва TimesTable следния израз набран на командния ред

Java TimesTable > time.txt;

изпраща изходния поток System.out във файла time.txt вместо върху екрана.

Потокът на грешките System.err не може да се пренасочва във файл и винаги излиза на екрана. Затова потокът на грешките освен за извеждане на екрана на съобщения за грешки може да се използва и за извеждане на други важни съобщения към потребителя, например:

System.err.println(“Times tables complete”);

Класът System

Класът System е дефиниран в пакета java.lang, който се зарежда автоматично от Java. В този клас са дефинирани като константи трите основни потока, както следва:



public static final InputStream in;

public static final PrintStream out;

public static final PrintStream err;

Константата in е от тип InputStream докато константите out и err са от тип PrintStream. Класът PrintStream е специализиран клас на OutputStream и съдържа различни методи за извеждане на данни, например методите print и println.

Класовете InputStream и InputStreamReader

Знаем, че входният поток System.in е свързан към клавиатурата и е от тип InputStream. Основен метод на класа InputStream за вкарване на данни е метода read( ). Този метод, обаче чете само един байт от данните, поради което не е практичен за четене на текст или числа. System.in.read() ще прочете само един байт от клавиатурата.

Класът InputStreamReader осъществява необходимата връзка между потоци от байтове и потоци от символи. Можем да създадем обект от тип InputStreamReader както следва:

InputStreamReader input = new InputStreamReader(System.in);

Новата променлива input може да се използва за четене на символи.

input.read();

Класът BufferedReader

Входните и изходни операции са бавни поради взаимодействието им с външни устройства. Когато използваме обект на класа InputStreamReader текстът се чете символ след символ и затова изисква многократен достъп до клавиатурата. По-ефективен начин е след като се натрупат в паметта достатъчно символи, да се прочетат наведнъж. Мястото където се събира такава информация се нарича “буфер”. Класът BufferedReader представлява такъв буфер, който натрупва входния поток и освен това съдържа метод за еднократно четене на цял текстов ред. Можем да създадем обект bInput на класа BufferedReader по следния начин:



Двете команди могат да се обединят в една както следва:


Сега новата променлива bInput е свързана с клавиатурата и е обект на класа BufferedReader, поради което можем да прочетем цял текстов ред:





Четене на числа

Друг полезен клас за четене от клавиатура Scanner, който не се нуждае от буферен клас, съдържа директни методи за четене на числа: nextInt(), nextDouble().

За четене на числа от текст се използват методите Integer.parseInt и Double.parseDouble. Това е показано в следния пример:



Записване на данни във файл и четене на данни от файл

Информацията, която се съдържа в променливите и обектите изчезва когато програмата приключи. Затова е полезно да записваме информацията трайно във файлове на диск. Записаната във файла информация е или във вид на символи (текстов файл) или в бинарен вид. Бинарният вид е по-компактен и съответно по-бърз от текстовия вид, но е неудобен поради факта че съдържанието не може да се види с текстов редактор, който показва съдържанието на текстови файлове. Освен това файловете могат да се организират по два начина: с последователен достъп (sequentially) и със случаен достъп (randomly). Ще се ограничим с разглеждането и използването на текстови файлове с последователен достъп.

Езикът Java съдържа специален клас File за манипулиране на файлове. Следващият пример показва действието на методите exists() и delete() в класа File.

Ако в работната директория съществува файл test.txt и ако съществува под-директория exercises\\temp\съдържаща файла Test.class, изходът на програматa ще бъде следния:



Можем да отбележим следните особености в горния пример:



  • Когато създаваме файл, обект на класа File, задаваме името на файла като аргумент (текстов низ) в конструктора.

  • За проверка дали файла съществува използваме метода exists(), който връща логическа променлива от тип boolean.

  • За да маркираме наклонена черта \ използваме двойна наклонена черта \\ защото единичната черта означава началото на специален знак, например \n, \t

  • Методът за триене на файл delete е необратим и трябва да се използва внимателно

Четене от файл

Четенето от файл става с помощта на класа BufferedReader.Ще покажем два начина за четене от файл input.txt:



  • Четене чрез байтови потоци:

BufferedReader f = new BufferedReader(new InputStreamReader(new FileInputStream(“input.txt”)));

Тук потокът InputStreamReader превръща байтовете в символи.



  • Четене чрез символни потоци:

BufferedReader f = new BufferedReader(new FileReader(“input.txt”));

Съдържанието на файла може да се изнесе с помощта на цикъл. Редовете се четат от файла с помощта на while-цикъл. Когато се достигне края на файла методът readLine връща null и цикълът приключва.

String line = f.readLine();

while(line!=null){

System.out.println(line);

line = f.readLine();

}

Писане във файл

Класът PrintWriter дава възможност да се пише текст във файл. Всички методи на изходния поток System.out са достъпни за обекти на PrintWriter. Ще покажем три начина за писане във файла new.txt.



  • Писане чрез символи:

PrintWriter q = new PrintWriter(new FileWriter(“new.txt”));

  • Писане чрез байтове:

PrintWriter q = new PrintWriter(new FileOutputStream(“new.txt”),true);

  • Писане чрез байтове, като символите се превръщат в байтове чрез потока OutputStreamWriter

PrintWriter q = new PrintWriter(new OutputStreamWriter(new FileOutputStream(“new.txt”)));
Забележете че файлът задължително се затваря с командата q.close(); преди да свърши програмата.

Потоци и интърнет

Потоците могат да се свързват не само с файлове, но също така и към страници в мрежата, като се използва класа URL в пакета java.net. Следващата програма създава входен поток от страница с указан адрес. С помощта на този поток кодът HTML на страницата се прочита ред по ред и се извежда на екрана на монитора. Очевидно компютърът трябва да е свързан към мрежата за да работи програмата. Тази програма може да сваля само текст, но не може да сваля изображения.



В програмата трябва да се въведе пакета java.net, който е създаден за работа в мрежата. Също така в главния метод е използван израза throws Exception вместо throws IOException, понеже освен изключения на входно/изходния поток, може да възникнат и други видове изключения. Въпросите за изключенията се разглеждат по-подробно в следващата лекция.



Решаване на уравнението за топлинния поток

Ще решим числово едномерното уравнение за топлинния поток:



(1)


Топлинен поток в метална пръчка

Нека имаме метална пръчка с дължина L и ширина W, разположена по оста х както е показано на фиг.3. Пръчката е топлоизолирана по дължината си, но не и двете челни плоскости. Нека в началния момент пръчката е нагрята равномерно до

100 0С, а двата и края са в контакт с лед т.е. при 0 0С. Топлината е свободна да потече през двата края на пръчката и задачата е да се определи еволюцията във времето на разпределението на температурата по дължината на пръчката.

Имаме следната начална температура на пръчката:

T(x, t=0) = 100 0C (2)

Граничните условия се дават от това че краищата на пръчката са потопени във вода с лед:

T(x=0, t) = T(x=L, t) = 0 (3)

100 0С


0 0С 0 0С


L W

Фиг. 3


Числовият алгоритъм се базира на превръщане на диференциалното уравнение в уравнение на крайните разлики, като се използва развитие в ред на Тейлор. Първата производна по времето получаваме от следното приближение от първи порядък:

(4)


Втората производна по х получаваме като развием в ред на Тейлор до втори порядък функциите T(x+x, t) и T(x-x, t) и сумираме резултатите. Първите порядъци се съкращават и получаваме следното приближение за втората производна по х:


(5)
Заместваме уравнения (4) и (5) в (1) и получаваме следното уравнение на крайните разлики:




(6)


Преминаваме към дискретен вид като положим x = ix и t = jt:

(7)

Алгоритъмът описан от (7) е показан графично на фиг.4. Вижда се че температурата в точката (x = ix , t = (j+1)t), лявата част на (7), се изчислява от стойностите на температурата в трите съседни точки от предишния момент, дясната част на (7). Граничните условия се въвеждат като се поддържат крайните точки с фиксирана стойност, нула. Началното условие се въвежда като се задава температурното разпределение в първия момент t = t. След това може да се пресметне разпределението в момент 2t и т.н.


Х, i











Time, j


Фиг.4

Условие за стабилност

При числовото решаване на частни диференциални уравнения е възможно итерацията по две или повече променливи да доведе до нестабилност .т.е. да настъпи неограничено нарастване на стойностите на променливите. Затова се налага ограничаващо условие за дължината на стъпките на независимите променливи, наречено условие за стабилност. Може да се покаже че за настоящата задача имаме следното условие за стабилност:




(8)


Ако това условие не е изпълнено, числовото решение няма да затихва с времето, и затова ще бъде грешно. Условието (8) ни казва, че ако намалим времевата стъпка ще подобрим сходимоста, но ако намаляваме времевата стъпка без едновременно да увеличим пространствената стъпка на квадрат, разходимоста ще се влоши. Често се налага условието за стабилност на решението трябва да се търси емпирично или чрез друг подход. По принцип трябва да се знае, че могат да съществуват такива стъпки x и t, за които решението става неверно и, че ако намаляваме поотделно x или t това може да не подобрява решението.

Фиг.5 Разпределение на температурата Т по времето t и по координатата х.



Реализация на алгоритъма

  • Напишете програма за решаване на уравнението на топлопроводност с

указаните гранични и начално условия. Удобно е да се въведе двумерен масив за температурата T[Nmax][2], където Nmax е броя на интервалите на които пространствено е разделена пръчката, а вторият индекс е за двa момента във времето – настояще и минало, които се актуализират след всяка стъпка във времето. Като използваме масива T[Nmax][2] вместо масив T[Nmax][ Тmax] се спестява памет тъй като стъпkите във времето Tmax могат да бъдат хиляди на брой.

  • Запишете данните в текстов файл и направете тримерна графика Т(х, t).

  • Проверете стабилноста на решението при различни стъпки като проверите дали

условието за стабилност (9) е вярно.

  • Изследвайте два материала:

Стомана: С=0.113 cal/(g 0C), K=0.12 cal/(s g 0C), =7.8 g/cc

Алуминий: С=0.217 cal/(g 0C), K=0.49 cal/(s g 0C), =2.7 g/cc

Имайте предвид, че условието за стабилност (8) може да изисква промяна на стъпките. Кой от двата материала изстива по-бързо?


  • С
    инусоидално първоначално разпределение на температурата: sin(x/L).

Числовото решение може да се сравни с аналитичното решение:

  • Нека има две еднакви пръчки, всяка 25 см дълга, които са в контакт челно.

Едната е загрята до 100 град., а другата до 50 град. Двeтe свободни краища на пръчките се поддържат при 0 град. Как се изменя температурата в пространството и времето?

  • Охлаждане чрез излъчване. Нека сега пръчката не е изолирана, а е в контакт с

околна среда при температура Т0, различна от температурата на пръчката Т. В този случай температурата се променя чрез излъчване по закона на Нютон:

T/t = -h(T-T0), h е положителна константа. Тогава топлинното уравнение се променя така:

М
одифицирайте програмата да отчита Нютоновото охлаждане и сравнете резултата с предишния.

import java.io.*;

public class Heat {

public static final double K=210.;//heat conduction

public static final double RO=2700.;//material density

public static final double C=900.;//specific heat

public static final double deltax=0.01, deltat=0.1;//steps size

public static final double NEWTON=0.02;//Newton radiation constant

public static final int Nx=31,Nt=300;//grid size

public static void main(String[] args) throws FileNotFoundException, IOException{

int ix,jt;// step counters

double T[][]=new double[Nx][2],cons, eta;//declare temperature array

cons=K/(C*RO);

eta=cons*deltat/(deltax*deltax);//stability parameter

//open file for writing

PrintWriter f=new PrintWriter(new FileOutputStream("temperature.txt"),true);

//initial conditions

for(ix=1;ix

//boundary conditions

T[0][0]=0; T[Nx-1][0]=0;

T[0][1]=0; T[Nx-1][1]=0;

//time and x iterations

for(jt=1;jt

for(ix=1;ix

if(jt==1||jt%5==0)

T[ix][1]=T[ix][0]+eta*(T[ix-1][0]+T[ix+1][0]-2*T[ix][0])- NEWTON*T[ix][0];//calculate temperature field in next moment

T[ix][0]=T[ix][1];//assign new time to old time

}//end of ix-loop

for(ix=0;ix

f.print(T[ix][1]+" ");//write row

f.println();//go to next line

}//end of jt-loop

System.out.println("Done.Look in file: temperatire.txt");

System.out.println("Stability parameter="+eta);



}

}


База данных защищена авторским правом ©obuch.info 2016
отнасят до администрацията

    Начална страница