[30] fundamentals of Java IO application in Android

Posted by BittenApple on Sat, 19 Feb 2022 17:15:51 +0100

(1) As long as a person doesn't give up himself, the whole world won't give up you
(2) I was born to be of great use
(3) If you can't bear the pain of learning, you must bear the pain of life. This is a painful and profound understanding
(4) Hard work pays off
(5) Spirit is the real blade
(6) Defeat your opponent twice, the first in your heart
(7) To live well is to do something meaningful
(8) It's not too late to mend
(9) In the field of science and technology, there are no shortcuts and opportunism.
(10) With strength, 365 days a year are the peak season for application. Without strength, every day is the off-season for application.
(11) The foundation is not firm, the earth moves and the sky shakes
(12) It's not easy to write. If you like it or it's helpful to you, remember to like it + pay attention to it or collect it~

Application foundation of Java IO in Android

1. Why learn Java I/O

Solid Java Foundation:

  • Object serialization
  • Jason analysis
  • xml parsing
  • I/O compression is required as the basis
  • When dealing with the underlying data business

2. Usage mode often seen in io

DataOutputStream out = new DataOutputStream(
                    new BufferedOutputStream(
                    new FileOutputStream(
                    new File(file)
                    )));

(1) What is the principle of this nesting?

(2) An output stream is output from memory to a printing device or hard disk

(3) The input stream is read from a file into memory

(4) Read in and write out are from the perspective of memory.

(5) The purpose of BufferedOutputStream cache is to make the file read faster and reduce the access to disk.

  • Because when there is no Buffer, it will access the disk one by one. If there is a Buffer, it can access one block continuously. At this time, it can reduce the call to the head.

(6) DataOutputStream is a sequence of files.

(7) FileOutputStream is to turn a file into a stream

(8) You can also read files without Buffer, but if there is, the speed will be faster and the format will more meet our needs.

  • Factory mode is used to make choices
  • The question now is which set

3. Decoration mode

3.1 Android Context source code of decoration mode

3.2 decoration mode

3.2.1 implementation case of decoration mode

3.2.1.1 abstract component role
/**
 * Abstract component role
 */
public interface Component {
	
	void doSomeThing();
	
}
3.2.1.2 specific construction roles
/**
 * Specific construction roles
 */
public class ConcreteComponent implements Component {
	@Override
	public void doSomeThing() {
		System.out.println("function A");
	}
}
3.2.1.3 decorative role
/**
 * Decorative role
 * 1.Implement Abstract build role interface
 * 2.It also holds a reference to the abstract construction role, which is convenient to assign a value to the specific construction role through the construction method.
 */
public class Decorator implements Component {

	/**
	 * Holds a reference to an abstract build role
	 */
	private Component component;
	
	public Decorator(Component component) {
		super();
		this.component = component;
	}

	@Override
	public void doSomeThing() {
		component.doSomeThing();
	}
}
3.2.1.4 specific decorative roles
/**
 * Specific decorative role 1
 */
public class ConcreteDecorator1 extends Decorator{
	public ConcreteDecorator1(Component component) {
		super(component);
	}

	@Override
	public void doSomeThing() {
		super.doSomeThing();
		this.doAnotherThing();
	}
	
	private void doAnotherThing() {
		System.out.println("function B");
	}
}
/**
 * Specific decorative role 2
 */
public class ConcreteDecorator2 extends Decorator {

	public ConcreteDecorator2(Component component) {
		super(component);
	}

	@Override
	public void doSomeThing() {
		super.doSomeThing();
		doAnotherThing();
	}
	
	private void doAnotherThing() {
		System.out.println("function C");
	}
}
3.2.1.5 client
public class Client {
	public static void main(String[] args) {
		//s1. Create specific build roles
		Component component1 = new ConcreteComponent();
		//s2. Create specific decorative role 1
		Component component2 = new ConcreteDecorator1(component1);
		//s3. Create specific decorative role 2
		Component component3 = new ConcreteDecorator2(component2);
		//s4. Call specific build role methods
		component3.doSomeThing();
	}

	@Test
	public void test1(){
		Component component =
				new ConcreteDecorator2(
						new ConcreteDecorator1(
								new ConcreteComponent()));
		component.doSomeThing();
	}
}

3.2.2 decoration mode in io

4. Key methods of IO learning

  • Challenge
    Learning Java IO is a very difficult task.

  • comprehensive

(1) Its challenge is to cover all possibilities.

(2) There are not only various I/O source ends, but also the receiving end (file / console / network link) who want to communicate with them, but also need to communicate with them in different ways (sequential / random access / buffer / binary / character / line / word, etc.). These situations bring us a lot of learning tasks and a lot of classes to learn.

  • history

(1) It's difficult for us to learn all these java IO, because we don't build a system about IO, so we need to build it
Building this system also requires an in-depth understanding of the evolution process of IO library. Therefore, if we lack historical vision, what will we do soon
When should I use which classes in IO and when should I not use them.

(2) Therefore, in the eyes of developers, IO is very messy, many classes, many methods, very confused.

(3) Flexibility of decoration mode

  • You can build roles based on abstractions and multiple concrete roles
  • Multiple concrete decorative roles can be constructed according to abstract construction roles and abstract decorative roles

4.1 learning of IO decoration model

(1) When we write a file, we must first create a DataInputStream and provide it to BufferedInputStream to improve the speed.

(2) What does DataInputStream turn into a DataInputStream?

  • Is to change a File into a DataInputStream, that is, a File into a Stream
  • FileInputStream can convert a File into a Stream
  • The parent class of DataInputStream is FilterInputStream, and its reading and writing are formatted
  • The parent class of FileInputStream is InputStream
  • The parent class of BufferedInputStream is also FilterInputStream, which is used to improve the speed. Its reading and writing are not formatted
  • In general, the IO decoration mode is to gradually enhance the function of the stream.

5.Java I/O development history and detailed introduction

5.1 IO class structure

5.2 byte stream learning

(1) FileInputStream and FileOutputStream convert File files into streams and provide them to BufferedOutputStream and BufferedInputStream
(2) Object outputstream and ObjectInputStream are read-write objects
(3) ByteArrayOutputStream and ByteArrayInputStream are provided for byte arrays
(4) FilterInputStream and FilterOutputStream are general interfaces, which cannot be used directly. Their role is decoration in decoration mode It provides a common method for the following specific decorative flows.

public class FilterInputStream extends InputStream {

public class FilterOutputStream extends OutputStream {

5.2.1 cases

public class DataStream {

    /**
     * write
     */
    @Test
    public void testDataOutPutStream() {
        try {
            File file = new File("src/testtxt/dataStreamTest.txt");
            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));

            out.writeBoolean(true);
            out.writeByte((byte) 0x41);
            out.writeChar((char) 0x4243);
            out.writeShort((short) 0x4445);
            out.writeInt(0x12345678);
            out.writeLong(0x987654321L);

            out.writeUTF("abcdefghijklmnopqrstuvwxyz Yan 12");
            out.writeLong(0x023433L);
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * read
     */
    @Test
    public void testDataInputStreamI() {
        try {
            File file = new File("src/testtxt/dataStreamTest.txt");
            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));

            System.out.println(Long.toHexString(in.readLong()));
            System.out.println(in.readBoolean());
            System.out.println(byteToHexString(in.readByte()));
            System.out.println(charToHexString(in.readChar()));
            System.out.println(shortToHexString(in.readShort()));
            System.out.println(Integer.toHexString(in.readInt()));
            System.out.println(Long.toHexString(in.readLong()));
            System.out.println(in.readUTF());
            System.out.println(Long.toHexString(in.readLong()));
            in.close();
        } catch (Exception e) {
        }
    }

    // Print hexadecimal string corresponding to byte
    private static String byteToHexString(byte val) {
        return Integer.toHexString(val & 0xff);
    }

    // Print the hexadecimal string corresponding to char
    private static String charToHexString(char val) {
        return Integer.toHexString(val);
    }

    // Print the hexadecimal string corresponding to short
    private static String shortToHexString(short val) {
        return Integer.toHexString(val & 0xffff);
    }

}

5.2.2BufferedInputStream

(1) Read a byte buf[] array every time, that is, read one block instead of one byte at a time.

public class BufferedStream {
    private static final byte[] byteArray = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
            0x77, 0x78, 0x79, 0x7A };

    @Test
    public void bufferedOutPutStream() {
        try {
            File file = new File("src/testtxt/BufferedStreamTest.txt");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            bos.write(byteArray[0]);
            bos.write(byteArray, 1, byteArray.length - 1);
            bos.flush();
            bos.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void bufferedInputStream() {
        try {
            File file = new File("src/testtxt/BufferedStreamTest.txt");
            BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
            for (int i = 0; i < 10; i++) {
                if (bin.available() >= 0) {
                    System.out.println(byteToString((byte) bin.read()));
                }
            }

            bin.mark(6666);
            bin.skip(10);

            byte[] b = new byte[1024];
            int n1 = bin.read(b, 0, b.length);
            System.out.println("Number of valid bytes remaining: " + n1);
            printByteValue(b);

            bin.reset();
            int n2 = bin.read(b, 0, b.length);
            System.out.println("Number of valid bytes remaining: " + n2);
            printByteValue(b);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String byteToString(byte b) {
        byte[] barray = { b };
        return new String(barray);
    }

    private static void printByteValue(byte[] buf) {
        for (byte b : buf) {
            if (b != 0) {
                System.out.print(byteToString(b) + " ");
            }
        }
    }

}

5.3 character stream learning

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-cInQJ8nS-1619158576012)(6.png)]

(1) Why is there a character stream after a byte stream?
Foreign abcd is a byte, but Chinese is not. Each Chinese is basically more than two bytes. If you read Chinese documents by bytes, it is meaningless to read them.

(2) The difference between character stream and stanza stream

  • The character stream has a readline()
  • One character = 2 bytes (Chinese coding format)
  • Coding format UTF-8 GBK. These coding formats appear to be compatible with various characters.

(3) Why is it rare to stream characters into xml, PNK, and apk files?

  • Because there is no difference in reading these files into bytes, it is useless to operate these files with character stream.
  • Using character streams makes sense only if each line of the file makes sense.

5.3.1 character stream

5.3.2 most common usage of character stream

(1) Generally, character stream and byte stream need to be mixed together.

public class OutputStreamWriterTest {

    private final static String STRING = "I like LiuManLin";

    @Test
    public void testOutputStreamWriter() throws IOException {
        File file = new File("src/testtxt/OutputStreamWriter.txt");

        // true, the setting content can be appended
        FileOutputStream fos = new FileOutputStream(file, true);
        //Does todo have an encapsulated writer?
        OutputStreamWriter oswDef = new OutputStreamWriter(fos);
        BufferedWriter bwdef = new BufferedWriter(oswDef);

        bwdef.write(STRING);
        bwdef.newLine();
        bwdef.flush();
        //		bwdef.close();  // Why can't you write here
        System.out.println("oswDef encoding: " + oswDef.getEncoding());

        OutputStreamWriter oswGBK = new OutputStreamWriter(fos, "GBK");
        BufferedWriter bwGBK = new BufferedWriter(oswGBK);
        bwGBK.write(STRING + "GBK");
        bwGBK.newLine();
        bwGBK.flush();
        //		bwGBK.close();
        System.out.println("oswDef encoding: " + oswGBK.getEncoding());

        OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8");
        BufferedWriter bwUTF8 = new BufferedWriter(oswUTF8);
        bwUTF8.write(STRING + "UTF-8");
        bwUTF8.newLine();
        bwUTF8.flush();
        //		bwUTF8.close();
        System.out.println("oswDef encoding: " + oswUTF8.getEncoding());

        bwdef.close();
        bwGBK.close();
        bwUTF8.close();
    }
}
public class InputStreamReaderTest {

    public static void testISRDefaultEncoder(InputStream is){
        try{
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String string;
            while ((string = br.readLine()) != null) {
                System.out.println(string);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void testISRGBK(InputStream is){
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(is,"GBK");
            BufferedReader gbkBr = new BufferedReader(inputStreamReader);
            String string;
            while ((string = gbkBr.readLine()) != null) {
                System.out.println("code: " + inputStreamReader.getEncoding());
                System.out.println(string);
            }
            gbkBr.close();
        } catch (IOException e) {
        }
    }

    public static void testISRUTF8(InputStream is){
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(is,"UTF-8");
            BufferedReader gbkBr = new BufferedReader(inputStreamReader);
            String string;
            while ((string = gbkBr.readLine()) != null) {
                System.out.println("code: " + inputStreamReader.getEncoding());
                System.out.println(string);
            }
            gbkBr.close();
        } catch (IOException e) {
        }
    }

    @Test
    public void testReader() throws Exception{
        testISRDefaultEncoder(
                new FileInputStream(
                        new File("src/testtxt/OutputStreamWriter.txt")));
        testISRGBK(
                new FileInputStream(
                        new File("src/testtxt/OutputStreamWriter.txt")));
        testISRUTF8(
                new FileInputStream(
                        new File("src/testtxt/OutputStreamWriter.txt")));
    }
}

(1) Writer and Reader only need to focus on BufferedWriter and BufferedReader,OutputStreamWriter and InputStreamReader

5.3.3 problems related to character stream

(1) If only fileoutputstream is used, fileoutputstream = new fileoutputstream ("d:/text.txt");

Can't you also output to "d:/text.txt"? Why use the other two? What role can it play?

answer:

FileOutputStream: a byte stream, which sends data to the outside byte by byte
OutputStreamWriter: a character stream that sends data out character by character

(2) What's the difference between them?

answer:

  • Because computers were invented by foreign devils, their English characters occupy one byte, while our Chinese characters occupy at least two bytes.

  • If you use stream, the English you read can be reversed again. The Chinese you read can be garbled or "?????".
    If you use WRITER, there will be no garbled code

(3) BufferedWriter Buffer is a BUFFER. Why use BUFFER?

answer:

If you use stream or writer directly, your hard disk may read and write a character or a byte
Hard disk once, huge IO burden. But when you use the Buffer, your hard disk is to read and write the hard disk after reading a pile of data
Plate. This is good for your hard drive.

public class ObjectStream {

    private File newFile(String path){
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    private void writeObject(){
        try {
            FileOutputStream fos = new FileOutputStream("src/testtxt/object.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            for(int i = 0; i < 10; i++){
                oos.writeObject(new Person("Ouyang Feng[" + i +"]", i));
            }
            oos.flush();
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void readObject() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(
                    new BufferedInputStream(
                            new FileInputStream(newFile("src/testtxt/object.txt"))));
            while (ois.available() != -1) {
                System.out.println("available: "+ois.available());
                try {
                    Object object = ois.readObject();
                    Person person = (Person) object;
                    System.out.println(person);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (EOFException e){
            //Use EOFException to judge the end
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void writeObjectByArray(){
        try {
            ObjectOutputStream oos = new ObjectOutputStream(
                    new FileOutputStream(newFile("src/testtxt/objectArrays.txt")));
            Person[] persons = new Person[10];
            for(int i = 0; i < 10; i++){
                Person person = new Person("master hongqi[" + i + "]", i);
                persons[i] = person;
            }
            oos.writeObject(persons);
            oos.close();

        } catch (Exception e) {
        }
    }


    public void readObjectByArray() throws IOException {
        ObjectInputStream oos = null;
        try {
            oos = new ObjectInputStream(
                    new FileInputStream(newFile("src/testtxt/objectArrays.txt")));
            Person[] persons = (Person[]) oos.readObject();
            if(null != persons && persons.length > 0){
                for(Person p : persons){
                    System.out.println(p);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            oos.close();
        }
    }


    /**
     * Write objects through collections
     */
    private void writeObjectByList() {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(
                    new FileOutputStream("src/testtxt/objectByList.txt"));
            List<Person> persons=new ArrayList<Person>();
            for (int i = 1; i < 10; i++) {
                Person person = new Person("Ouyang Peng List[" + (20+i)+"]", 20+i);
                persons.add(person);
            }
            //Write List
            oos.writeObject(persons);
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void readObjectByList(){
        ObjectInputStream oos = null;
        try {
            oos = new ObjectInputStream(
                    new FileInputStream(newFile("src/testtxt/objectByList.txt")));
            List<Person> persons = (List<Person>) oos.readObject();
            if(null != persons && persons.size() > 0){
                for(Person p : persons){
                    System.out.println(p);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            try {
                oos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Test
    public void testWriteObject(){
        writeObject();
    }

    @Test
    public void testRead(){
        readObject();
    }

    @Test
    public void testWriteByArray(){
        writeObjectByArray();
    }

    @Test
    public void testReadObjectByArray() throws IOException {
        readObjectByArray();
    }

    @Test
    public void testWriteByList(){
        writeObjectByList();
    }

    @Test
    public void testReadObjectByList(){
        readObjectByList();
    }

}

6.File and RandomAccessFile

6.1RandomAccessFile

6.1.1 why RandomAccessFile?

It is different from other files in the way of reading and writing.

6.1.2 introduction to common methods

(1) Construction method: RandomAccessFile raf = newRandomAccessFile(File file, String mode);

(2) The value of the parameter mode can be "r": readable, "w": writable, "rw": readable;

6.2 features and advantages of RandomAccessFile

(1) You can read or write

RandomAccessFile does not belong to the InputStream and OutputStream classes. It is a completely independent class. All methods (most of them belong to itself) are specified from scratch. Here, there are two kinds of operations: read and write

(2) You can specify the location for reading and writing
RandomAccessFile can move back and forth in the file, and the seek() used for moving in the file, so its behavior is similar to that of other I/O classes
There are some fundamental differences. In a word, it is an independent class that directly inherits Object. Only RandomAccessFile has the seek search method, and this method is only applicable to files

6.2.1 cases

public class RandomAccessFileTests {
    private static final File file = new File("src\\testtxt\\raf.txt");

    /**
     * Write content to file
     */
    @Test
    public void testRandomAccessFileWriter() throws IOException{
        //First delete the existing files to avoid interference.
        if(file.exists()){
            file.delete();
        }

        RandomAccessFile rsfWriter = new RandomAccessFile(file, "rw");

        //The file size will not be changed, but it will identify the writing position of the next character as 10000
        //That is, after that, as long as the content is written, that is, it is stored from 10001
        rsfWriter.seek(10000);
        printFileLength(rsfWriter);		//result: 0

        //Will change the file size, just change the file size
        //It does not change the position of the next content to be written
        //The annotation here is to verify the description of the seek method above
        rsfWriter.setLength(10000);
        System.out.println("oo");
        printFileLength(rsfWriter);		//result: 0
        System.out.println("xx");
        //Each man occupies 3 bytes. When writing a string, there will be a record of two bytes of the length of the written string
        rsfWriter.writeUTF("Pig Bajie carries his daughter-in-law");
        printFileLength(rsfWriter);		//result: 10014

        //Each character takes up two bytes
        rsfWriter.writeChar('a');
        rsfWriter.writeChars("abcde");
        printFileLength(rsfWriter);		//result: 10026

        //Then insert a character array with a length of 100 and full contents of 'a' from the place where the "file pointer" is 5000
        //Here, the file length is still 10026, because it is overwritten from the place where the "file pointer" is 5000
        //The 200 bytes and subscript of does not exceed the file length
        rsfWriter.seek(5000);
        char[] cbuf = new char[100];
        for(int i=0; i<cbuf.length; i++){
            cbuf[i] = 'a';
            rsfWriter.writeChar(cbuf[i]);
        }


        printFileLength(rsfWriter);	//result:  10026

        //Then insert a byte array with a length of 100 and all contents of a from the place where the "file pointer" is 1000
        //Here, the file length is still 10026, because it is overwritten from the place where the "file pointer" is 5000
        //The 200 bytes and subscript of does not exceed the file length
        byte[] bbuf = new byte[100];
        for (int i = 0; i < bbuf.length; i++) {
            bbuf[i] = 1;
        }
        rsfWriter.seek(1000);
        rsfWriter.writeBytes(new String(bbuf));
        printFileLength(rsfWriter);
    }

    /**
     * Read content from file
     * Here we need to know what is in the current file, as well as the starting byte subscript and length of these contents
     *
     * @throws IOException
     */
    @Test
    public void testRandomAccessFileRead() throws IOException{
        /*
         * Brief description of contents in the document:
         * 1,From 0 to 1000 	 Empty
         * 2,From 1001 to 1100, there are 100 1s
         * 3,From 1101 to 5000 is empty
         * 4,From 5001 to 5200 is the character 'a'
         * 5,From 5201 to 10000 is empty
         * 6,From 10001 to 10011 is the string "Chen Huaying"
         * 7,From 10012 to 10023 is "aabcde"
         */
        RandomAccessFile rsfReader = new RandomAccessFile(file, "r");
        //It can be read according to the position and length of what you want to read

        //Read "pig Bajie carries his daughter-in-law"
        rsfReader.seek(10000);
        System.out.println(rsfReader.readUTF());

        //Read 100 characters' a '
        rsfReader.seek(5000);
        byte[] bbuf = new byte[200];
        rsfReader.read(bbuf);
        System.out.println(new String(bbuf));

        //Read 100 1
        byte[] bbuf2 = new byte[100];
        rsfReader.seek(1000);
        rsfReader.read(bbuf2, 0, 100);
        for(byte b : bbuf2){
            System.out.print(b);
        }

        //Read character 'aabcde'
        byte[] bbuf3 = new byte[12];
        rsfReader.seek(10014);
        rsfReader.read(bbuf3);
        System.out.println(new String(bbuf3));
    }
    /**
     * Print file length
     * @param rsfWriter Random file stream to file
     * @throws IOException
     */
    private static void printFileLength(RandomAccessFile rsfWriter)
            throws IOException {
        System.out.println("file length: " + rsfWriter.length() + "  file pointer: " + rsfWriter.getFilePointer());
    }
}

6.2.2 application scenarios

(1) Breakpoint continuation of network data

6.3NIO-FileChannel

(1) Channel is the encapsulation of I/O operations.

(2) FileChannel cooperates with ByteBuffer to cache the read and write data into memory, and then read/write in batch / cache mode, eliminating the repeated intermediate operation in non batch operation. When manipulating large files, it can significantly improve the efficiency (what's the difference between Stream and byte array? After testing, there is almost no difference in efficiency).

public class FileChannelTest {

    @Test
    public void testCopyFileByStream() {
        File sourceFile = new File("F://01_ Life wisdom video / / test mp4");
        File targetFile = new File("D://target.mp4");
        if(targetFile.exists()){
            targetFile.delete();
        }
        try {
            targetFile.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //1. Byte stream read / write
        copyFileByStream(sourceFile, targetFile);
    }

    /**
     * NIO Mode reading and writing
     */
    @Test
    public void testCopyFileByFileChannel(){
        File sourceFile = new File("F://01_ Life wisdom video / / test mp4");
        File targetFile = new File("D://target.mp4");
        if(targetFile.exists()){
            targetFile.delete();
        }
        try {
            targetFile.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //1.NIO reading and writing speed is much higher, especially when reading and writing files are large
        copyFileByFileChannel(sourceFile, targetFile);
    }

    private void copyFileByFileChannel(File sourceFile,File targetFile){
        Instant begin = Instant.now();

        RandomAccessFile randomAccessSourceFile;
        RandomAccessFile randomAccessTargetFile;

        try {
            randomAccessSourceFile = new RandomAccessFile(sourceFile, "r");
            randomAccessTargetFile = new RandomAccessFile(targetFile, "rw");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        FileChannel sourceFileChannel = randomAccessSourceFile.getChannel();
        FileChannel targetFileChannel = randomAccessTargetFile.getChannel();

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024*1024);
        try {
            while(sourceFileChannel.read(byteBuffer) != -1) {
                byteBuffer.flip();
                targetFileChannel.write(byteBuffer);
                byteBuffer.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                sourceFileChannel.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }

            try {
                targetFileChannel.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("total spent: " + Duration.between(begin, Instant.now()).toMillis());
    }

    private void copyFileByStream(File sourceFile,File targetFile) {
        Instant begin = Instant.now();

        FileInputStream fis;
        FileOutputStream fos;

        try {
            fis = new FileInputStream(sourceFile);
            fos = new FileOutputStream(targetFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }
        byte[] readed = new byte[1024*1024];
        try {
            while (fis.read(readed) != -1) {
                fos.write(readed);
            }
            fos.flush();
        } catch( IOException e){
            e.printStackTrace();
        } finally {
            try{
                fos.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        System.out.println("total spent: " + Duration
                .between(begin, Instant.now()).toMillis());

    }
}

6.3.1 why is NIO faster than using byte stream?


(1) Because its bottom layer uses pipeline technology.
(2) Used when operating large files.