четверг, 4 ноября 2010 г.

Java I/O streams

Потоки используются для приема передачи данных. Существует два основных вида потоков байтовыми и символьными:

Поэтому существует три вида классов:
1) InputStream & OutputStream -- это байтовые потоки.
2) Reader & Writer -- это символьные потоки.

Отличие между ними лежит в следующем - первые читают побайтово, вторые посимвольно (в зависимости от кодировки либо побайтово, либо подвобайтово), и возвращают из метод read(arr), соответсвенно либо массив byte, либо массив char.

Если пользоваться read() без аргументов, то и в первого класса и во второго будет возвращаться int, только вот у первого единички могут быть только в первых 8 битах. Int возвращается для того, чтобы можно было вернуть -1, что означает, что мы подошли к концу потока.

Выше описанные классы абстрактные. Cимвольные классы-потоки базируются(используют) на байтовых. Поэтому есть посредники(bridges), которые помогают превратить байтовые в символьные потоки:
InputStreamReader & OutputStreamWriter.

Дополнительный вид потоков:
BufferedReader & PrintWriter -- это строчные потоки.


Построчные потоки основаны на символьных, но считывают/записывают они не посимвольно, а построчно. При этом ридер на ходу разбирается с файлом какой используется признак окончиния строки в файле. Райтер же вставляет характерный признак для поточной среды (ОС).

BufferedReader inputStream = null;
        PrintWriter outputStream = null;

        try {
            inputStream = 
                new BufferedReader(new FileReader("xanadu.txt"));
            outputStream = 
                new PrintWriter(new FileWriter("characteroutput.txt"));

            String l;
            while ((l = inputStream.readLine()) != null) {
                outputStream.println(l);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
 
Использование напрямую потоков довольно дорогое удовольствие, потому что они обращаются напрямую к ОС, и та запускает дорогостоющие обращения к жестким дискам, к сетевому ресурсу и т.д. Продуктивней использовать буферизированные потоки, ридеры обращаются к ОС, если буфер пуст, а райтеры - если буфер полный. Буфер находится в оперативной памяти, в части выделенной под работающий поток.
Строчные потоки  являются буферезированными.
Буферы это обвертки:
1) BufferedInputStream & BufferedOutputStream.
2) BufferedReader & BufferedWriter.

Буфер можно вручную сливать в райтере, не дожидаясь его переполнения. Метод называется flush, а впринципе есть в любом райтере, но вызывать его смысл есть только в буферизированном райтере. У некоторых б-райтеров есть автофлешинг. Например PrintWriter делает флеш при каждом
 println() и format().
В ридере есть аналог, этой технологии -- это маркировка, мы можем на определенном байте поставить эту марку, а потом если мы считаем из буфера часть потока, но если из-за ошибки потеряем эту часть, мы можем вызвать reset() и буфер заполнится потерянными байтами, а на выходе будет наш  маркированный.:)

Комментариев нет:

Отправить комментарий