Learning of IO flow -- the overall framework and use of IO flow

Posted by chenggn on Tue, 09 Nov 2021 20:50:48 +0100

IO flow learning (II) - the overall framework and use of IO flow

Stream operation

I/O is the abbreviation of input/output, that is, the data transmission between processing devices, and the transmission process is called "flow"; And java provides standard methods to read and write data, and the input and output is for programs (i.e. memory) and external storage structures or network links

  • Input: that is, input, which reads external data into memory
  • Output: that is, output, which outputs the data in memory to storage devices such as disk or optical disc

On the classification of flow

  • According to the processing data type, it is divided into character stream (char) and byte stream (byte)
  • According to the flow direction: input flow and output flow
  • According to the role of flow, it is divided into node flow and processing flow

Graphical description of flow
As shown in the figure below, node flow is the most basic flow linking two transmission nodes; The processing flow is a flow wrapped outside the node flow, and more than one processing flow can be added. Multiple stacking is possible

Flow architecture

  • InputStream\OutputStream is for byte stream and Reader\Writer is for character stream. They are abstract base classes and realize functions through their subclasses
  • File stream is cited in node stream: add a file before the class, which is well understood, that is, the stream type of accessing the file. It belongs to node stream and creates objects by directly referencing the file name;
  • In the processing stream, mention the buffer stream: add a Buffered in front of the class, that is, provide a buffer to improve the reading and writing speed of the file; Note that it needs to create its object through the object of the node flow, and when closing the flow, it also closes the flow from the outer layer to the inner layer;

Use of node flow

Use steps of node flow

Four basic steps

  • Create an object of the File class to indicate the read and write files
  • Create read and write method objects through the object of File class
  • Use the read-write method to read and write
  • Close the flow (because the function of automatically closing the flow is not set in java, we need to call its close method ourselves)

Points needing attention during operation

  • The structure of try\catch\finally needs to be used to ensure the normal operation of * * close() * * while correctly catching exceptions

  • FileReader

    • The read() method returns a character and returns a - 1 number when it is read to the end. It can be received as a single char through null parameter construction, or create a char [] array to receive the read data
    • It cannot read files that do not exist
  • FileWriter

    • The write() method is an output operation, and the file specified by it may not exist. If it does not exist, it will automatically create the file
    • If the file it specifies exists, it depends on the object constructor it uses
      • If the constructor used is new FileWrite (filepath, false)/ new FileWrite(filePath); The content of the original file is overwritten with the input content
      • If the constructor used is new FileWrite(filePath,true); The input content is appended to the content of the original file
  • The difference between FileInputStream and FileOutputStream is that when transmitting byte type data, byte or byte [] is required to accept the read data when using the read() method

Simple use of FileReader and FileWriter

		/*
	 	*	 Read the contents of the hello.txt file of xsxIO1109 into the program and output it to the console
		* 
		* 	1. Understanding of read(): return one character read in. If the end of the file is reached, - 1 is returned;
		* 	2.Exception handling: to ensure that the resource can perform the close operation, you need to use try/catch/finally
		* 	3.Cannot read a file that does not exist
		*/
	public void testFileReader(){
		FileReader fr=null;
		//The try catch finally structure is used to ensure that the read stream can be closed normally
		try {
			//1. Instantiate the object of File class and specify the File to be operated
			File file=new File("C:\\Users\\no\\Desktop\\hello.txt");//The absolute path is used here
			//2. Provide specific flow
			fr=new FileReader(file);
		
			//3. Data reading
			int data;
			while((data=fr.read())!=-1) {
				System.out.print((char)data);
			}
		} catch (IOException e) {
			// TODO: handle exception
		}finally {
			//4. Close the flow
			if(fr!=null) {
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}
		

	}
	
	//Upgrade of read operation read(): use the overloaded method of read()
	public void testFileReader1(){
		FileReader fr=null;
		try {
					//1. Instantiation of File class
		File file=new File("C:\\Users\\no\\Desktop\\hello.txt");
		//2. Instantiation of FileReader stream
		fr=new FileReader(file);
		//3. Read in operation
		//read(char[] cbuf): returns the number of characters read into the cbuf array each time. Returns - 1 if it reaches the end of the file
		char[] cbuf=new char[5];
		int len;//Represents the number of data read into the array each time
		

		while((len=fr.read(cbuf))!=-1) {
		//Method 1:
		//Incorrect writing: this will cause errors in the read result package
//			for(int i=0;i<cbuf.length;i++) {
//				System.out.print(cbuf[i]);
//			}
		//Correct writing
//			for(int i=0;i<len;i++) {
//				System.out.print(cbuf[i]);
//			}
		
			
		//Method 2:
		//Wrong writing
//		String str=new String(cbuf);
//		System.out.print(str);
		//Correct writing
		String str=new String(cbuf, 0, len);
		System.out.print(str);
	}
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			//4. Resource shutdown
			if(fr!=null) {
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

	}

  • The use method of byte stream is to follow the gourd and draw a gourd. You can try to combine the read-write method into a copy method;

Then the question arises: when to use byte stream and when to use character stream??????
answer:
1. For text files (txt,java,c,c + +), character stream is used to process them
2. For non text files (jpg,mp3,mp4,avi,doc,ppt...), byte stream is used

The reason is well understood. If the character stream is used to process the normalization of image information, the pixel data of the picture cannot be transmitted correctly, and a pile of garbled code is transmitted, resulting in the invalidation of the file and the change of occupation size. When the byte stream is used to read the text file, the garbled code will also be read out because the byte is used instead of the character to transmit the information;

Use of buffered streams (one kind of processing streams)

Operation process of buffer stream

The use of buffer flow means that when an object with an additional layer of buffer flow is constructed and closed, the buffer flow is closed (when the buffer flow is closed, the node flow it contains will be closed automatically)

Upper code

	
	//Buffer byte stream copy method
	public void testCopyWithReaderWriter(String srcPath,String desPath) {
		//Object to create the flow
		BufferedReader br=null;
		BufferedWriter bw=null;
		
		try {
		//Instantiation of flow objects
		br=new BufferedReader(new FileReader(new File(srcPath)));
		bw=new BufferedWriter(new FileWriter(new File(desPath)));
		
		//Copy operation
		//Method 1:
//		char[] cbuf=new char[1024];
//		int len;
//		while((len=br.read(cbuf))!=-1) {
//			bw.write(cbuf, 0, len);
//		}
		
		//Method 2:
		String str;
		while((str=br.readLine())!=null) {
			bw.write(str+"\n");
		}
		
		
		} catch (IOException e) {
			// TODO: handle exception
		}finally {
			//Closure of flow
			if(br!=null) {
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bw!=null) {
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}
	}

	//Replication method of buffer stream
	public void testCopyBufferedInputOutput(String srcPath,String desPath) {
		//An object that creates a node flow
		BufferedInputStream bis=null;
		BufferedOutputStream bos=null;
		try {
			
			//1. Create an object of the File class to specify where to read and write
			File srcFile=new File(srcPath);
			File desFile=new File(desPath);
			
			//2. Flow generation
			//An object that creates a node flow
			FileInputStream fis=new FileInputStream(srcFile);
			FileOutputStream fos=new FileOutputStream(desFile);
			//An object that creates a buffered stream from a node stream
			bis=new BufferedInputStream(fis);
			bos=new BufferedOutputStream(fos);
			
			//3. Copy operation
			byte[] buffer=new byte[1024];
			int len;
			while((len=bis.read(buffer))!=-1) {
				bos.write(buffer, 0, len);
			}
		} catch (IOException e) {
			// TODO: handle exception
		}finally {
			//4. Close flow
			//Note: you need to close the outer flow first and then the inner flow (when the outer flow is closed, the inner flow will be closed automatically)
			if(bos!=null) {
				try {
					bos.close();
				} catch (IOException e2) {
					// TODO: handle exception
				}
			}
			if(bis!=null) {
				try {
					bis.close();
				} catch (IOException e2) {
					// TODO: handle exception
				}
			}
		}
	}

Advantages of buffered streams

The above is a code implementation of the replication method of the buffer stream. From the test run, it can be found that the replication time they need is several times less than that of the node stream. Therefore, the advantage of the buffer stream is that it can provide buffer space to speed up the reading and writing speed

  • Node stream replication

  • Buffered stream replication

Topics: Java Eclipse