java 新IO 常用接口

新IO提供原生支持的数据处理接口

———缓冲区:Buffer、ByteBuffer:

package com.mldn;

import .nio.ByteBuffer;

public class ByteBuf

{

public static void main(String[] args)

{

ByteBuffer buf = null; // 声明字节缓冲区

buf = ByteBuffer.allocate(10); // 开辟10个字节的缓冲区

System.out.println(“初始状态下各参数的值:”);

System.out.println(“capacity: ” + buf.capacity() + ” limit: ” + buf.limit() + ” position: ” + buf.position());

byte b = (byte)1; // 一个byte

buf.put(b); // 写入缓冲区当前位置

System.out.println(“写入一个单位数据后各参数的值:”);

System.out.println(“capacity: ” + buf.capacity() + ” limit: ” + buf.limit() + ” position: ” + buf.position());

byte[] a = “hello”.getBytes(); // 5个byte

buf.put(a); // 写入缓冲区当前位置

System.out.println(“再写入5个单位数据后各参数的值:”);

System.out.println(“capacity: ” + buf.capacity() + ” limit: ” + buf.limit() + ” position: ” + buf.position());

buf.flip(); // 将position置0,limit置当前position;

System.out.println(“重设缓冲区后各参数的值:”);

System.out.println(“capacity: ” + buf.capacity() + ” limit: ” + buf.limit() + ” position: ” + buf.position());

buf.clear(); // 清空缓冲区:将复位到出始状态;

System.out.println(“清空缓冲区后各参数的值:”);

System.out.println(“capacity: ” + buf.capacity() + ” limit: ” + buf.limit() + ” position: ” + buf.position());

}

}

/*

ubuntu@xu-desktop:~$ com.mldn.ByteBuf

初始状态下各参数的值:

capacity: 10 limit: 10 position: 0

写入一个单位数据后各参数的值:

capacity: 10 limit: 10 position: 1 // 写入一个字节,位置0–>1

再写入5个单位数据后各参数的值:

capacity: 10 limit: 10 position: 6 // 写入5个字节,1–>6

重设缓冲区后各参数的值:

capacity: 10 limit: 6 position: 0

清空缓冲区后各参数的值:

capacity: 10 limit: 10 position: 0

// rewind()方法只是置当前position为0,而不管limit!

// 0 */

/*
传统型的IO,处理过程如下
(1)准备就绪—->(2)接受连接(accept阻塞)——>(3)读取服务器请求(阻塞)——>(4)改请求业务逻辑处理(如)—–>(5)发送响应至服务器———-(2)重新开始
如果在(2)accept的时候,接受到A请求,服务器会read A请求的请求数据,如果在此时A数据读取阻塞,那么接下来的B请求,将得不到响应;
为此。我们通常的处理方式是在
  |————–线程1
(2)接受连接(accept阻塞)—|————–线程2
  |————–线程3
  ……..
进行线程分发;
在使用了NIO以后,利用一种selector.select同样是的需要阻塞才能得到,这一点我认为跟accept没有本质区别,不同的是select能够得到多个channel的处理状态,迭代进行顺序处理:
*/
—–IntBuffer:

package com.mldn;

import .nio.IntBuffer;

public class IntBuf

{

public static void main(String[] args)

{

IntBuffer buf = IntBuffer.allocate(10); // 准备10个大小 的缓冲区

System.out.print(“1.写入数据之前的position,limit和capacity:”);

System.out.println(“position = ” + buf.position() + “, limit = ” + buf.limit() + “, capacity = ” + buf.capacity());

int[] temp = {5, 7, 9}; // 定义一个int数组

buf.put(3); // 设置一个数据

buf.put(temp); // 此时已经放了四个记录

System.out.print(“2.写入数据之后的position,limit和capacity:”);

System.out.println(“position = ” + buf.position() + “, limit = ” + buf.limit() + “, capacity = ” + buf.capacity());

buf.flip(); // 置position为0,limit为当前position值;

System.out.print(“2.重置之后的position,limit和capacity:”);

System.out.println(“position = ” + buf.position() + “, limit = ” + buf.limit() + “, capacity = ” + buf.capacity());

System.out.print(“缓冲区内容:”);

while (buf.hasRemaining())

{

System.out.print(buf.get() + ” “);

}

System.out.println();

}

}

/*

ubuntu@xu-desktop:~$ com.mldn.IntBuf

1.写入数据之前的position,limit和capacity:position = 0, limit = 10, capacity = 10

2.写入数据之后的position,limit和capacity:position = 4, limit = 10, capacity = 10

2.重置之后的position,limit和capacity:position = 0, limit = 4, capacity = 10

缓冲区内容:3 5 7 9

*/

——–只读缓冲区:

package com.mldn;

import java.nio.IntBuffer;

public class ReadOnlyBuf

{

public static void main(String[] args)

{

IntBuffer buf = IntBuffer.allocate(10); // 准备10个大小的缓冲区

IntBuffer read = null; // 定义子缓冲区

for (int i = 0; i {

buf.put(2 * i + 1); // 在主缓冲区中加入10个奇数

}

read = buf.asReadOnlyBuffer(); // 创建只读 缓冲区

read.flip(); // 重设子缓冲区

System.out.println(“主缓冲区中内容:”);

while (read.hasRemaining())

{

int x = read.get();

System.out.print(x + ” “);

}

System.out.println(“\n往子缓冲区中写入:”);

read.put(30); // 写入一个值,将报错

}

}

/*

ubuntu@xu-desktop:~$ java com.mldn.ReadOnlyBuf

主缓冲区中内容:

1 3 5 7 9 11 13 15 17 19

往子缓冲区中写入:

Exception in thread “main” java.nio.ReadOnlyBufferException

at java.nio.HeapIntBufferR.put(HeapIntBufferR.java:148)

at com.mldn.ReadOnlyBuf.main(ReadOnlyBuf.java:24)

// 说明只读 缓冲区不能写入!用于只读不写的操作;

*/

———–直接缓冲区:
直接缓冲区创建后,jvm尽最大努力执行本机的IO操作;

package com.mldn;

import java.nio.ByteBuffer;

public class DirectBuf

{

public static void main(String[] args)

{

ByteBuffer buf = ByteBuffer.allocateDirect(10); // 准备10个直接字节缓冲区

byte[] temp = {1, 3, 5, 7, 9}; // 设置内容

buf.put(temp); // 设置一组内容

buf.flip();

System.out.println(“缓冲区内容:”);

while (buf.hasRemaining())

{

int x = buf.get();

System.out.print(x + ” “);

}

System.out.println();

}

}

/*

ubuntu@xu-desktop:~$ java com.mldn.DirectBuf

缓冲区内容:

1 3 5 7 9

// 该操作和普通缓冲区的操作一致,只不过其性能有所提升,执行速度快!

*/

// java新IO是对缓冲区操作的类库,对除了boolean类型以外的所有原生数据类型进行了缓冲区的操作实现!

—————-通道(Channel)
通道可以用来读取和写入数据,通道类似于之前的输入/输出流,但是程序不会直接操作通道!
所有的内容都是先读入到或写入到缓冲区之后,在通过缓冲区中取得或写入的;
通道与传统流的操作不同,传统的流操作分为输入和输出流的,而通道本身是双向操作的,既可以完成输入也可以完成输出;
——Channel——Channel—->缓冲区——-从通道读入缓冲区!
可以获取一个File类型的Channel:

FileChannel getChannel();

——-获取文件通道并写入通道:

package com.mldn;

import java.io.File;

import java.io.FileOutputStream;

import java.nio.channels.FileChannel;

import java.nio.ByteBuffer;

public class FileChannelOut

{

public static void main(String[] args) throws Exception

{

String[] info = {“k187”, “www.k187.com”, “k187.com”};

File file = new File(File.separator + “home” + File.separator + “ubuntu” + File.separator + “infofile.txt”);

FileOutputStream output = null; // 声明输出流

FileChannel fout = null; // 声明文件通道

output = new FileOutputStream(file);

fout = output.getChannel(); // 获取输出流的通道

ByteBuffer buf = ByteBuffer.allocate(1024); // 开辟1024字节的缓冲区

for (int x = 0; x {

buf.put(info[x].getBytes()); // 写入缓冲区

}

buf.flip(); // 重设

fout.write(buf); // 从缓冲区写入通道

fout.close(); // 关闭通道

output.close(); // 关闭输出流

}

}

/*/home/ubuntu/infofile.txt:

k187www.k187.comk187.com

*/

————用通道实现有固定缓冲区的输入输出:

package com.mldn;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.File;

import java.nio.channels.FileChannel;

import java.nio.ByteBuffer;

public class FileChannelIO

{

public static void main(String[] args) throws Exception

{

File file1 = new File(“/home/ubuntu/infofile.txt”); // 源文件

File file2 = new File(“/home/ubuntu/infocopy.txt”); // 目标文件

FileInputStream input = null; // 输入流

FileOutputStream output = null; // 输出流

input = new FileInputStream(file1);

output = new FileOutputStream(file2);

FileChannel fout = null; // 声明写入的文件通道

FileChannel fin = null; // 声明读取的文件通道

fout = output.getChannel(); // 得到输出通道

fin = input.getChannel(); // 得到输入通道

ByteBuffer buf = ByteBuffer.allocate(1024); // kaip huanchongq

int temp = 0;

while ((temp = fin.read(buf)) != -1) // 读取1024字节的数据到buf

{

buf.flip(); // 置position = 0

fout.write(buf); // 一次性把当前buf内容写入通道

buf.clear(); // 清空缓冲区,所有参数恢复到原点,准备接收下一次的写入

}

fin.close();

fout.close();

input.close();

output.close();

}

}

/*

该实例用输入通道读入数据源到缓冲区,然后从缓冲区一次性写出数据到输出通道,这是一种快速的双向操作;

这个过程是反复执行的,直到读完数据源的数据!

本程序的缓冲区是1024,即每次最大处理1024字节数据,当然可以更大,根据需要而定!

*/

———用通道和缓冲区实现内存映射:
内存映射可以把文件映射到内存中,这样文件的数据就可以用内存的读/写指令来访问,而不是用InputStream或OutputStream这样的I/O操作类,采用此种方式读取文件的速度是最快的。
数据读入的方式:
1.RandomAccessFile,较慢;
2.FileInputStream,较慢;
3.缓冲读取,速度较快;
4.内存映射,速度最快;
// 内存映射缓冲区:

public abstract class MappedByteBuffer

extends ByteBuffer

// 该缓冲区是直接内存缓冲区,它的内容是某个文件的内存映射!
A direct byte buffer whose content is a memory-mapped region of a file.
// FileChannel抽象类提供内存映射操作:获取一个内存映射的缓冲区
public abstract MappedByteBuffer map(FileChannel.MapMode mode,
                                     long position, // 开是位置
                                     long size)        // 字节长度
                              throws IOException
        // 直接映射当前通道的文件区域到内存
    Maps a region of this channel's file directly into memory.
    A region of a file may be mapped into memory in one of three modes:
// 三种映射模式:

static FileChannel.MapMode PRIVATE // 专用写入copy的映射

Mode for a private (copy-on-write) mapping.

static FileChannel.MapMode READ_ONLY // 只读映射

Mode for a read-only mapping.

static FileChannel.MapMode READ_WRITE // 读写映射

Mode for a read/write mapping.
——实例:

package com.mldn;

import java.io.FileInputStream;

import java.io.File;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

public class MappedMemory

{

public static void main(String[] args) throws Exception

{

File file = new File(“/home/ubuntu/infofile.txt”); // 被映射的文件

FileInputStream input = null; // 输入流

input = new FileInputStream(file);

FileChannel fin = null; // 文件通道用于输入到缓冲区

fin = input.getChannel(); // 获取文件输入通道

MappedByteBuffer mbb = null; // 声明内存映射缓冲区

mbb = fin.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); // 映射操作,只读方式,从文件头开始,长度为整个文件

byte[] data = new byte[(int)file.length()]; // 接收映射缓冲区的输入

int foot = 0;

while (mbb.hasRemaining())

{

data[foot++] = mbb.get(); // 读取内存映射

}

System.out.print(new String(data)); // 数据输出到屏幕

fin.close();

input.close(); // 关闭

}

}

/*

ubuntu@xu-desktop:~$ java com.mldn.MappedMemory

public abstract class FileChannel

extends AbstractInterruptibleChannel

implements ByteChannel, GatheringByteChannel, ScatteringByteChannel

A channel for reading, writing, mapping, and manipulating a file.

A file channel has a current position within its file which can be both queried and modified. The file itself contains a variable-length sequence of bytes that can be read and written and whose current size can be queried. The size of the file increases when bytes are written beyond its current size; the size of the file decreases when it is truncated. The file may also have some associated metadata such as access permissions, content type, and last-modification time; this class does not define methods for metadata access.

………….// 屏幕上打印所有文件内容。这是一次性完成的!

*/

// 内存映射的方式,直接对磁盘数据在内存中的映射操作,不当的设置很危险,很可能再写的时候把磁盘数据破坏,因为在内存中的任何修改都等价于直接保存修改到磁盘数据上;
//比较适合读取操作;

———用通道实现文件锁功能:
文件锁:当一个线程将文件锁定后其他线程是无法操作此文件的,锁定文件需要使用FileLocke类完成,此类的实例依赖于FileChannel;
// FileChannel类提供以下方法:

FileLock lock() // 获取此通道的文件独占锁定

Acquires an exclusive lock on this channel's file.

abstract FileLock lock(long position, long size, boolean shared)

// 获得此通道文件给定区域的锁定,并指定锁定位置、锁定大小、是共享锁定(true)还是独占锁定(false);
          Acquires a lock on the given region of this channel's file.

FileLock tryLock() // 试图获取此通道的独占锁定

Attempts to acquire an exclusive lock on this channel's file.

abstract FileLock tryLock(long position, long size, boolean shared)

// 试图获得此通道文件给定区域的锁定,并指定锁定位置、锁定大小、是共享锁定(true)还是独占锁定(false);
          Attempts to acquire a lock on the given region of this channel's file.
// 文件锁:

public abstract class FileLock

extends Object

A token representing a lock on a region of a file.

boolean isShared() // 判断是否为共享锁定

FileChannel channel() // 返回此锁定的FileChannel

abstract void release() throws IOException // 释放锁定,解锁

long size(); // 锁定区域的字节长度

共享锁:允许多个线程进行共享的读取操作;
独占锁:只允许锁定线程进行读/写操作;
——获取独占文件锁:

package com.mldn;

import java.io.File;

import java.io.FileOutputStream;

import java.nio.channels.FileChannel;

import java.nio.channels.FileLock;

public class FileLocker

{

public static void main(String[] args) throws Exception

{

File file = new File(“/home/ubuntu/infofile.txt”);

FileOutputStream output = null;

output = new FileOutputStream(file, true); // 自动追加的写入

FileChannel fout = null;

fout = output.getChannel(); // 得到通道

FileLock lock = fout.lock(); // 进行独占锁定

if (lock != null)

{

System.out.println(file.getName() + “文件被锁定!”);

Thread.sleep(30000);

lock.release(); // 解锁

System.out.println(file.getName() + “文件被释放!”);

}

fout.close();

output.close();

}

}

/*

ubuntu@xu-desktop:~$ java com.mldn.FileLocker

infofile.txt文件被锁定! // 锁定的时候当前进程的其他线程无法获取锁定,但对其他进程不起作用,比如下的文本文件

infofile.txt文件被释放!

*/

package com.mldn;

import java.io.File;

import java.io.FileOutputStream;

import java.nio.channels.FileChannel;

import java.nio.channels.FileLock;

public class FileLocker

{

public static void main(String[] args) throws Exception

{

File file = new File(“/home/ubuntu/infofile.txt”);

FileOutputStream output = null;

output = new FileOutputStream(file, true); // 自动追加的写入

FileChannel fout = null;

fout = output.getChannel(); // 得到通道

FileLock lock = fout.lock(); // 进行独占锁定

if (lock != null)

{

System.out.println(file.getName() + “文件被锁定!”);

Thread.sleep(30000);

lock.release(); // 解锁

System.out.println(file.getName() + “文件被释放!”);

}

fout.close();

output.close();

}

}

/*

ubuntu@xu-desktop:~$ java com.mldn.FileLocker

infofile.txt文件被锁定! // 锁定的时候当前进程的其他线程无法获取锁定,但对其他进程不起作用,比如下的文本文件

infofile.txt文件被释放!

*/

声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 智乐兔
转载请注明:转自《java 新IO 常用接口
本文地址:https://www.zhiletu.com/archives-176.html
关注公众号:智乐兔

赞赏

wechat pay微信赞赏alipay pay支付宝赞赏

上一篇
下一篇

相关文章

在线留言

你必须 登录后 才能留言!

在线客服
在线客服 X

售前: 点击这里给我发消息
售后: 点击这里给我发消息

智乐兔官微