Stage 4 IO

IO stream

Preface:

We can only do some operations in the existing closed scope, but this is obviously not interesting, and does not allow us to implement some complex requirements, so Java provides the concept of IO flow, easy to operate on data

And use IO flow we can achieve some powerful features, such as mobile copy for file operations, or between the application and external file data storage or read, or implement a real-time chat program (network programming), the data transmission is also used by our IO streams, which we will design in the back, Let me begin my formal study of IO streams

(a) overview and classification of IO flow

(1) concept

IO stands for input/output, and the concept of a stream is somewhat unfamiliar

A “flow” is literally like a stream of water, directional, fluid, continuous, and capable of carrying something. In our computers, a “flow” is an abstract description of ordered, continuous, directional data. Its essence is the transmission of data, and according to its characteristics, it is abstracted into a variety of classes, more convenient for users to operate

(2) classification

A: to

  • Input stream – Reads data
  • Output stream – Writes out data

B: Data type

  • Byte stream
    • Byte InputStream — InputStream
    • Byte OutputStream — OutputStream
  • Characters of the flow
    • Character input stream — Reader
    • Character output stream — Writer

Note:

A: If we don’t specify what we are going to score by, the default score is by data type.

B: Use character stream only if the file is open with Notepad in Windows and we can read it. Otherwise, it is recommended to use byte stream.

(2) byte stream

(1) FileOutputStream writes data

A: Operation procedure

  • Create a byte output stream object
  • Call the writer() method
  • Release resources

B: Code representation

FileOutputStream fos = new FileOutputStream("fos.txt");
for.write("hello".getBytes());
fos.close;
Copy the code

Wrapping operation

Because different systems recognize different newlines differently

Windows: \r\ N Linux: \ N Mac: \ R

Some common advanced notepads can recognize any newline symbol

How to append data?

Use the constructor with the second argument true

FileOutputStream fos = new FileOutputStream("fos.txt".true);
Copy the code

(2) FileInputStream reads data

A: Operation procedure

  • Creates a byte input stream object
  • Call the writer() method
  • Release resources

B: Code representation

FileInputStream fis = new FileInputStream("fos.txt");
Copy the code
// Use FileInputStream to read the content in the specified path. You can operate files with FileOutputStream
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\fos.txt");

        / / way
        int by = 0;
        while((by = fis.read()) ! = -1){
            System.out.print((char)by);
        }

        // Method 2 (this method is faster, recommended)
        // The array length is usually 1024 or a multiple of 1024
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = fis.read(bys))! = -1){
            System.out.print(new String(bys,0,len));
        }
        // Release resourcesfis.close(); }}Copy the code

(3) Byte buffer stream

// Count the running time of this program

long start = System.currentTimeMillis();
// The code under test
long end = System.currentTimeMillis();
System.out.println("Total time" + (end - start) + "毫秒");
Copy the code

Byte streams can read and write to an array at a time much faster than they can read and write a byte at a time. This is because of the buffer effect of arrays. Java itself is designed with this in mind (decorative design patterns explained below), so it provides byte buffer streams

// Bytes buffer output stream
BuffereOutputStream
// Buffer the input stream in bytes
BufferedInputStream
Copy the code
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedOutputStreamDemo {
    public static void main(String[] args) throws IOException {
// FileOutputStream fos = new FileOutputStream("F:\\fos.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        //
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\fos.txt"));
        
        / / write data
        bos.write("hello".getBytes());
        // Release resources, note that fos.close is not requiredbos.close(); }}Copy the code

Why not pass a specific file or file path instead of an OutputStream object?

The reason is simple: byte buffer streams only provide buffers, designed for efficiency. However, the real read and write operations are still implemented by basic stream objects.

import java.io.*;

public class Test {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();

        method1("E: \ \ nocturnes. Mp3"."F:\\Test1.mp3");
        method2("E: \ \ nocturnes. Mp3"."F:\\Test2.mp3");
        method3("E: \ \ nocturnes. Mp3"."F:\\Test3.mp3");
        method4("E: \ \ nocturnes. Mp3"."F:\\Test4.mp3");
        long end = System.currentTimeMillis();
        System.out.println("Total time" + (end - start) + "毫秒");
    }

    // The basic byte stream reads and writes one character at a time
    public static void method1(String srcString, String deskString) throws IOException {
        FileInputStream fis = new FileInputStream(srcString);
        FileOutputStream fos = new FileOutputStream(deskString);
        int by = 0;
        while((by = fis.read()) ! = -1) {
            fos.write(by);
        }
        fis.close();
        fos.close();
    }

    // The basic byte stream reads and writes one byte array at a time
    public static void method2(String srcString, String deskString) throws IOException {
        FileInputStream fis = new FileInputStream(srcString);
        FileOutputStream fos = new FileOutputStream(deskString);
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = fis.read(bys)) ! = -1) {
            fos.write(bys, 0, len);
        }
        fis.close();
        fos.close();
    }

    // Efficient byte stream reads and writes one byte at a time
    public static void method3(String srcString, String deskString) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
        BufferedOutputStream bos = new 
            BufferedOutputStream(new FileOutputStream(deskString));
        int by = 0;
        while((by = bis.read()) ! = -1) {
            bos.write(by);
        }
        bis.close();
        bos.close();
    }

    // Efficient byte stream reads and writes one byte array at a time
    public static void method4(String srcString, String deskString) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
        BufferedOutputStream bos = new 
            BufferedOutputStream(new FileOutputStream(deskString));
        byte[] bys = new byte[1024];
        int len = 0;
        while((len = bis.read(bys)) ! = -1) {
            bos.write(bys, 0, len); }}}// Run the resultTime elapsed125961Millisecond total time143Millisecond total time1356Millisecond total time29msCopy the code

Thus, of the four methods mentioned above, the most efficient is the last one – the efficient byte stream reads and writes one byte array at a time!

(3) Character stream

In development, if we want to transfer data from text that we can recognize, if we continue to use the byte stream that we learned above, we will find that the content displayed is garbled because of encoding problems, and we will use our character stream. We can start by simply recognizing the character stream = byte stream + encoding

(1) Encoding and decoding

coding instructions
ASCII American standard information interchange code, represented by seven bits of a byte.
ISO8859-1 Latin code watch. European code meter, represented by 8 bits of a byte.
GB2312 Chinese code table in China.
GBK The Chinese code table in China has been upgraded to incorporate more Chinese characters.
GB18030 Alternative version of GBK
The BIG – 5 yards A traditional Chinese character coding scheme in Taiwan and Hong Kong, commonly known as “big five code”.
Unicode The International standard code, a combination of various characters, some of which are represented by two bytes, is used in the Java language as Unicode
UTF-8 A maximum of three bytes can be used to represent a character. Utf-8 is different in that it defines an “interval rule” that is compatible with ASCII encoding to the greatest extent possible: It represents Unicode characters encoded 00000000-0000007F as a single byte. It represents Unicode characters encoded 00000080-000007FF as two bytes. It represents Unicode characters encoded 00000800-0000FFFF as three bytes

Byte stream we have a certain understanding of the previous, so what is encoding and decoding?

Encoding is the process of converting information from one form or format to another; Decoding is the reverse process of coding.

Let’s start with an example to see how it works

// Decodes the byte array with the specified character set
String(byte[] bytes, String charsetName)
// Encodes a string as a byte array using the specified character set
byte[] getBytes(String charsetName)
Copy the code
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class EncodingDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "Ideal";

        // string-byte [] - byte
        byte[] bys = s.getBytes();  //[-25, -112, -122, -26, -125, -77]
// byte[] bys = s.getBytes("UTF-8"); //[-25, -112, -122, -26, -125, -77]
// byte[] bys = s.getBytes("GBK"); / / [49-64-19, -, - 21]
        System.out.println(Arrays.toString(bys));
        
        //byte[] -string - decode
        String string = new String(bys);  / / an ideal
// String string = new String(bys,"UTF-8"); / / an ideal
// String string = new String(bys,"GBK"); / / 鐞 嗘 兂System.out.println(string); }}Copy the code

Sending process: “Ideal” — digital — binary — send

Receiving process: Receiving — binary — decimal — Numeric — Character — “Ideal”

In fact, the simple summary is:

** coding: ** turn comprehensible into comprehensible

** Decode: ** to see not understand into understand

(2) character input and output streams

OutputStreamWriter Character output stream (write out)

public OutputStreamWriter(OutputStream out)
public OutputStreamWriter(OutputStream out,String charsetName)
Copy the code

InputStreamReader Character input stream (read)

public InputStreamReader(InputStream in)
public InputStreamReader(InputStream in,String charsetName)
Copy the code

OutputStreamWriter Method for writing data

// Write a character
public void write(int c)

// Write an array of characters
public void write(char[] cbuf)

// Write part of a character array
public void write(char[] cbuf,int off,int len)

// Write a string
public void write(String str)

// Write part of a string
public void write(String str,int off,int len)
Copy the code

OutputStreamWriter Reads the data method

// Read a character
public int read(a)

// The first character array
public int read(char[] cbuf)
Copy the code

Note the problem of character stream operation

The difference between flush() and close()?

Close: The stream object is closed, but the buffer is flushed once. After closing, the stream object cannot be used any more

Flush: Simply flush the buffer, after which the stream object can continue to be used

(2) The simple writing method of character stream

The name of the transformation stream is long, and our common operations are implemented according to the native default encoding, so to simplify our writing, the transformation stream provides a corresponding subclass

/ / the output stream
FileWriter
/ / input stream
FileReader
Copy the code
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"))
/ / equivalent
FileWriter fw = new FileWriter("b.txt"); (write) InputStreamReader ISr =new InputStreamReader(new FileInputStream("a.txt"))
/ / equivalent
FileReader fr = new FileReader("a.txt"); (read)Copy the code

(3) Character buffer stream

BufferedWriter: output stream of character buffering

Writes text to a character output stream, buffering individual characters to provide efficient writing of individual characters, arrays, and strings.

You can specify the size of the buffer or accept the default size. In most cases, the default is large enough.

BufferedReader: character buffered input stream

Reads text from the character input stream, buffering individual characters for efficient reading of characters, arrays, and rows.

You can specify the size of the buffer, or you can use the default size. In most cases, the default is large enough.

Special function

BufferedWriter:

// Determine the newline character according to the system
public void newLine(a)
Copy the code

BufferedReader:

// Reads one line of data at a time, containing the contents of that line as a string, without any line terminators, and returning NULL if the end of the stream has been reached
public String readLine(a)
Copy the code

(4) IO flow cases

Byte stream case

Case 1: Copy a single level folder

import java.io.*;

/* * Demand: copy single level folder * * Data source: f:\\demo * destination: f:\\test * * Analysis: * A: encapsulates the directory * B: obtains the File array of all the text in the directory * C: iterates the File array to obtain each File object * D: copies the File */


public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
        File srcFloder = new File("F:\\demo");
        File deskFloder = new File("F:\\test");

        if(! deskFloder.exists()) { deskFloder.mkdirs(); } File[] fileArray = srcFloder.listFiles();for (File file : fileArray) {
            String name = file.getName();
            // Piece together the path of each file
            File newFile = newFile(deskFloder, name); copyFloder(file, newFile); }}public static void copyFloder(File file, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while((len = bis.read()) ! = -1) {
            bos.write(bys, 0, len); } bis.close(); bos.close(); }}Copy the code

Case 2: Copy the specified file in the specified directory and change the file name extension

import java.io.*;

/* * Demand: copy the specified file in the specified directory and change the suffix. * The specified file is:.txt file. * The specified suffix is:.bat * The specified directory is: test * * Data source: f:\\demo\\ a. TXT * Destination: f:\test\\ a. bat * * Analysis: * A: encapsulate directory * B: get the File array of Java files in this directory * C: iterate over the File array to get each File object * D: copy the File * E: rename the File in the destination directory */
public class CopyFolderDemo2 {
    public static void main(String[] args) throws IOException {
        File srcFloder = new File("F:\\demo");
        File destFloder = new File("F:\\test");

        if(! destFloder.exists()) { destFloder.mkdirs(); } File[] fileArray = srcFloder.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isFile() && name.endsWith(".txt"); }});for (File file : fileArray) {
            String name = file.getName();
            File newFile = new File(destFloder, name);
            copyFile(file, newFile);
        }

        File[] deskFileArray = destFloder.listFiles();
        for (File destFile : deskFileArray) {
            String name = destFile.getName();
            String newName = name.replace(".txt".".bat");

            File newFile = newFile(destFloder, newName); destFile.renameTo(newFile); }}public static void copyFile(File file, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while((len = bis.read(bys)) ! = -1) {
            bos.write(bys, 0, len); } bis.close(); bos.close(); }}Copy the code

Case 3: Copying multi-level folders

import java.io.*;

/* * Requirement: Copy multipole folder * * Data source: F:\\admin * destination: E:\\ * * Analysis: * A: encapsulates the data source File * B: encapsulates the destination File * C: determines whether the File is A folder or A File * A: is A folder * Creates the folder in the destination directory * obtains all files under the File object or folder File object * iterates to obtain each File object * Back to C * b: if file * is copied (byte stream) */
public class CopyFloderDemo3 {
    public static void main(String[] args) throws IOException {
        File srcFile = new File("F:\\admin");
        File destFile = new File("E:\\");
        copyFolder(srcFile, destFile);
    }


    private static void copyFolder(File srcFile, File destFile) throws IOException {
        if (srcFile.isDirectory()) {
            File newFolder = new File(destFile, srcFile.getName());
            newFolder.mkdirs();

            // Get all files or folder File objects under this File object
            File[] fileArray = srcFile.listFiles();
            for (File file : fileArray) {
                // recursive, continue to judgecopyFolder(file, newFolder); }}else {
            File newFile = newFile(destFile, srcFile.getName()); copyFile(srcFile, newFile); }}private static void copyFile(File srcFile, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while((len = bis.read(bys)) ! = -1) {
            bos.write(bys, 0, len); } bos.close(); bis.close(); }}Copy the code

Character stream case

Case 1: Randomly obtain the name in the text file case

import java.io.*;
import java.util.ArrayList;
import java.util.Random;

/* * Get a random name in a text file * Requirement: I have a text file stored several names * please write a program to achieve a random name of a person. * * Analysis: * A: store data from A text file into A collection * B: randomly generate an index * C: get A value based on that index */
public class GetRandName {
    public static void main(String[] args) throws IOException {
        String path = "F:\\test.txt";
// BufferedReader br = new BufferedReader(new FileReader(path));
        // By default, notepad is stored in ANSI encoding, but FileReader uses UTF-8 output by default, so using the above statement will be garbled
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "gb2312"));

        ArrayList<String> array = new ArrayList<>();
        String line = null;
        while((line = br.readLine()) ! =null) {
            array.add(line);
        }
        br.close();

        Random r = new Random();
        int index = r.nextInt(array.size());

        String name = array.get(index);
        System.out.println("The lucky one:"+ name); }}Copy the code

Case two: Keyboard input student information according to the total score and write the text file case

// The Student class adds its own complement
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class StudentDemo {
    public static void main(String[] args) throws IOException {
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s2.getSum() - s1.getSum();
                int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
                int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
                int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
                int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName()) : num4;
                returnnum5; }});for (int x = 1; x <= 3; x++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("Please enter no" + x + "Student score information");
            System.out.println("Name:");
            String name = sc.nextLine();
            System.out.println("Chinese Score:");
            int chinese = sc.nextInt();
            System.out.println("Math score:");
            int math = sc.nextInt();
            System.out.println("English:");
            int english = sc.nextInt();

            Student s = new Student();
            s.setName(name);
            s.setChinese(chinese);
            s.setMath(math);
            s.setEnglish(english);
            ts.add(s);

            BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\students.txt"));
            bw.write("Student scores are listed below.");

            bw.newLine();
            bw.flush();
            bw.write("Name - Chinese score - Math score - English score");
            bw.newLine();
            bw.flush();
            for (Student stu : ts) {
                StringBuilder sb = new StringBuilder();
                sb.append(stu.getName() + "-" + stu.getChinese() + "-" + stu.getMath() + "-" + stu.getEnglish());
                bw.write(sb.toString());
                bw.newLine();
                bw.flush();
            }

            bw.close();
            System.out.println("Student score information has been entered."); }}}Copy the code

Case 3: Login and Registration case (using IO)

Based on the collection implementation in the previous articles, the rest of the files remain the same and you just need to rewrite the Userdaoimp.java file

Due to the long length, the rest of the DAO, POJO, test layer code please refer to the previous several collection framework – List

package cn.bwh_05_LoginDemo.dao.impl;

import cn.bwh_05_LoginDemo.dao.UserDao;
import cn.bwh_05_LoginDemo.pojo.User;

import java.io.*;

/** * This is the concrete implementation class (IO) for user actions **@author BWH_Steven
 * @versionV1.1 * /
public class UserDaoImpl implements UserDao {
    private static File file = new File("User.txt");

    static {
        try {
            file.createNewFile();
        } catch (IOException e) {
            System.out.println(Failed to create file); e.printStackTrace(); }}@Override
    public boolean isLogin(String username, String password) {
        boolean flag = false;
        BufferedReader br = null;
        String path = "user.txt";

        try {
            br = new BufferedReader(new FileReader(file));
            String line = null;
            while((line = br.readLine()) ! =null) {
                // Username -- password
                String[] datas = line.split("--");
                if (datas[0].equals(username) && datas[1].equals(password)) {
                    flag = true;
                    break; }}}catch (FileNotFoundException e) {
            System.out.println("Unable to find information file required for login");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("User login failed");
            e.printStackTrace();
        } finally {
            if(br ! =null) {
                try {
                    br.close();
                } catch (IOException e) {
                    System.out.println("User login failed to release resource"); e.printStackTrace(); }}}return flag;
    }

    @Override
    public void regist(User user) {
        /* * Define a rule for registered data: username -- password */
        BufferedWriter bw = null;
        String path = "user.txt";
        try {
            // To ensure that data is appended, true must be added
            bw = new BufferedWriter(new FileWriter(file, true));
            //bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path,true),"gb2312"));
            bw.write(user.getUsername() + "--" + user.getPassword());
            bw.newLine();
            bw.flush();
        } catch (IOException e) {
            System.out.println("User registration failed");
            e.printStackTrace();
        } finally {
            try {
                bw.close();
            } catch (IOException e) {
                System.out.println("User failed to register to release resource"); e.printStackTrace(); }}}}Copy the code

The end:

If there is any inadequacy in the content, or wrong place, welcome everyone to give me a message to put forward opinions, crab crab everyone! ^_^

If it helps you, follow me! (The series of articles will be updated in the public account as soon as possible)

We don’t know each other here, but we are working hard for our dreams

A adhere to push original Java technology public account: ideal more than two days