среда, 1 августа 2012 г.

module: java io

    Видео по модулю



    Подтемы
        - 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