Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Java IO

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "how to use Java IO". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn how to use Java IO.

Foreword:

It is a difficult task for programming language designers to create a good I / O (input / output) system.

Java IO: Java input / output system. Most programs need to process some input and produce some output from the input, so Java provides us with the java.io package

As a qualified program developer, we are no stranger to IO. The knowledge structure of JAVA IO system is as follows:

After reading the above picture, we will suddenly realize that there is so much support for us in the Java.io package. But we do not need to panic at the same time, as the saying goes, we only need to expand according to the source, I believe we can have a good grasp of IO knowledge system.

File class

Read and write operations without dealing with files (File), so if we want to master the IO stream, we might as well start with files.

The word File is neither singular nor plural. It can represent both a particular file and a set of files in a directory.

List

What can we do if we want to get a directory if File represents a set of files under a directory?

File has prepared API for us, and based on the return value type, it is not difficult to guess the usefulness of each API method.

It is known that there is a TestFile folder under our D disk directory, which contains the following files:

Name list

If we want to get a list of names under the specified directory, we can use these two API:

List ()

List (FilenameFilter filter)

The list () method with no parameters defaults to listing all file names in the specified directory. If we want a list of directory names that specify names, we can use another method:

We expect to get the name of the file with the test keyword, and the result is what we want.

File list

Sometimes we do a lot of operations not just on a single file, but on the entire set of files. To generate this fileset, we need to use another API method of File:

ListFiles ()

ListFiles (FilenameFilter filter)

ListFiles (FileFilter filter)

With the above experience, it is not difficult to guess that the purpose of listFiles () is to list all the files:

In the figure, we have got the fileset, and this method returns the same array, but an array of type File.

You must have known that if you get a set of files with specified keywords,

The name of the file listed above is the same as the name of the file listed above.

But how is the parameter passed by the listFiles (FileFilter filter) method different from that passed above? We might as well have a try:

It is also an interface, and you also need to override the accept () method, but this method has only one parameter to File. Therefore, these two parameters are used for file filtering, and the functions are more or less the same.

Catalog tool

Create a directory

The usefulness of the File class not only allows you to manipulate existing directory files, but also makes you create something out of nothing!

The characteristics of the file are as follows: name, size, last modified date, readable / writable, type, etc.

Then we should also be able to get through API:

All of the above types have been obtained, except that one is missing. Although File does not provide a method to obtain the type directly, we can obtain the file type by obtaining the full name of the file, and then clipping the suffix of the file:

As soon as you change hands, you can also get the file type by yourself. What a clever kid.

All of the above operations are based on the existence of a file directory, so if the file directory we want to operate does not exist. Or what will happen if we enter the file directory name incorrectly because of our carelessness, and will the operation process proceed normally?

The result is that an exception is thrown, and it is normal to throw an exception. Isn't it nonsense to operate on a non-existent file directory?

So when we are not sure if the file directory exists, we can do this:

In the figure, we can see two API methods that we have not seen before, namely exists () and mkdirs ().

Exists (): used to verify that the file directory exists

Mkdirs (): used to create a directory

Through the above verification before operation, we have successfully avoided the exception. What you need to know here is that in addition to mkdirs () can create a directory, there is a mkdir () can also create a directory, these two methods apart from missing an s, there are other differences?

Mkdir (): can only create an one-tier directory

Mkdirs (): you can create multi-tier directories

Our current scenario is that the Test directory does not exist, and the dir01 directory naturally does not exist, so you have to create a two-tier directory at this time. But it doesn't work for us to use the mkdir () method, it can't be created. So we should use the mkdirs () method in this case.

File Typ

File can be a file or a set of files, and the set of files can contain a file or a folder. If we want to read and write to a file, but inadvertently operate on a folder, it will be embarrassing, so we can use isDirectory to determine whether it is a folder:

Input and output

Above we talked about the basic operation of the File class, and then we went into the Icano module.

Input and output we often use the concept of stream, such as input stream and output stream. This is an abstract concept that represents any data source object that is capable of producing data or a receiver object that has the ability to accept data. The stream blocks the actual Iram O device to find the details of how to process the data!

Icano can be divided into input and output parts.

The input stream is divided into byte input stream (InputStream) and character input stream (Reader). Any class derived from InputStream or Reader implements the method read (), which is used to read a single byte or byte array.

The output stream is divided into byte output stream (OutputStream) and character output stream (Writer). Any class derived from OutputStream or Writer implements the method write (), which is used to write a single byte or byte array.

So we can see the rule in Java: all classes related to input should inherit from InputStream, and all classes related to output should inherit from OutputStream.

InputStream

Used to represent classes that generate input from different data sources

What exactly are those different data sources? The common ones are: 1. Byte array 2. String object 3. Document 4. "Pipeline" (input at one end, output at the other)

Each of these data sources has a corresponding InputStream subclass that can be manipulated:

Class function ByteArrayInputStream allows the buffer of memory to be treated as InputStream using StringBufferInputStream has been discarded, converting String to InputStreamFileInputStream for reading information from files PipedInputStream generating data for writing related PipedOutPutStream, implementing pipelined concept SequenceInputStream converts two or more InputStream objects into an InputStreamFilterInputStream abstract class as an interface for decorators, and provides useful functions for other InputStream

OutPutStream

The class of this category determines the destination of the output: 1. Byte array 2. Document 3. Pipeline

Common OutPutStream subclasses are:

Class function ByteArrayOutputStream creates a buffer in memory, and all data sent to the "stream" should be placed in this buffer. FileOutputStream is used to write information into the file PipedOutputStream. Any information written into it will automatically be output as the relevant PipedInputStream, realizing the pipelized concept FilterOutputStream abstract class, as an interface to the decorator, providing useful functions for other OutputStream.

Decorator

From the above understanding, we can see that whether it is the input stream or the output stream, there is an abstract class FilterInputStream and FilterOutputStream, which acts as a decorator. In Java, iCandle O operations require a variety of different combinations of functions, and this is the reason for using decorator mode.

What is a decorator? The decorator must have the same interface as the object it decorates, but it can also extend the interface, which can provide us with considerable flexibility, but it can also increase the complexity of the code.

FilterInputStream and FilterOutputStream are two classes used to provide decorator class interfaces to control specific input streams (InputStream) and output streams (OutputStream).

FilterInputStream

If InputStream is used as a byte input stream, the read data should be received by byte array, as follows:

We have to use a byte array to receive the read value and then convert it to a string type.

Now that we have the decorator FilterInputStream, can we use a subclass of the decorator to help us read? Let's first take a look at the common FilterInputStream subclasses:

The class function DataInputStream is used in conjunction with DataOutputStream so that we can read the basic data type (int,char,long) BufferedInputStream from the stream in a portable way to prevent the actual write operation every time it is read. Stands for "buffer zone"

DataInputStream allows us to read different basic data types and String objects, and with the corresponding DataOutputStream, we can "stream" the basic types of data from one place to another.

Then before we talk about BufferedInputStream, let's look at a set of test code:

At present, there are three text files, of which the test01.txt size is about 610m, and all of them are empty text files.

So we now write text with ordinary InputStream + OutputStream and decorated BufferedInputStream + BufferedOutputStream, respectively.

Common combination:

Buffer combination:

You can see that the two methods are time-consuming, 4864 ms and 1275 ms respectively. Using a normal combination is equivalent to four times the length of the buffer, and if the file is larger, the difference is amazing! Surprised must also be surprised at the same time, this is why?

If you use the read () method to read a file, every byte read will have to access the hard disk, this way of reading is very inefficient. Even if the read (byte b []) method is used to read more than one byte at a time, the disk will be manipulated frequently when the read file is large.

BufferedInputStream's API document explains that when you create a BufferedInputStream, an array of internal buffers is created. When reading bytes in the stream, you can repopulate the internal buffer from the included input stream as needed, filling multiple bytes at a time. In other words, buffered class initialization will create a large byte array, read multiple bytes from the underlying input stream to populate the byte array, when the program reads one or more bytes, it can be obtained directly from the byte array, when the byte in memory is read, it will again fill the buffer array with the underlying input stream. So this way of reading data from direct memory is much more efficient than accessing the disk every time.

Instead of directly manipulating the data source, BufferedInputStream/BufferedOutputStream wraps other byte streams, which are processing streams.

The program saves the data to the BufferedOutputStream buffer, not immediately to the file, and the array in the buffer is saved to the file in the following cases:

The buffer is full

Flush () clears the buffer

Close () closes the stream

FilterOutputStream

The basic operations of OutputStream are as follows:

You can write the value to the file by calling the write () method. Here are two things to note:

Writing to a document is overwritten by default

According to our understanding, when the method is called twice, the content in the text file should be two lines of official account: Cai Liangji, but in fact only one line is used, this is because the content written later will overwrite the content that already exists before, and the solution is to add append = true to the constructor.

The difference between writing and reading is that if the file does not exist when reading, it will report an error, but if the file does not exist when writing, it will create the file for you by default.

The decorator class FilterOutputStream also exists in OutputStream. Here are the common subclasses of the decorator class:

Class function DataOutputStream is used in conjunction with DATAInputStream to write basic type data (int,char,long, etc.) to the stream in a portable way. BufferedOutputStream uses it to avoid the actual write operation every time the data is sent, representing the use of a buffer. You can call flush to empty the buffer.

DataOutputStream and BufferedOutputStream have already talked about it above, so I won't repeat it here.

Reader and Writer

In Java 1.1, a major change was made to the basic Imax O stream class library, adding two classes, Reader and Writer. In my previous limited cognition, I would mistakenly think that these two categories appeared to replace InputStream and OutputStream, but the fact is not similar to my limited cognition.

InputStream and OutputStream provide functions for iMaple O in byte-oriented form, while Reader and Writer provide compatibility with Unicode in character-oriented form.

Both coexist and provide adapters-InputStreamReader and OutputStreamWriter

InputStreamReader can convert InputStream to Reader

OutputStreamWriter can convert OutputStream to Writer

Although the two are not exactly the same, they are also very similar. The comparison is as follows:

Byte stream character stream InputStreamReaderOutputStreamWriterFileInputStreamFileReaderFileOutputStreamFileWriterByteArrayInputStreamCharArrayReaderByteArrayOutputStreamCharArrayWriterPipedInputStreamPipedReaderPipedOutputStreamPipedWriter

Even the decorator class is almost similar:

Byte stream character stream FilterInputStreamFilterReaderFilterOutputStreamFilterWriterBufferedInputStreamBufferedReaderBufferedOutputStreamBufferedWriterPrintStreamPrintWriter

The way to use Reader and Writer is also very simple:

By the way, let's take a look at the use of BufferedReader and BufferedWriter.

RandomAccessFile

RandomAccessFile is suitable for files made up of records of known size, so we can use seek () to move records from one place to another, and then read or modify records. The size of the records in the file is not necessarily the same, as long as we can determine which records are how big and where they are in the file.

We can see from the figure that RandomAccessFile does not inherit from InputStream and OutputStream interfaces, but from DateInput and DataOutput, which are somewhat unfamiliar.

It's a bit of a maverick class. Let's move on to its constructor:

We only intercept part of the constructor, after all, only the key points.

Looking at the constructor, you can see that there are four modes defined here:

R Open text read-only, which means that you cannot use write to operate files rw read and write operations are allowed rws whenever write operations are performed, synchronously refresh to disk, refresh content and metadata rwd whenever write operations are performed, synchronously refresh to disk, refresh content

What good will it do? To put it bluntly, RandomAccessFile is a category that wants everything. Can both read and write

In essence, RandomAccessFile works like a combination of DataInputStream and DataOutputStream, adding methods where the method getFilePointer () is used to find the current file location, seek () is used to move to a new location within the file, and length () is used to determine the maximum size of the file. The second parameter is used to indicate whether we are "random read (r)" or "read and write (rw)", but it does not support writing files separately. Let's actually do this:

Get read-only RandomAccessFile:

Get readable and writable RandomAccessFile

We first write four words of test to the file, then move the header pointer by three bits and then continue to write four words of File, and the result becomes testFile, because the writing starts at the fourth position after moving the pointer.

ZIP

When we see the word zip, we should think of compressed files, and yes, compressed files are also extremely important in Java I Pot O. Perhaps it should be said that the compression of files is also extremely important in our development.

Classes that need to be compressed about ZIP are provided in the Java built-in classes, and you can use ZipOutuputStream and ZipInputStream in the java.util.zip package to compress and decompress files. Let's first take a look at how to compress files.

ZipOutputStream

The construction method of ZipOutputStream is as follows:

Public ZipOutputStream (OutputStream out) {/ * doSomething * /}

We need to pass in an OutputStream object. So we can also roughly think that a compressed file is equivalent to writing data to a compressed file, which may sound a little roundabout. Let's first take a look at what API are in ZipOutputStream:

The return value of the method indicates that putNextEntry (ZipEntry e) void starts writing a new ZipEntry and moves the position in the stream to the beginning of the data valued by this entry. Write (byte [] b, int off, int len) void writes the byte array to the current ZIP entry data setComment (String command) void sets the comment text finish () void of this ZIP file to finish writing the contents of the ZIP output stream without closing the OutputStream it matches.

Let's demonstrate how to compress a file:

Scene: we need to compress the TestFile folder under disk D into test.zip under disk D.

The specific operation logic is as follows:

Through the above steps, we can compress a file smoothly.

ZipInputStream

After talking about how to compress the file, then naturally how to decompress the file!

Public ZipInputStream (InputStream in) {/ * doSomethings * /}

ZipInputStream is similar to a compressed stream, the constructor also needs to pass in an InputStream object, and there is no doubt that API must correspond to each other one by one:

The return value of the method indicates where read (byte [] b, int off, int len) int reads the off offset in the target b array. The length is len bytes avaiable () int determines whether the data specified by the current entry has been read, and returns 0 if it has finished reading. Otherwise, return 1closeEntry () void to close the current ZIP entry and locate the stream to read the next entry skip (long n) long skips the specified number of bytes in the current ZIP entry getNextEntry () ZipEntry reads the next ZipEntry And move the position within the stream to the beginning of the data that the entry refers to, createZipEntry (String name) ZipEntry, create a new ZipEntry object with the specified name parameter

So let's take a look at how to extract a file:

Don't be intimidated by the length of the code, read it carefully and you'll find it's easy to extract the file:

We use the getNextEntry () method to get a ZipEntry. The way to get the file here is similar to deep traversal, and the directory returned each time is roughly as follows:

Every time we traverse all the files in a directory, such as all the files in the dir01 folder, we will continue to traverse the dir02 folder, so we don't have to use recursion to get all the files. After fetching each file, the output stream is obtained through ZipFile, and then written to the decompressed file. The general process is as follows:

New Ipaw O

The new JavaI/O class library has been introduced into JDK1.4 's java.nio.* package, and its purpose is also simple, which is to improve speed. In fact, the old Imax O package has been reimplemented using nio to take full advantage of this speed increase.

As long as the structure used is closer to the way the operating system executes Icano, speed will naturally increase, resulting in two concepts: channels and buffers.

How do we understand the concepts of channel and buffer? We can think of the buffer as a small train in a coal mine, the passage is equivalent to the track of a train, and the small train is carrying full coal mines from the source to other places. So instead of interacting directly with the channel, we interact with the buffer and dispatch the buffer to the channel. The channel either gets data from the buffer or sends data to the buffer.

ByteBuffer is the only buffer that interacts directly with the channel and can store raw bytes.

ByteBuffer buffer = ByteBuffer.allocate (1024)

The way ByteBuffer is created can usually be specified by the allocate () method. At the same time, ByteBuffer supports the creation of ByteBuffer in 4.

In order to better support the new iMaple O, three classes in the old iMaple O class library have been modified to generate FileChannel. The modified class is: FileInputStream,FileOutputStream and RandomAccessFile for both reading and writing. It is worth noting that these are byte operation streams because character streams cannot be used to generate channels, but Channels provides practical methods for generating Reader and Writer in channels.

Get channel

We have learned that there are three classes that support the generation of channels. The specific methods for generating channels are as follows:

These are the three ways to create a channel and have been tested for read and write operations. Let's take a look at the test code in the figure and summarize it:

The getChannel () method will produce a FileChannel. We can send it ByteBuffer that can be used for reading and writing. One of the ways we store bytes in ByteBuffer is to populate them directly with the put () method, filling in one or more bytes, or values of the basic data type. However, you can also "wrap" an existing byte array into ByteBuffer using the wray () method. In this way, instead of copying the underlying array, it can be used as the memory of the resulting ByteBuffer, which can be called array-supported ByteBuffer.

We can also see the position () method used by FileChannel, which moves the FileChannel around the file, where we move it to the end and then do other read and write operations.

For read-only access, we must explicitly use the static allocate () method to allocate ByteBuffer. If we want to get better speed, we can also use allocateDirect () to produce a "direct" buffer that is more coupled to the operating system. However, this allocation will be more expensive, and the implementation varies from operating system to operating system.

If we want to call read () to store bytes to ByteBuffer, we must call the flip () method on the buffer, which is used to tell FileChannel that it is ready for others to read bytes and, of course, to get maximum speed. Here we don't continue to use buffers for further operations after we use ByteBuffer to receive bytes, and if we need to continue read (), we have to call the clear () method to prepare for each read () method.

Channel connection

Programmers tend to be lazy, and the above method of reading and then notifying FileChannel seems to be troublesome. So is there an easier way? There must be, otherwise I wouldn't ask, right? that is to connect one channel directly to another, with the help of special methods transferTo () and transferFrom (). The specific uses are as follows:

Either method 1 or method 2 can successfully write the file to the test03.txt file

At this point, I believe you have a deeper understanding of "how to use Java IO". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report