Лекция 05. Ввод/вывод¶
Введение¶
Классификация ВВ¶
Под вводом/выводом понимают часть стандартной библиотеки пакетов, предоставляющей средства для обмена информацией между устройствами ввода/вывода, а также файлами.
Основной абстракцией в этом процессе является поток. Потоки могут быть буферизированные и небуферизированные. Первые используют промежуточные хранилища (буферы), а вторые - нет.
Также потоки могут быть байтовые и символьные. Первые рассматривают данные как наборы байт, вторые умеют работать с данными, как с символами. Это важно при использование многобайтных кодировок. Рассмотрим потоки применительно к трем областям:
- Низкоуровневый ввод/вывод.
- Консольный ввод/вывод.
- Файловый ввод/вывод.
Stream¶
Во главе иерархии байтовых потоков ввода/вывода лежат
- InputStream - абстрактный поток ввода.
- OutputStream - абстрактный поток вывода.
Во главе иерархии символьных потоков ввода/вывода лежат
- Reader - абстрактный поток ввода.
- Writer - абстрактный поток вывода.
Байтовые потоки¶
Абстрактный класс InputStream
//Читает 1 байт из вх. потока. Результат в младшем байте.
public abstract int read() throws IOException
//Читает послед-ть байт в массив b[ ].
// Возвращает кол-во прочитанных байт или -1.
public int read (byte[ ] b) throws IOException
//Заполняет массив с указанного байта,
//читает не более len символов
public int read (byte[ ] b, int off, int len) throws IOException
// пропускает n байтов в потоке
public long skip (long n) throws IOException
// количество доступных байтов
int available ()
void close ()
OutputStream¶
// Записывает 1 байт в выходной поток.
public abstract void write (int b) throws IOException
// Записывает в поток массив байт
public void write (byte[ ] b) throws IOException
// Записывает часть массива в поток
// (len элементов начиная с элемента off)
public void write (byte[ ] b, int off, int len) throws IOException
//Немедленно выталкивает из буфера в поток
//все что накоплено в буфере.
public void flush() throws IOException
//Закрывает поток.
public void close() throws IOException
Низкоуровневый ввод/вывод¶
ByteArrayInputStream¶
ByteArrayInputStream – это реализация входного потока, в
котором в качестве источника используется массив типа
byte. У этого класса два конструктора, каждый из которых
в качестве первого параметра требует байтовый массив.
ByteArrayInputStream(byte array[ ])
ByteArrayInputStream(byte array[ ],
int start, int numBytes)
import java.io.*;
public class Program {
public static void main(String[] arg) {
byte [] arr={1,2,3,14,14,16,17,81,82,83};
ByteArrayInputStream in=new ByteArrayInputStream(arr);
ByteArrayOutputStream out=new ByteArrayOutputStream();
System.out.println(in.available());
int b;
while((b=in.read())!=-1)
out.write(b);
out.write(10);
byte [] c=out.toByteArray();
for(byte i:c)
System.out.println((char)i);
}
}
ByteArrayOutputStream¶
Выходной поток имеет два конструктора:
ByteArrayOutputStream()
ByteArrayOutputStream(int size)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String text = "Hello Wolrd!";
byte[] buffer = text.getBytes();
try{
baos.write(buffer);
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
// превращаем массив байтов в строку
System.out.println(baos.toString());
// получаем массив байтов и выводим по символьно
byte[] array = baos.toByteArray();
Метод, записывающий содержимое одного потока в другой:
public void writeTo(OutputStream out) throws IOException
byte buf [ ] = {'a','b','c','d'};
ByteArrayOutputStream b = new ByteArrayOutputStream();
b.write(buf);
FileOutputStream f = new FileOutputStream("result.txt");
b.writeTo(f);
Консольный ввод/вывод¶
Консольный ВВ¶
Два примера консольного ввода:
- Классический
- Современный
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException
{
System.out.println("Hello, enter your name:");
String buf;
BufferedReader in=new BufferedReader(
new InputStreamReader(System.in));
buf=in.readLine();
System.out.println("Hello, "+buf);
}
Еще один вариант:
import java.io.*;
public class ReadConsole {
public static void main(String args[]) throws IOException
{
InputStreamReader cin = null; char c;
try {
cin = new InputStreamReader(System.in);
System.out.println("Enter characters, 'q' to quit.");
do {
c = (char) cin.read();
System.out.print(c);
} while(c != 'q');
}finally {
if (cin != null) {
cin.close();
}
}
}
}
Более современный вариант:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("Enter a line:");
String buf;
Scanner in = new Scanner(System.in);
buf=in.nextLine();
System.out.println("Hello, "+buf);
}
}
System.out.println("How old are you?");
int age=0;
try {
age=Integer.parseInt(in.readLine());
}
catch(NumberFormatException ex) {
System.out.println("Wrong age!");
System.exit(1);
}
System.out.printf("Good age %d",age);
}
}
Вывод¶
Консольный ВВ¶
Рассмотрим методы, используемые с System.out:
- print() - печать строки без перевода курсора
- println() - печать строки с переводом курсора
- printf() - печать строки с форматированием
int value=5;
System.out.println("Отлично - это "+value);
System.out.printf("%d - отличная оценка\n",value);
import java.util.Date;
public class PrintfDemo
{
public static void main(String[] args)
{
System.out.println(new Date());
}
}
Результат: Thu Mar 23 18:11:50 MSK 2017 Печать текущего года:
import java.util.Date;
public class PrintfDemo
{
public static void main(String[] args)
{
System.out.printf("%tY\n",new Date());
}
}
Файловый ввод/вывод¶
Работа с файлами¶
Для работы с файлами применяются различные потоки
- FileInputStream,FileOutputStream - байтовые потоки
- FileReader,FileWriter - символьные потоки
Создание файлового объекта:
File f = new File("1.txt");
Файловый объект может использоваться как параметр при создании потоков.
Байтовые потоки¶
FileInputStream¶
Рассмотрим работу с файлами с помощью FileInputStream
FileInputStream(String name) throws FileNotFoundException
FileInputStream (File file) throws FileNotFoundException
В классе FileInputStream переопределяется большая часть методов класса InputStream (в т.ч. абстрактный метод
read() ). Когда создается объект класса FileInputStream, он одновременно с этим открывается для чтения.
import java.io.*;
public class FilesApp {
public static void main(String[] args) {
try
{
FileInputStream fin=new FileInputStream("note.txt")
System.out.println("Размер файла: " +
fin.available() + " байт(а)");
int i=-1;
while((i=fin.read())!=-1){
System.out.print((char)i);
}
}
catch(IOException ex){
System.out.println(ex.getMessage());
}
}
}
byte[] buffer = new byte[fin.available()];
// считываем файл в буфер
fin.read(buffer, 0, fin.available());
System.out.println("Содержимое файла:");
for(int i=0; i<buffer.length;i++){
System.out.print((char)buffer[i]);
}
FileOutputStream¶
Класс FileOutputStream можно применять для записи байтов в файл. У класса FileOutputStream есть 3 конструктора:
FileOutputStream (String filePath) throws FileNotFoundException
FileOutputStream (File fileObj) throws FileNotFoundException
FileOutputStream (String filePath, boolean append)
throws FileNotFoundException
try
{
FileInputStream source = new FileInputStream("infile.dat");
FileOutputStream dest = new FileOutputStream("outfile.dat");
int c;
while ((c = source.read()) != -1)
{
dest.write(c);
}
source.close(); dest.close();
}
catch (FileNotFoundException ex)
{...}
Пример работы с двумя файлами
import java.io.*;
public class FilesApp {
public static void main(String[] args) {
try
{
FileOutputStream fos=new FileOutputStream("new.txt");
FileInputStream fin=new FileInputStream("notes.txt");
byte[] buffer = new byte[fin.available()];
// считываем буфер
fin.read(buffer, 0, buffer.length);
// записываем из буфера в файл
fos.write(buffer, 0, buffer.length);
}
catch(IOException ex){
System.out.println(ex.getMessage());
}
}
}
Символьные потоки¶
FileReader¶
Для работы с символами и строками используют символьные потоки.
Основные методы FileReader:
- int read() throws IOException - чтение одиночного символа.
- int read(char [] c, int offset, int len) - чтение символов в массив.
...
try {
FileReader reader=new FileReader("1.txt");
int c;
while((c=reader.read())!=-1) {
System.out.print((char)c);
}
catch(IOException ex) {
System.out.println(ex.getMessage());
}
}
...
Для чтения строк удобно использовать буферизированный поток BufferedReader:
File file = new File("...");
FileReader reader = new FileReader(file);
BufferedReader breader = new BufferedReader(reader);
String line;
while ((line=breader.readLine()) != null) {
...
}
reader.close();
FileWriter¶
import java.io.*;
class Random2FileWriter
{
public static void main(String[] args)
throws Exception {
Writer file = new FileWriter("random.txt");
int n=(int)(Math.random()*10);
String outstr="Number:"+n;
file.write(outstr);
file.close();
}
}
Копирование строк:
BufferedReader in = null;
PrintWriter out = null;
String line;
try {
in = new BufferedReader(new FileReader(args[0]));
out = new PrintWriter(new FileWriter(args[1]));
while ((line = in.readLine()) != null) {
out.println(l);
}} finally {
if (in!= null) { in.close(); }
if (out!= null) { out.close(); }
}
Reader reader;
Writer writer;
try {
reader = new FileReader(args[0]);
writer = new FileWriter(args[1]);
int c = 0;
while ((c = reader.read()) >= 0) {
writer.write(Character.toUpperCase((char) c));
}
reader.close();
writer.close();
}
catch(FileNotFoundException ex) {}
catch(IOException ex) { }
Специальные типы файлов¶
Properties¶
Можно использовать файлы для хранения наборов свойств:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;
public class ReadPropertiesFile {
public static void main(String[] args) {
try {
File file = new File("test.properties");
FileInputStream fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInput);
fileInput.close();
Enumeration enuKeys = properties.keys();
while (enuKeys.hasMoreElements()) {
String key = (String) enuKeys.nextElement();
String value = properties.getProperty(key);
System.out.println(key + ": " + value);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Запись файла со свойствами:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class WritePropertiesFile {
public static void main(String[] args) {
try {
Properties properties = new Properties();
properties.setProperty("favoriteAnimal", "marmot");
properties.setProperty("favoriteContinent", "Antarctica");
properties.setProperty("favoritePerson", "Nicole");
File file = new File("test.properties");
FileOutputStream fileOut = new FileOutputStream(file);
properties.store(fileOut, "Favorite Things");
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
XML-файлы¶
XML¶
В более сложных случаях предпочтительно использовать XML-файлы.
import java.io.*;
import java.util.Enumeration;
import java.util.Properties;
public class ReadPropertiesXmlFile {
public static void main(String[] args) {
try {
File file = new File("test.xml");
FileInputStream fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.loadFromXML(fileInput);
fileInput.close();
...
...
Enumeration enuKeys = properties.keys();
while (enuKeys.hasMoreElements()) {
String key = (String) enuKeys.nextElement();
String value = properties.getProperty(key);
System.out.println(key + ": " + value);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}}}
Запись XML- файла:
import java.io.*
import java.util.Properties;
public class WritePropertiesXmlFile {
public static void main(String[] args) {
try {
Properties properties = new Properties();
properties.setProperty("favoriteAnimal", "marmot");
properties.setProperty("favoriteContinent", "Antarctica");
properties.setProperty("favoritePerson", "Nicole");
...
...
File file = new File("test.xml");
FileOutputStream fileOut = new FileOutputStream(file);
properties.storeToXML(fileOut, "Favorite Things");
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}}
JSON¶
JSON (JavaScript Object Notation) - специальный текстовый формат для обмена данными (чаще всего между клиентом и сервером).
Рассмотрим пример:
"students": [
{
"id": 100,
"fio": "Иванов А.А."
},
{
"id": 101,
"fio": "Петров В.В."
}
]
}
Для работы с форматом JSON существует несколько библиотек. Одна из наиболее распространенных: json-simple.
import java.io.*;
import org.json.simple.*;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSONRead {
public static void main(String[] args) {
try {
File f=new File("students.json");
JSONParser parser=new JSONParser();
FileReader fr = new FileReader(f);
Object obj=parser.parse(fr);
JSONObject js=(JSONObject)obj;
JSONArray items=(JSONArray)js.get("students");
for(Object i : items) {
System.out.println(((JSONObject)i).get("id"));
}
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (ParseException ex) {
System.out.println(ex.getMessage());
} catch(IOException ex) {
System.out.println(ex.getMessage());
}
}
}