1、核心类
映射方式读取文件涉及的核心类:java.nio.channels.FileChannel。该类通过 FileInputStream 实例的 getChannel 方法所获得的通道将允许进行读取操作;通过 FileOutputStream 实例的 getChannel 方法所获得的通道将允许进行写入操作。
对于该类的其他详细解释,可参见JDK_API_1_6_zh_CN.CHM的FileChannel类。
2、输入流InputChannelImpl
该类构造函数有两个参数:输入文件,读取输入文件的byte模板的大小(即一次读取多长的字符)。
该类提供三个方法:打开一个文件来读取(open())、读取下一节数据(read_next())和判断文件是否读完(end_of_stream())。
源代码如下:
package com.emms.raw.channel.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import org.apache.log4j.Logger; /** * 通过映射方式读取文件。 * @author Administrator * */ public class InputChannelImpl { /** * 打印日志对象。 */ Logger logger = Logger.getLogger(InputChannelImpl.class); /** * 文件输入流。 */ private FileInputStream fileInputStream; /** * 输入流对于的文件通道。 */ private FileChannel fileChannel; /** * 作为映射模板的字节缓冲区。 */ private ByteBuffer byteBuffer; /** * */ private int byteBufferSize; /** * 用户输入的文件。 */ private File file; /** * 从文件中读取的映射模板大小的字节数组。 */ private byte[] bytelist; /** * 是否读取完毕。 */ private boolean isEnd = true; /** * 对应文件的输入流。 * @param file 输入文件。 * @param size 读取输入文件的byte模板的大小,即一次读取多长的字符。 */ public InputChannelImpl(File file,int size) { this.file = file; this.byteBufferSize = size; } /** * 打开一个文件来读取. */ public void open() { try { fileInputStream = new FileInputStream(this.file); } catch (FileNotFoundException e) { logger.error("Open File : " + file.getPath() + " failed",e); } fileChannel = fileInputStream.getChannel(); logger.info("Open File : " + file.getPath() + " success"); } /** * 读取下一个. */ public byte[] read_next() { if(fileChannel.isOpen()) { byteBuffer = ByteBuffer.allocate(byteBufferSize); try { fileChannel.read(byteBuffer); } catch (IOException e) { logger.error("Read data failed, because : IOException",e); } bytelist = byteBuffer.array(); } logger.info("Return bytelist length: " + bytelist.length + ". Read from " + file.getPath()); return bytelist; } /** * 当一个判断return true时,说明到达流的末尾. * @return */ public boolean end_of_stream() { try { if(fileChannel.position() < fileChannel.size()) { isEnd = false; } else { isEnd = true; close(); } } catch (ClosedChannelException e) { logger.info("The fileChannel is Closed"); } catch (IOException e) { logger.error("Get fileChannel position failed, because : IOException",e); } logger.info("Return isEnd : " + isEnd + ". Read from " + file.getPath()); return isEnd; } /** * 关闭输入流和读取数据的通道。 */ private void close() { if(fileChannel != null) { try { fileChannel.close(); } catch (IOException e) { logger.error("Close fileChannel failed, because : IOException",e); } } if(fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { logger.error("Close fileInputStream failed, because : IOException",e); } } } }
3、输出流OutputChannelImpl
该类构造函数有一个参数:需要创建的文件路径字符串,文件路径字符串的合法性需要调用者校验。该类提供三个方法:创建一个新文件(create())、在流中写入一个元素(write())和关闭一个流(close())。源代码如下:package com.emms.raw.channel.impl; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import org.apache.log4j.Logger; /** * 通过映射方式输出文件。 * @author Administrator * */ public class OutputChannelImpl { /** * 打印日志对象。 */ Logger logger = Logger.getLogger(OutputChannelImpl.class); /** * 需要创建的文件路径。 */ private String filePath; /** * 通过文件路径,创建的文件。 */ private File file; /** * 输出流。 */ private FileOutputStream fileOutputStream; /** * 输出流对于的文件通道。 */ private FileChannel fileChannel; /** * 作为映射模板的字节缓冲区。 */ private ByteBuffer byteBuffer; /** * 构造方法,必须设置所需创建的文件路径。 * @param filePath */ public OutputChannelImpl(String filePath) { this.filePath = filePath; } /** * 创建一个新文件. */ public void create() { file = new File(this.filePath); try { fileOutputStream = new FileOutputStream(file); } catch (FileNotFoundException e) { logger.error("Create File : " + this.filePath + " failed",e); } fileChannel = fileOutputStream.getChannel(); logger.info("Create File : " + this.filePath + " success"); } /** * 在流中写入一个元素. * @param byteList */ public void write(byte[] byteList) { if(fileChannel.isOpen()) { byteBuffer = ByteBuffer.wrap(byteList); try { fileChannel.write(byteBuffer); } catch (IOException e) { logger.error("Write byteList length : " + byteList.length + ". to " + this.filePath + " failed, because : IOException",e); } logger.info("Write byteList length : " + byteList.length + ". to " + this.filePath + " success"); } else { logger.info("FileChannel is not opened"); } } /** * 关闭一个流. */ public void close() { if(fileChannel != null) { try { fileChannel.close(); } catch (IOException e) { logger.error("Close fileChannel failed, because : IOException",e); } } if(fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { logger.error("Close fileOutputStream failed, because : IOException",e); } } } }