1 File class
method on this collection, which will return a string array .
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, FilePathwould be a better name for this class. If it refers to a file set, we can call the list()
2 Input and output (Input an output) The I/O class library of programming languages often uses the abstract concept of
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 toinputInputStreamshould inherit from
, 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
2.1 InputStream type The purpose of InputStream is to represent classes that generate input data from different
data sources. These data sources include: byte arrays. An array of bbytes.
OutputStream
class determines the destination to which the output goes:#FilterInputStream
andspecific
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
I/O provides functions of the form
##Reader and Writer
(Unicode compatible) form of I/O functionality Design Reader and Writer
. The old I/O stream inheritance hierarchy only supported
Move records from one place to another, and then read or modify records.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: RandomAccessFile
RandomAccessFile
is suitable for files consisting of records of known size, so we can use seek()
RandomAccessFile
Has 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.
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.
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.
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 thejava.nio.ByteBuffer
in the JDK documentation, we will find that it is a fairly basic class: it creates aByteBuffer
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.
FileChannel
is manipulating the byte stream. Three classes in the old I/O class library have been modified to generate FileChannel
:
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(); } }
put() to directly fill in one or more bytes, Or a value of a basic data type;
wrap() to wrap the existing byte array into ByteBuffer.
in and an output channel
outAnd a buffer
buffer:
##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. </li></ul><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">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 <tt>-1</tt> 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
}
}
}</pre><div class="contentsignin">Copy after login</div></div><h3>8.4 转换数据</h3><blockquote><p>缓冲器容纳的是普通的字节,为了把它们转换成字符,我们要么在输入它们的时候对其进行<span style="color:red"><strong>编码</strong></span>(这样,它们输出时才具有意义),要么在将其从缓冲器输出时对它们进行<span style="color:red"><strong>解码</strong></span>。可以使用<span style="color:red"><code>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.
视图缓冲器(view buffer)可以让我们通过某个特定的基本数据类型的视窗查看其底层的ByteBuffer。ByteBuffer依然是实际存储数据的地方,“支持”着前面的视图,因此对视图的任何修改都会映射成为对ByteBuffer中数据的修改。
文件加锁对其他的操作系统进程是可见的,因为Java的文件加锁直接映射到了本地操作系统的加锁工具。
exclusive lock 独占锁
Locking portions of a mapped file 对映射文件的部分加锁
cretical section 临界区
Java的对象序列化将那些实现了
Serilizable
接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可通过网络朝廷这意味着序列化机制能自动弥补不同操作系统之间的差异。就其本身来说,对象的序列化是非常有趣的,因为利用它可以实现轻量级持久性(ligthweight persistence)。持久性意味着一个对象的生存周期并不取决于程序是否正在执行,它可以生存于程序的调用之间。
对象序列化的概念加入到语言中是为了支持两种主要特性:
一是Java的远程方法调用(Remote Method Invocation, RMI),它使存活于其他计算机的对象使用起来就像是存活于本机上一样。当向远程对象发送消息时,需要通过对象序列化来传输参数和返回值。
再者,对Java Beans来说,对象的序列化也是必需的。使用一个Bean时,一般情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动时进行后期恢复;这种具体工作就是由对象序列化完成的。
序列化一个对象和反序列化:
首先要创建一个ObjectOutputStream
对象,要通过构造函数含有一个 OutputStream
对象。
然后,只需调用 void writeObject(Object obj)
,即可将对象obj
序列化,即转换成字节序列输出到第一步所说的Outputstream
。
反序列化,即将字节序列还原为一个对象,则只需调用ObjectInputStream
的Object readObject()
,输入到一个InputStream
。
例:
Worm.java
反序列,即将字节序列还原为对象时,必须保证Java虚拟机能够找到要还原的对象的相关.class
文件,否则抛出java.lang.ClassNotFoundException
异常。
如果只希望一个对象的某些信息序列化而某些信息不序列化,即进行序列化控制,可使用Externalizable
接口。
Externalizable
接口继承自Serializable
接口,有两个方法如下,这两个方法会在序列化和反序列化过程中被自动调用。
void writeExternal(ObjectOutput obj)
,在该方法内部只对所需部分进行显式序列化。
void readExternal(ObjectInput in)
Externalizable
只序列化writeExternal()
中的部分,而Serializable
自动地全部序列化。
Externalizable
在反序列化时(即调用readObject()
时),会首先调用所有普通的默认构造器,然后调用readExternal()
。
Serializable
在反序列化时,对象完全以它存储的二进制位为基础来构造,而不用调用构造器。
例:
Blips.javaBlip3.java
transient
(瞬时)关键字如果我们正操作的是一个Serializable对象,那么所有序列化操作都会自动进行。为了能够予以控制,可以用
transient
(瞬时)关键字逐个字段地关闭序列化,它的意思是“不用麻烦你保存或恢复数据——我会自己处理的”。由于
Externalizable
对象在默认情况下不保存任何字段,所以transient
关键字只能和Serializable
对象一起使用。
我们可以通过一个字节数组来使用对象序列化,从而实现对任何可Serializable对象的“深度复制”(deep copy)——深度复制意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。
一个对象被序列化在单一流中,就可以恢复出与我们写出时一样的对象网,并且没有任何意外重复复制出的对象。
一个对象被序列化在不同流中,再从不同流恢复时,得到的对象地址不同。
例:
MyWorld.java
对象序列化的一个重要限制是它只是Java的解决方案:只有Java程序才能反序列化这种对象。一种更具互操作性的解决方案是将数据转换为XML格式,这可以使其被各种各样的平台语言使用。
相关文章:
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!