Java input and output(4)

Java input and output (4)

1. RandomAccessFile class

  • The RandomAccessFile class is not a stream, but it has the function of reading and writing file data. It can randomly start reading and writing data from any position in the file.

  • The RandomAccessFile class can open a file with specified operation permissions (such as read-only, write-only, etc.). The specific permissions used depend on the construction method used to create it.

Creating a RandomAccessFile object through two construction methods requires accepting two parameters: the first parameter specifies the associated file, and the second parameter mode specifies the mode of accessing the file (file permissions)

The RandomAccessFile construction method is as follows:

RandomAccessFile(File file,String mode)//Use parameter file to specify the file being accessed, and use mode to determine the specified access mode
RandomAccessFile(File name,String mode)//Use parameter name to specify the path of the file being accessed, and use mode to determine the specified access mode

RandomAccessFile features

? RandomAccessFile is the most versatile file content access class in the Java Io system. That is, you can read the contents of the file, and you can also write the contents to the file. But unlike other input/output streams, the program can jump directly to any location in the file to read and write data.

Because RandomAccessFile can freely access any location in the file, if we want to access only part of the file, we can use the RandomAccessFile class.

Different from output streams such as OutputStearm and Writer, the RandomAccessFile class allows free positioning of the file record pointer, so RandomAccessFile can not output from the beginning of the file, so RandomAccessFile can append content to an existing file. Then RandomAccessFile should be used.

Overall introduction to RandomAccessFile

The RandomAccessFile class contains a record pointer to identify the current reading and writing location. When the program creates a new RandomAccessFile object, the file record pointer of the object is located at the file header (that is, at 0). When n files are read/written, bytes, the file record pointer will move backward n bytes. In addition, RandomAccessFile can move the record pointer freely, that is, it can move forward or backward.

RandomAccessFile contains the following two methods to operate the file’s record pointer:

  • long getFilePointer(); returns the current position of the file record pointer
  • void seek(long pos); Position the file record pointer to the pos position

RandomAccessFile can both read and write files, so it contains three read() methods that are completely similar to InputStream, and its usage is exactly the same as the three read() methods of InputStream; it also contains three read() methods that are completely similar to OutputStream. A write() method, its usage is exactly the same as the three Writer() methods of OutputStream. In addition, RandomAccessFile also contains a series of readXXX() and writeXXX() methods to complete input and output.

RandomAccessFile has two constructors. In fact, the two constructors are basically the same, except that the form of specifying the file is different. One uses the String parameter to specify the file name, and the other uses the File parameter to specify the file itself. In addition, creating a RandomAccessFile object also requires specifying a mode parameter. This parameter specifies the access mode of RandomAccessFile and has the following 4 values:

  1. r: Indicates opening in read-only mode. If you try to write to a RandomAccessFile object, an I/OException will be thrown.
  2. rw: indicates opening in “read-write” mode. If the file does not exist, it will be automatically created.
  3. rws: indicates opening in “read-write” mode. Compared with “rw”, it requires that every update to the file’s content or metadata be written synchronously to the underlying storage device
  4. rwd: means opening in **”read-write” mode. It requires that every update to the file’s content** be synchronously written to the underlying storage device

The RandomAccessFile object contains a record pointer to identify the current reading and writing location**. Sequential reading and writing, the pointer is at the 0 position at the beginning**, in addition to the record pointer can be moved freely, both forward and backward

int skipBytes(int n) //make the read and write pointer start from the current position and skip n bytes
void write(byte[] b) //Write the specified byte array to this file, starting from the current file pointer
long getFilePointer() //Returns the position of the current read-write pointer
void seek(long pos) //Set the position of the read and write pointer, pos bytes away from the beginning of the file
void setLength(long newLength) //Set the length of this file
final String readLine() //Read the next line of content from the current pointer of the specified file
Use RandomAccessFile to implement the function of reading files from a specified location
  public static void main(String[] args)throws IOException {<!-- -->
    String filePath="E:\learnproject\Iotest\lib\src\main\java\\com\Test.txt\ ";
    RandomAccessFile raf=null;
    File file=null;
    try {<!-- -->
        file=new File(filePath);
        raf=new RandomAccessFile(file,"r");
        // Get the position of the RandomAccessFile object file pointer, the initial position is 0
        System.out.print("Input content:" + raf.getFilePointer());
        //Move the position of the file record pointer
        raf.seek(1000);

        byte[] b=new byte[1024];
        int hasRead=0;
        //Loop to read files
        while((hasRead=raf.read(b))>0){<!-- -->
            //Output the content read from the file
            System.out.print(new String(b,0,hasRead));
        }
    }catch (IOException e){<!-- -->
        e.printStackTrace();
    }finally {<!-- -->
        raf.close();
    }
}

There are two key codes in the above program. One is to create a RandomAccessFile object, which opens the Test.txt file in read-only mode, which means that the RandomAccessFile file can only read the file content and cannot perform writing. The second call to the seek(1000) method refers to positioning the record pointer of the file to the 1000-byte position. In other words, the program will start reading data from 1000 bytes. The way other parts of the code are read is no different from other input streams.

public class RandomAccessFileTest2 {<!-- -->
    public static void main(String[] args)throws IOException {<!-- -->
        String filePath="E:\learnproject\Iotest\lib\src\main\java\\com\Test.txt\ ";
        RandomAccessFile raf=null;
        File file=null;
        try {<!-- -->
            file=new File(filePath);
            //Open a RandomAccessFile object for reading and writing
            raf=new RandomAccessFile(file,"rw");
            //Move the record pointer to the end of the file
            raf.seek(raf.length());
            //Append content to the end of the file
            raf.writeChars("This is additional content..");
        }catch (IOException e){<!-- -->
            e.printStackTrace();
        }finally {<!-- -->
            raf.close();
        }
    }
}

The above code first creates a RandomAccessFile object in read and write mode, then moves the file record pointer to the end, and then uses RandomAccessFile to write content to the file. The same way as other output examples OutputStream. Every time you run the above program, you will find that an extra line of content is added to the text.txt file.

Use RandomAccessFile to insert content into a specified location in a file

Note: RandomAccessFile cannot insert content into the specified position of the file. If you directly move the file record pointer to a certain position in the middle and start outputting, the new output content will overwrite the original content of the file. If you need to insert content into the specified position, the program needs First, write the content after the insertion point into the cache area. After the data to be inserted is written into the file, the content in the cache area is appended to the end of the file.

 /**
 * Insert the specified content at the specified location of the file
 * @param filePath file path
 * @param pos insert the specified location of the file
 * @param insertContent insert the content in the file
 * @throwsIOException
 */
  public static void insert(String filePath,long pos,String insertContent)throws IOException{<!-- -->
      RandomAccessFile raf=null;
      File tmp=File.createTempFile("tmp",null);
      tmp.deleteOnExit();
      try {<!-- -->
          //Open a RandomAccessFile object for reading and writing
          raf = new RandomAccessFile(new File(filePath), "rw");
          //Create a temporary file to save the data after the insertion point
          FileOutputStream fileOutputStream = new FileOutputStream(tmp);
          FileInputStream fileInputStream = new FileInputStream(tmp);
          //Locate the file record pointer to the pos position
          raf.seek(pos);
          raf.seek(pos);
          //------The following code reads the content after the insertion point into a temporary file and saves it-----
          byte[] bbuf = new byte[64];
          //Used to save the actual read byte data
          int hasRead = 0;
          //Use a loop to read the data after the insertion point
          while ((hasRead = raf.read(bbuf)) != -1) {<!-- -->
              //Write the read content to a temporary file
              fileOutputStream.write(bbuf, 0, hasRead);
          }
          //-----The following code is used to insert content-----
          //Reposition the file record pointer to the pos position
          raf.seek(pos);
          //Add the content to be inserted
          raf.write(insertContent.getBytes());
          //Append the contents of the temporary file
          while ((hasRead = fileInputStream.read(bbuf)) != -1) {<!-- -->
              //Write the read content to a temporary file
              raf.write(bbuf, 0, hasRead);
          }
      }catch (Exception e){<!-- -->
          throw e;
      }
  }
    public static void main(String[] args)throws IOException {<!-- -->
        String filePath="E:\learnproject\Iotest\lib\src\main\java\\com\Test.txt\ ";
        insert(filePath,1000,"Insert the specified content at the specified location");
    }

The above program uses the createTempFile method of the File class to create a temporary file (the file will be deleted after the JVM exits) to save the content after the insertion point. The program first reads the content after the insertion point in the file into a temporary file, then relocates to the insertion point, adds the content to be inserted to the end of the file, and finally adds the content of the temporary file to the end of the file. Through this process, the program can add the content to the end of the file. Specify the file and insert the content at the specified location. Every time you run the above program, you will see an extra line in the Test.txt file.

2. Filter flow

In Java development, filter stream (FilterStream) is a very practical tool for filtering and processing input streams or output streams. It can realize instant processing of data, making data transmission and processing more efficient and convenient. This article will guide you how to use Java filter streams, giving detailed steps and sample code.

Process Overview

The process of using Java filter flow for data filtering and processing is as follows:

Steps Description
1 Create an input or output stream
2 Create a filter stream object and connect it to the input or output stream
3 Read or write data
4 Close the filter stream and the underlying stream

The specific operations and required code of each step will be introduced step by step below.

Detailed explanation of steps
Step 1: Create an input stream or output stream

First, we need to create an input stream (InputStream) or output stream (OutputStream) object as the source or destination of data. The specific creation method depends on the needs. For example, you can use the file input stream (FileInputStream) to read files, or use the network input stream (URLInputStream) to read network data.

Sample code:

//Create file input stream
InputStream inputStream = new FileInputStream("input.txt");
Step 2: Create a filter stream object and connect to the input stream or output stream

Next, we need to create a filter stream object and connect it to the input or output stream created in step 1. Java provides a variety of filter stream implementation classes, and you can choose the appropriate implementation class according to your needs. For example, if you need to buffer the input stream, you can use the buffered input stream (BufferedInputStream).

Sample code:

//Create a buffered input stream object and connect to the input stream
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
Step 3: Read or write data

Now, we can use the filter stream object to read or write data. The specific operation method depends on the requirements. For example, you can use the read() method of the filter stream to read data, or use the write() method to write data.

Sample code:

//Read data from the buffered input stream
int data = bufferedInputStream.read();
//Use the output stream to write data
outputStream.write(data);

Step 4: Close the filter stream and underlying stream
Finally, we need to close the filter stream and underlying stream to release resources. Closing the filter stream automatically closes the underlying stream, so just close the filter stream.

Sample code:

//Close the buffered input stream
bufferedInputStream.close();

Java filter streams can be used to filter and process input streams or output streams to improve data transmission and processing efficiency. This article introduces the steps and sample code for using Java filter flow. I hope it will be helpful for you to understand and use filter flow.

3. Object serialization

Java serialization is the process of converting an object into a stream of bytes so that the object can be saved to disk, transmitted over the network, or stored in memory and later deserialized to convert the bytes The stream is converted back into an object.

Serialization is implemented in Java through the java.io.Serializable interface, which does not have any methods and is just a marker interface used to identify classes that can be serialized.

When you serialize an object, you wrap it into a special file that can be saved, transferred, or stored. Deserialization opens the file, reads the serialized data, and then restores it to an object for use in the program.

Serialization is a method for saving, transferring, and restoring objects. It allows objects to be moved and shared between different computers, which is useful for distributed systems, data storage, and cross-platform communication.

The following are the basic concepts and usage of Java serialization:

Implement the Serializable interface: To make a class serializable, the class needs to implement the java.io.Serializable interface, which tells the Java compiler that this class can be serialized, for example:

import java.io.Serializable;

public class MyClass implements Serializable {<!-- -->
    // Class members and methods
}

Serialize objects: Use the ObjectOutputStream class to serialize objects into a byte stream. The following is a simple example:

MyClass obj = new MyClass();
try {<!-- -->
    FileOutputStream fileOut = new FileOutputStream("object.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(obj);
    out.close();
    fileOut.close();
} catch (IOException e) {<!-- -->
    e.printStackTrace();
}

The above code serializes the obj object in a file named “object.ser”.

Deserialize objects: Use the ObjectInputStream class to deserialize objects from a byte stream. The following is a simple example:

MyClass obj = null;
try {<!-- -->
    FileInputStream fileIn = new FileInputStream("object.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn);
    obj = (MyClass) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException e) {<!-- -->
    e.printStackTrace();
} catch (ClassNotFoundException e) {<!-- -->
    e.printStackTrace();
}

The above code reads the byte stream from the “object.ser” file and deserializes it into a MyClass object.

The classes ObjectInputStream and ObjectOutputStream are high-level data streams that contain methods for deserializing and serializing objects.

The ObjectOutputStream class contains many writing methods for writing various data types, with the exception of one particular method:

public final void writeObject(Object x) throws IOException

The above method serializes an object and sends it to the output stream. The similar ObjectInputStream class contains the following methods for deserializing an object:

public final Object readObject() throws IOException,
                                 ClassNotFoundException

This method takes the next object from the stream and deserializes the object. Its return value is Object, therefore, you need to convert it to the appropriate data type.

Example

To demonstrate how serialization works in Java, I will use the Employee class mentioned in the previous tutorial. Suppose we define the following Employee class, which implements the Serializable interface.

public class Employee implements java.io.Serializable
{<!-- -->
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {<!-- -->
      System.out.println("Mailing a check to " + name
                            + " " + address);
   }
}

Please note that for an object of a class to be serialized successfully, two conditions must be met:

This class must implement the java.io.Serializable interface.

All properties of this class must be serializable. If a property is not serializable, the property must be marked as ephemeral.

If you want to know whether a Java standard class is serializable, check the documentation for that class. Checking whether an instance of a class can be serialized is very simple, just check whether the class implements the java.io.Serializable interface.

Serialized object

The ObjectOutputStream class is used to serialize an object. The following SerializeDemo example instantiates an Employee object and serializes the object to a file.

After the program executes, a file named employee.ser is created. The program does not produce any output, but you can understand what the program does by studying the code.

Note: When serializing an object to a file, Java’s standard convention is to give the file a .ser extension.

import java.io.*;
 
public class SerializeDemo
{<!-- -->
   public static void main(String [] args)
   {<!-- -->
      Employee e = new Employee();
      e.name = "Reyan Ali";
      e.address = "Phokka Kuan, Ambehta Peer";
      e.SSN = 11122333;
      e.number = 101;
      try
      {<!-- -->
         FileOutputStream fileOut =
         new FileOutputStream("/tmp/employee.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(e);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in /tmp/employee.ser");
      }catch(IOException i)
      {<!-- -->
          i.printStackTrace();
      }
   }
}

Deserialized object

The DeserializeDemo program below instantiates deserialization and /tmp/employee.ser stores Employee objects.

import java.io.*;
 
public class DeserializeDemo
{<!-- -->
   public static void main(String [] args)
   {<!-- -->
      Employee e = null;
      try
      {<!-- -->
         FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
         ObjectInputStream in = new ObjectInputStream(fileIn);
         e = (Employee) in.readObject();
         in.close();
         fileIn.close();
      }catch(IOException i)
      {<!-- -->
         i.printStackTrace();
         return;
      }catch(ClassNotFoundException c)
      {<!-- -->
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
      System.out.println("Deserialized Employee...");
      System.out.println("Name: " + e.name);
      System.out.println("Address: " + e.address);
      System.out.println("SSN: " + e.SSN);
      System.out.println("Number: " + e.number);
    }
}

The results of compiling and running the above program are as follows:

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

The following points should be noted here:

The try/catch code block in the readObject() method attempts to catch the ClassNotFoundException exception. For the JVM to be able to deserialize an object, it must be a class that can find the bytecode. If the JVM cannot find the class during deserialization of the object, a ClassNotFoundException exception is thrown.

Note that the return value of the readObject() method is converted into an Employee reference.

When the object is serialized, the value of the attribute SSN is 111222333, but because the attribute is ephemeral, the value is not sent to the output stream. So the SSN property of the Employee object is 0 after deserialization.