Видео по модулю
Подтемы
- byte-ориентированные потоки
- char-ориентированные потоки
- java-type-ориентированные потоки
- классы-адаптеры
- классы-декораторы
- работа с файловой системой
- сериализация и клонирование
Материалы
- [Флэган. Справочник] Глава 10 стр 343-401
Пишем отдельные байты в ByteArrayOutputStream, а он "адаптирует" класс OutputStream
Подтемы
- byte-ориентированные потоки
- char-ориентированные потоки
- java-type-ориентированные потоки
- классы-адаптеры
- классы-декораторы
- работа с файловой системой
- сериализация и клонирование
Материалы
- [Флэган. Справочник] Глава 10 стр 343-401
ШАБЛОН: Декоратор (Decorator)
ШАБЛОН: Адаптер (Adapter)
ШАБЛОН: Стратегия (Strategy)
ШАБЛОН: Шаблонный метод (Template Method)
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class BAISTest_0 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
// read one byte
int oneByte = in.read();
System.out.println("(1): " + oneByte);
// read full array
byte[] array0 = new byte[2];
int count0 = in.read(array0);
System.out.println("(" + count0 + "): " + Arrays.toString(array0));
// read interval in array
byte[] array1 = new byte[10];
int count1 = in.read(array1, 0, 8);
System.out.println("(" + count1 + "): " + Arrays.toString(array1));
// nothing to read
System.out.println(in.read());
System.out.println(in.read(new byte[10]));
System.out.println(in.read(new byte[10], 5,2));
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class BAISTest_1 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
while (true) {
int oneByte = in.read();
if (oneByte != -1) {
System.out.print(" " + oneByte);
} else {
System.out.print("\n" + "end");
break;
}
}
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class BAISTest_2 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
int oneByte;
while ((oneByte = in.read()) >= 0) {
System.out.print(" " + oneByte);
}
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class BAISTest_3 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
byte[] buff = new byte[3];
while (true) {
int count = in.read(buff);
if (count != -1) {
System.out.println("count " + count + ": " + Arrays.toString(buff));
} else {
break;
}
}
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class BAISTest_4 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
byte[] buff = new byte[3];
int count;
while ((count = in.read(buff)) != -1) {
System.out.println("count " + count + ": " + Arrays.toString(buff));
}
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class BAISTest_5 {
private static final int MAX_READ_COUNT = 3;
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
byte[] buff = new byte[10];
int totalCount = 0;
int currentCount;
while (true) {
int freeSpace = buff.length - totalCount;
int sizeToRead = Math.min(MAX_READ_COUNT, freeSpace);
currentCount = in.read(buff, totalCount, sizeToRead);
if (currentCount != -1) {
totalCount += currentCount;
System.out.println("t(" + totalCount + "), c(" + currentCount + "): " + Arrays.toString(buff));
} else {
break;
}
}
}
}
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class BAISTest_6 {
public static void main(String[] args) throws IOException {
InputStream in = new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4, 5, 6, 7});
byte[] buff = new byte[10];
int totalCount = 0;
int currentCount;
while ((currentCount = in.read(buff, totalCount, Math.min(3, buff.length - totalCount))) != -1) {
totalCount += currentCount;
System.out.println("t(" + totalCount + "), c(" + currentCount + "): " + Arrays.toString(buff));
}
}
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class BAOSTest_0 {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(16);
try {
out.write(0);
out.write(new byte[]{1, 2});
out.write(new byte[]{0, 0, 3, 4, 5, 0, 0}, 2, 3);
out.flush();
} finally {
out.close();
}
byte[] array = out.toByteArray();
System.out.println(Arrays.toString(array));
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FOSTest {
public static void main(String[] args) throws IOException {
OutputStream out = null;
try {
out = new FileOutputStream("d:/tmp/tmp.txt");
out.write(0);
out.write(new byte[]{1, 2});
out.write(new byte[]{0, 0, 3, 4, 5, 0, 0}, 2, 3);
} finally {
try {
out.flush();
} catch (IOException ignore) {}
try {
out.close();
} catch (IOException ignore) {}
}
}
}
Пишем отдельные байты в ByteArrayOutputStream, а он "адаптирует" класс OutputStream
class ByteArrayOutputStream extends OutputStream
к byte[]
byte[] bytes = ByteArrayOutputStream.toByteArray()
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; public class BAOSTest { public static void main(String[] args) throws IOException { ByteArrayOutputStream buff = new ByteArrayOutputStream(); buff.write(0); buff.write(1); buff.write(2); byte[] arr = buff.toByteArray(); System.out.println(Arrays.toString(arr)); } }
>> [0, 1, 2]
Класс абстрактный OutputStream имеет 5 методов: три для записи - write(int), write(byte[]), write(byte[], int, int), и два специальных - flush(), close().
package java.io;
public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
...
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}
public void flush() throws IOException {}
public void close() throws IOException {}
}
>> 0
Три метода write(...) позволяют записывать отдельный байт, все элементы массива байт или интервал из массива байт:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class BAOSTest1 {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream buff = new ByteArrayOutputStream();
buff.write(0);
buff.write(new byte[]{1, 2, 3});
buff.write(new byte[]{0, 0, 4, 5, 6, 0, 0}, 2, 3);
byte[] arr = buff.toByteArray();
System.out.println(Arrays.toString(arr));
}
}
>> [0, 1, 2, 3, 4, 5, 6]
В этом смысле OutputStream "шире" обычного массива, в который мы можем записывать элементы только по одному. Во так не получится:
byte[] arr = ...
arr[2,3,4] = {10, 20, 30}; // WRONG!
а вот так можно:
OutputStream out = ...
out.write(new byte[]{10, 20, 30}); // OK
но "уже", так как в него можно только писать, а не читать.
После такой программы остается файл d:/tmp/hi.txt со строчкой "Hello!":
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FOSTest {
public static void main(String[] args) throws IOException {
OutputStream out = new FileOutputStream("d:/tmp/hi.txt");
try {
out.write('H');
out.write(new byte[]{'e', 'l', 'l', 'o', '!'});
out.flush();
} finally {
out.close();
}
}
}
Обратите внимание на то, что мы закрываем поток вывода в finally.
Пишем потом читаем файл:
import java.io.*;
public class FOS_FIS_Test {
public static void main(String[] args) throws IOException {
OutputStream out = new FileOutputStream("d:/tmp/hi.txt");
try {
out.write(new byte[]{'H', 'e', 'l', 'l', 'o', '!'});
out.flush();
} finally {
out.close();
}
InputStream in = new FileInputStream("d:/tmp/hi.txt");
try {
int ch;
while ((ch = in.read()) >= 0) {
System.out.print((char) ch);
}
} finally {
in.close();
}
}
}
>> Hello!
import java.io.*;
import java.util.Arrays;
public class BAOS_BAIS_Test {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[]{0, 0, 5, 7, 9, 0, 0}, 2, 3);
byte[] bytes = out.toByteArray();
System.out.println(Arrays.toString(bytes));
InputStream in = new ByteArrayInputStream(bytes);
for (int k = 0; k < 6; k++) {
System.out.println(" " + in.read());
}
}
}
>> 5 7 9 -1 -1 -1
Интерфейс DataOutput - это поток вывода ориентированный на типы данных Java:
public interface DataOutput {
void write(int b) throws IOException;
void write(byte b[]) throws IOException;
void write(byte b[], int off, int len) throws IOException;
void writeBoolean(boolean v) throws IOException;
void writeByte(int v) throws IOException;
void writeShort(int v) throws IOException;
void writeChar(int v) throws IOException;
void writeInt(int v) throws IOException;
void writeLong(long v) throws IOException;
void writeFloat(float v) throws IOException;
void writeDouble(double v) throws IOException;
void writeBytes(String s) throws IOException;
void writeChars(String s) throws IOException;
void writeUTF(String s) throws IOException;
}
Вопрос: чем отличаются DataOutput .writeBytes(...), .writeChars(...), .writeUTF()?
Вопрос: почему один byte, short и char пишутся как int?
>> 0
>> 0
Лабораторные
Есть общие для всех лабораторных классы:
public interface AllocateStrategy {
public int nextAfter(int now);
}
public class DoubleAllocateStrategy implements AllocateStrategy {
public int nextAfter(int now) {
return now * 2;
}
}
>> 0
io.decorator.baos_with_strategy
import java.io.*;
public class BAOSWithStrategy extends OutputStream {
private final AllocateStrategy strategy;
private byte[] buf;
private int count = 0;
public BAOSWithStrategy(AllocateStrategy strategy) {
this(16, strategy);
}
public BAOSWithStrategy(int startSize, AllocateStrategy strategy) {
this.buf = new byte[startSize];
this.strategy = strategy;
}
@Override
public void write(int b) throws IOException {
if (buf.length == count) {
int newSize = strategy.nextAfter(buf.length);
...
}
...
}
@Override
public void write(byte b[]) throws IOException {
...
}
@Override
public void write(byte b[], int off, int len) throws IOException {
...
}
public void writeTo(OutputStream out) throws IOException {
...
}
public byte[] toByteArray() {
...
}
}
io.decorator.buffered_os_with_strategy
import java.io.*;
public class BOSWithStrategy extends OutputStream {
private final AllocateStrategy strategy;
private byte[] buf;
private int count = 0;
public BOSWithStrategy() {
this(16, new DoubleAllocateStrategy());
}
public BOSWithStrategy(int startSize) {
this(startSize, new DoubleAllocateStrategy());
}
public BOSWithStrategy(AllocateStrategy strategy) {
this(16, strategy);
}
public BOSWithStrategy(int startSize, AllocateStrategy strategy) {
this.buf = new byte[startSize];
this.strategy = strategy;
}
@Override
public void write(int b) throws IOException {
if (count == buf.length) {
int newSize = strategy.nextAfter(buf.length);
// int newSize = 2 * buf.length;
byte[] newBuf = new byte[newSize];
System.arraycopy(buf, 0, newBuf, 0, buf.length);
this.buf = newBuf;
}
buf[count++] = (byte) b;
}
@Override
public void write(byte b[]) throws IOException {
...
}
@Override
public void write(byte b[], int off, int len) throws IOException {
...
}
}
io.decorator.buffered_is_with_strategy
>> 0