Home  >  Article  >  Java  >  Java Programming Thoughts Learning Class (5) Chapter 18-Java IO System

Java Programming Thoughts Learning Class (5) Chapter 18-Java IO System

php是最好的语言
php是最好的语言Original
2018-08-09 14:45:091527browse

1 File class

File(file) class has the name Certainty misleading; we might think it refers to a file, but it doesn't. It can represent both the name of a specific file, and the ## of a group of files in a directory. #name. Actually, FilePath would be a better name for this class. If it refers to a file set, we can call the list()

method on this collection, which will return a string array .

2 Input and output (Input an output)  The I/O class library of programming languages ​​often uses the abstract concept of

stream

, which represents Any

data source object capable of producing data or a receiving object capable of receiving data. "Streams" mask the details of processing data in the actual I/O device. We rarely use a single class to create a flow object, but instead provide the desired functionality by overlaying multiple objects (this is the decorator design pattern). In fact, the main reason why the "stream" library in Java is confusing is that to create a single result stream, you need to create multiple objects.

 In Java 1.0, the designer of the class library first stipulated that all classes related to
input

should inherit from

InputStream

, and all classes related to output should inherit from OutputStream. read() in InputStream or Reader is used to read a single byte or byte array

, and OutputStream or Writer is used to write a single byte or byte array.

2.1 InputStream type The purpose of InputStream is to represent classes that generate input data from different

data sources

.

Each data source has a corresponding InputStream subclass

. These data sources include: byte arrays. An array of bbytes.

    String objects. A String object.
  • file. A file.
  • "A pipe" (A pipe) works like an actual pipe, that is, input comes from one end and output comes from the other end.
  • A sequence composed of other kinds of streams so that we can collect them into a single stream. A sequence of other streams.
  • #Other data sources, such as Internet connections, etc. Other sources.
  • ##2.2 OutputStream type
  • 

    OutputStream

    class determines the destination to which the output goes:

Byte array

File
  • Pipe
  • 3 Add properties and useful interfaces
  • #FilterInputStream

    and
  • FilterOutputStream
are used to provide

decorator class interface

to control

specific Input stream (InputStream) and Output stream (OutputStream) are two classes whose names are not intuitive. These two classes are necessary for decorators (in order to provide a common interface for all objects being decorated). 4 Reader and WriterInputStream

and

OutputStream

  • byte-oriented

    I/O provides functions of the form ##Reader and Writer

  • character-oriented
  • (Unicode compatible) form of I/O functionality Design Reader and Writer

    inheritance hierarchy primarily for
globalization

. The old I/O stream inheritance hierarchy only supported 8 bit byte streams, and did not handle 16## well. The # digit Unicode character . Since Unicode is used for character internationalization (Java's own char is also 16-bit Unicode), so add Reader and WriterThe inheritance hierarchy is designed to support Unicode in all I/O operations. In addition, the design of the new class library makes its operation faster than the old class library. 5 Self-contained class: RandomAccessFileRandomAccessFile is suitable for files consisting of records of known size, so we can use seek()

Move records from one place to another, and then read or modify records.

RandomAccessFileHas fundamentally different behavior from other I/O types in that we can move forward and backward within a file. In any case, it is self-contained and derived directly from Object.

 Essentially, RandomAccessFile works like combining DataInputStream and DataOutputStream, with some new methods added:

  • getFilePointer() is used to find the current file location,

  • seek() is used to move to a new location within the file,

  • length() is used to determine the maximum size of the file.

6 Typical uses of I/O streams

Although I/O streams can be combined in different ways categories, but we may only use a few combinations of them. The following examples can be used as a basic reference for typical I/O usage.

6.1 Buffered input file

6.2 Input from memory

6.3 Formatted memory input

6.4 Basic file output

6.5 Storing and recovering data

6.6 Reading and writing random access files -access files)

6.7 PipedStreams

7 Standard I/O

Standard I The term /O refers to the Unix concept of "a single flow of information used by a program".

The significance of standard I/O is that we can easily connect programs together, and the standard output of one program can become the standard input of another program.

8 New I/O

The speed increase comes from using a structure that is closer to the way the operating system performs I/O: Channel and buffer . We can think of it like a coal mine, the channels are the deposits containing the coal seams (data), and the buffers are the trucks that are dispatched to the deposits. The trucks come back loaded with coal and we get the coal from the trucks. In other words, we don't interact directly with the channel, we just interact with the buffer and dispatch the buffer to the channel. A channel either gets data from a buffer or sends data to a buffer.

The only buffer that interacts directly with a channel is ByteBuffer - that is, a buffer that can store raw bytes. When we query the java.nio.ByteBuffer in the JDK documentation, we will find that it is a fairly basic class: it creates a ByteBuffer object by telling how much storage space to allocate, and also A selection of methods for outputting and reading data in raw byte form or primitive data types. However, there is no way to output or read objects, not even string objects. This handling is low-level, but it's just right because it's the more efficient way of mapping in most operating systems.

8.1 Channel FileChannel

FileChannel is manipulating the byte stream. Three classes in the old I/O class library have been modified to generate FileChannel:

  • ##FileInputStream.getChannel()

  • FileOutputSteam.getChannel()

  • RandomAccessFile.getChannel()

  • package net.mrliuli.io.nio;import java.nio.*;import java.nio.channels.*;import java.io.*;public class GetChannel {
        private static final int BSIZE = 1024;
        public static void main(String[] args) throws Exception {
            // Write a file:
            FileChannel fc = new FileOutputStream("data.txt").getChannel();
            fc.write(ByteBuffer.wrap("Some text ".getBytes()));
            /*
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            fc.read(buffer);                                            // NonReadableChannelException
            System.out.println((char)buffer.get());
            */
            fc.close();
            // Add to the end of the file:
            fc = new RandomAccessFile("data.txt", "rw").getChannel();   // Readable and Writable        
            fc.position(fc.size()); // Move to the end      
            fc.write(ByteBuffer.wrap("some more".getBytes()));
            fc.close();
            // Read the file:
            fc = new FileInputStream("data.txt").getChannel();
            ByteBuffer buff = ByteBuffer.allocate(BSIZE);       
            fc.read(buff);
            //fc.write(ByteBuffer.wrap("again".getBytes()));            //NonWritableChannelException
            buff.flip();
            while(buff.hasRemaining())
                System.out.print((char)buff.get()); // ByteBuffer.get() returns a byte
            System.out.println();
        }
    }
8.2 Buffer ByteBuffer

will The method of storing bytes in the buffer ByteBuffer:

  • Use

    put() to directly fill in one or more bytes, Or a value of a basic data type;

  • Use

    wrap() to wrap the existing byte array into ByteBuffer.

8.3 read(), write(), flip(), write()

There is an input channel

in and an output channel outAnd a bufferbuffer:

  • ##in.read(buffer); Input the bytes in fc into buffer. At this time, you must adjust buffer.flip(); so that others can follow bufferPreparation for reading bytes.

  • out.write(buffer)Output the bytes in buffer to out, write()After the operation, the information is still in the buffer buffer, and buffer.clear(); must be called for all The internal pointer is rearranged so that the buffer is ready to accept data during another read() operation.

package net.mrliuli.io.nio;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;public class ChannelCopy {    private static final int BSIZE = 1024;    public static void main(String[] args) throws Exception {        if(args.length != 2){
            System.out.println("arguments : sourcefile destfile");
            System.exit(1);
        }        // 打开一个FileChaanel用于读(输入)
        FileChannel in = new FileInputStream(args[0]).getChannel();        // 打开一个FileChannel用于写(输出)
        FileChannel out = new FileOutputStream(args[1]).getChannel();        // 一个缓冲器,分配了BSIZE个字节
        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);        /*
         * return The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream
         * FileChanel.read()
         * */

        // -1 一个分界符(源于Unix和C),表示到达了输入的末尾
        while(in.read(buffer) != -1){

            buffer.flip(); // Prepare for writing
            out.write(buffer);            // write()操作之后,信息仍在缓冲器中,clear()操作对所有的内部指针重新安排,以便缓冲器在另一个read()操作期间能够做好接受数据的准备。
            buffer.clear(); // Prepare for reading
        }

    }

}

8.4 转换数据

缓冲器容纳的是普通的字节,为了把它们转换成字符,我们要么在输入它们的时候对其进行编码(这样,它们输出时才具有意义),要么在将其从缓冲器输出时对它们进行解码。可以使用java.nio.charset.Charset类实现这些功能,该类提供子把数据编码成多种不同类型的字符集的工具。The buffer contains plain bytes, and to turn these into characters, we must either encode them as we put them in (so that they will be meaningful when they come out) or decode them as they come out of the buffer. This can be accomplished using the java.nio.charset.Charset class, which provides tools for encoding into many different types of character set.

8.5 视图缓冲器

  视图缓冲器(view buffer)可以让我们通过某个特定的基本数据类型的视窗查看其底层的ByteBuffer。ByteBuffer依然是实际存储数据的地方,“支持”着前面的视图,因此对视图的任何修改都会映射成为对ByteBuffer中数据的修改。

8.6 文件加锁

  文件加锁对其他的操作系统进程是可见的,因为Java的文件加锁直接映射到了本地操作系统的加锁工具。

exclusive lock 独占锁

Locking portions of a mapped file 对映射文件的部分加锁

cretical section 临界区

9 压缩(Compression)

10 对象序列化(Object serialization)

Java的对象序列化将那些实现了Serilizable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可通过网络朝廷这意味着序列化机制能自动弥补不同操作系统之间的差异。

就其本身来说,对象的序列化是非常有趣的,因为利用它可以实现轻量级持久性(ligthweight persistence)。持久性意味着一个对象的生存周期并不取决于程序是否正在执行,它可以生存于程序的调用之间。

  对象序列化的概念加入到语言中是为了支持两种主要特性:

  • 一是Java的远程方法调用(Remote Method Invocation, RMI),它使存活于其他计算机的对象使用起来就像是存活于本机上一样。当向远程对象发送消息时,需要通过对象序列化来传输参数和返回值。

  • 再者,对Java Beans来说,对象的序列化也是必需的。使用一个Bean时,一般情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动时进行后期恢复;这种具体工作就是由对象序列化完成的。

  序列化一个对象和反序列化

  • 首先要创建一个ObjectOutputStream对象,要通过构造函数含有一个 OutputStream 对象。

  • 然后,只需调用 void writeObject(Object obj),即可将对象obj序列化,即转换成字节序列输出到第一步所说的Outputstream

  • 反序列化,即将字节序列还原为一个对象,则只需调用ObjectInputStreamObject readObject(),输入到一个InputStream

例:

Worm.java

10.1 寻找类

  反序列,即将字节序列还原为对象时,必须保证Java虚拟机能够找到要还原的对象的相关.class文件,否则抛出java.lang.ClassNotFoundException异常。

10.2 序列化的控制

  如果只希望一个对象的某些信息序列化而某些信息不序列化,即进行序列化控制,可使用Externalizable接口。

10.2.1 Externalizable接口

  Externalizable接口继承自Serializable接口,有两个方法如下,这两个方法会在序列化和反序列化过程中被自动调用

  • void writeExternal(ObjectOutput obj),在该方法内部只对所需部分进行显式序列化

  • void readExternal(ObjectInput in)

10.2.2 Externalizable接口与Serializable接口区别

  • Externalizable只序列化writeExternal()中的部分,而Serializable自动地全部序列化。

  • Externalizable在反序列化时(即调用readObject()时),会首先调用所有普通的默认构造器,然后调用readExternal()

  • Serializable在反序列化时,对象完全以它存储的二进制位为基础来构造,而不用调用构造器

例:

Blips.javaBlip3.java

10.2.3 transient(瞬时)关键字

如果我们正操作的是一个Serializable对象,那么所有序列化操作都会自动进行。为了能够予以控制,可以用transient(瞬时)关键字逐个字段地关闭序列化,它的意思是“不用麻烦你保存或恢复数据——我会自己处理的”。

由于Externalizable对象在默认情况下不保存任何字段,所以transient关键字只能和Serializable对象一起使用。

10.3 序列化的持久性

我们可以通过一个字节数组来使用对象序列化,从而实现对任何可Serializable对象的“深度复制”(deep copy)——深度复制意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。

  • 一个对象被序列化在单一流中,就可以恢复出与我们写出时一样的对象网,并且没有任何意外重复复制出的对象。

  • 一个对象被序列化在不同流中,再从不同流恢复时,得到的对象地址不同。

例:

MyWorld.java

对象序列化的一个重要限制是它只是Java的解决方案:只有Java程序才能反序列化这种对象。一种更具互操作性的解决方案是将数据转换为XML格式,这可以使其被各种各样的平台语言使用。

相关文章:

Java编程思想学习课时(三)第15章-泛型

Java编程思想学习课时(四)第17章-容器深入探讨

The above is the detailed content of Java Programming Thoughts Learning Class (5) Chapter 18-Java IO System. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn