过去,我讨论过RandomAccessFile以及如何将其用于在Java中进行更快的IO,在本Java NIO教程中,我们将了解如何通过使用FileChannel和ByteBuffer来使用读/写数据。

Channel提供了一种从文件读取数据的替代方法,它提供了比InputStream或OutputStream更好的性能。 也可以在阻止和非阻止模式下打开它。 虽然, FileChannles是读/写通道,并且它们始终处于阻塞状态 ,但不能将其置于非阻塞模式。 RandomAccessFile类将文件视为字节数组。

您可以在数组的任何位置写入数据,也可以从任何位置读取数据。 为此,它使用保存当前位置的指针,并提供诸如seek()几种方法来移动该指针。 一旦定位正确,就可以从RandomAccessFile获取FileChannel并开始从文件中读取数据。 顺便说一下,JDK 7还引入了NIO 2,它使处理文件和目录变得更加容易。 阅读Anghel Leonard 撰写的Pro Java 7 NIO.2以了解更多信息。

如何使用FileChannel和ByteBuffer读取/写入文件

在开始编码之前,让我们修改Java NIO中Channel和Buffer的基本概念。 一言以蔽之,缓冲区与通道一起工作。 通道是传输数据的管道,缓冲区是数据传输的源和目标。 对于写操作,要写入的数据放置在缓冲区中,该缓冲区将传递到通道,而不是通道从缓冲区读取该数据并将其写入文件。

同样,在读取的情况下,通道会将数据放入您从文件 , 网络或任何其他来源提供的缓冲区中。 由于相同的缓冲区用于读取和写入,即您将数据写入缓冲区,而通道将其读取以写入文件,因此,一旦完成写入缓冲区,就必须调用flip()方法。 flip()方法更改指针,并允许您从缓冲区读取数据。 Java中的缓冲区有三种类型, 直接缓冲区,非直接缓冲区和映射缓冲区 。 在此示例中,我们将使用直接字节缓冲区。

使用FileChannel和Buffer读取/写入数据的步骤

这是逐步指南,开始使用RandomAccessFileFileChannelByteBuffer从文件读取数据:

  1. 在读取/写入模式下使用RandomAccessFile打开要读取/写入的文件。
  2. 调用RandomAccessFile的getChannel()方法以获取FileChannel。 返回的通道的位置将始终等于getFilePointer()方法返回的此对象的文件指针偏移量。
  3. 使用ByteBuffer.allocate()方法创建一个ByteBuffer。
  4. 使用各种数据存储到字节缓冲区put()方法例如putInt() putLong()
  5. 翻转缓冲区,以便Channel可以从缓冲区读取数据并写入文件。 flip()方法更改指针,并允许您从缓冲区读取数据。
  6. 调用FileChannel的write()方法。
  7. 关闭文件通道
  8. 关闭RandomAccessFile。

要注意的另一个重要点是,可以使用相同的缓冲区进行读写,但是需要翻转它。 现在,让我们看一个示例Java程序,该程序使用Java中的FileChannel和ByteBuffer从文件读取/写入数据。 在Memory Mapped File之后 ,这是从Java中读取和写入文件的第二快的方法。

Java程序,使用FileChannel和ByteBuffer从文件读取/写入

这是示例程序,以演示如何使用FileChannel和ByteBuffer类从文件(可以是二进制文件或文本文件)读取和写入数据。 我还使用抽象来创建一个名为Persistable的接口,该接口提供了两种方法persist()recover() 。 任何实现此接口的对象都可以保存和加载,但是如何保存和加载它们则留给实现者,即可以像我们一样使用Chanel和Buffer,也可以使用旧方法在Java中读取/写入文件。 。

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;/*** Java Program to read and write on RandomAccessFile in Java* using FileChannle and ByteBuffer.** @author Javin*/
public class FileChannelDemo {public static void main(String args[]) {Tablet ipad = new Tablet("Apple", true, 1000);System.out.println("Writing into RandomAcessFile : " + ipad);write("tablet.store", ipad);Tablet fromStore = new Tablet();read("tablet.store", fromStore);System.out.println("Object read from RandomAcessFile : " + fromStore);}/** Method to write data into File using FileChannel and ByteBuffeer*/public static void write(String filename, Persistable object) {try {// Creating RandomAccessFile for writingRandomAccessFile store = new RandomAccessFile("tablet", "rw");// getting FileChannel from fileFileChannel channel = store.getChannel();// creating and initializing ByteBuffer for reading/writing dataByteBuffer buffer = ByteBuffer.allocate(2048);// an instance of Persistable writing into ByteBufferobject.persist(buffer);// flip the buffer for writing into filebuffer.flip();int numOfBytesWritten = channel.write(buffer); // writing into FileSystem.out.println("number of bytes written : " + numOfBytesWritten);channel.close(); // closing file channelstore.close(); // closing RandomAccess file} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/** Method to read data from File using FileChannel and ByteBuffeer*/public static void read(String filename, Persistable object) {try {// Opening RandomAccessFile for reading dataRandomAccessFile store = new RandomAccessFile("tablet", "rw");// getting file channelFileChannel channel = store.getChannel();// preparing buffer to read data from fileByteBuffer buffer = ByteBuffer.allocate(1024);// reading data from file channel into bufferint numOfBytesRead = channel.read(buffer);System.out.println("number of bytes read : " + numOfBytesRead);// You need to filp the byte buffer before readingbuffer.flip();// Recovering objectobject.recover(buffer);channel.close();store.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

我们的界面为抽象的读写机制。 这也是提供抽象的接口的实际用法 ,将要做的事情与要做的事情分开。 像这个界面,只说坚持并恢复,不说你怎么做。

interface Persistable {public void persist(ByteBuffer buffer);public void recover(ByteBuffer buffer);
}

实现Persistable使其可读写的具体类:

class Tablet implements Persistable {private String brand;private boolean isCellular;private long cost; // in US Dollarspublic Tablet() {brand = "";}public Tablet(String brand, boolean isCellular, long cost) {this.brand = brand;this.isCellular = isCellular;this.cost = cost;}public final String getBrand() {return brand;}public final boolean isCellular() {return isCellular;}public final long getCost() {return cost;}public final void setBrand(String brand) {this.brand = brand;}public final void setCellular(boolean isCellular) {this.isCellular = isCellular;}public final void setCost(long cost) {this.cost = cost;}@Overridepublic void persist(ByteBuffer buffer) {byte[] strBytes = brand.getBytes();buffer.putInt(strBytes.length);buffer.put(strBytes, 0, strBytes.length);buffer.put(isCellular == true ? (byte) 1 : (byte) 0);buffer.putLong(cost);}@Overridepublic void recover(ByteBuffer buffer) {int size = buffer.getInt();byte[] rawBytes = new byte[size];buffer.get(rawBytes, 0, size);this.brand = new String(rawBytes);this.isCellular = buffer.get() == 1 ? true : false;this.cost = buffer.getLong();}@Overridepublic String toString() {return "Tablet [brand=" + brand + ", isCellular=" + isCellular + ", cost=" + cost + "]";}}Output:
Writing into RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000]
number of bytes written : 18
number of bytes read : 1024
Object read from RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000]

警告

将对象的内容写入其中之后,不要忘记翻转字节缓冲区,因为文件通道需要读取它才能将数据写入RandomAccessFile。 如果忘记在调用FileChannel.write()之前先调用flip()方法,那么最终将什么都没有写入文件中。

同样,在将数据从文件读入缓冲区后,再次翻转它,以便可以从缓冲区读数据到对象的常用内容。 许多Java程序员会犯这样的错误,即写后不会翻转,并最终导致调试时间过长,因为要么什么都没有写到文件,要么什么都看不到。

这就是如何在Java中使用FileChannel和ByteBuffer读取/写入文件的全部内容。 在本例中,我向您展示了如何使用FileChannel和ByteBuffer读写RandomAccessFile,但是您可以应用相同的技术从Java程序读取任何其他文本或二进制文件。

翻译自: https://www.javacodegeeks.com/2016/01/readingwriting-tofrom-files-using-filechannel-bytebuffer-java.html

在Java中使用FileChannel和ByteBuffer对文件进行读写相关推荐

  1. 使用Java中的FileChannel和ByteBuffer在文件中读取/写入文件

    过去,我讨论过RandomAccessFile以及如何将其用于在Java中进行更快的IO,在本Java NIO教程中,我们将了解如何通过使用FileChannel和ByteBuffer来使用读/写数据 ...

  2. java curl get_如何从Java中的curl get请求获取文件?

    我正在尝试使用API​​下载一些XBRL文件.为了做到这一点,我需要做一个卷曲的请求,就像这样:如何从Java中的curl get请求获取文件? curl -XGET http://distribut ...

  3. java如何解压rar文件怎么打开_如何在java中实现对zip和rar文件的解压

    如何在java中实现对zip和rar文件的解压 关注:101  答案:1  mip版 解决时间 2021-01-26 10:50 提问者芣①樣哋羙莮 2021-01-25 22:44 如何在java中 ...

  4. Java 中调用 Apache API 实现图片文件的 压缩 与 解压 实例

    < Java 中调用 Apache API 实现图片文件的 压缩 与 解压 > 为什么不直接使用 Java JDK 中自带的 API 呢?必须使用 Apache API 实现文件的压缩与解 ...

  5. Java中的ObjectOutputStream –将对象写入文件

    ObjectOutputStream in Java can be used to convert an object to OutputStream. The process of converti ...

  6. 转!!java中File的delete()方法删除文件失败的原因

    一般来说 java file.delete失败 有以下几个原因  1.看看是否被别的进程引用,手工删除试试(删除不了就是被别的进程占用) 2.file是文件夹 并且不为空,有别的文件夹或文件,  3. ...

  7. JAVA实现inotify一样的功能_哪些操作系统支持在Java中查看本机(类似inotify)文件

    JavaDoc for java.nio.file.WatchService状态; The implementation - is intended to map directly on to the ...

  8. java中File类应用:遍历文件夹下所有文件

    练习: 要求指定文件夹下的所有文件,包括子文件夹下的文件 代码: package 遍历文件夹所有文件;import java.io.File;public class Test {public sta ...

  9. java中io流如何创建一个文件_,Java中Io流操作-File类的常用操作-创建文件,创建文件夹...

    package com.hxzy.IOSer; import java.io.File; import java.io.IOException; public class Demo03 { publi ...

最新文章

  1. PHP如何设置圆,php绘制圆形的方法
  2. 我们人类与人工智能技术究竟是怎样的关系?
  3. Windows命令:查看端口占用状况,杀掉进程
  4. java中引导页面的,Android实现欢迎引导页面
  5. 计算机项目开发流程,产品开发项目建议流程图怎样画
  6. linux 图片编辑 java_Java在Linux下 不能处理图形的解决办法 分享
  7. 详解数据治理相关的7个术语和名词
  8. js跟php增加删除信息,浅谈JavaScript数组的添加和删除
  9. PYTHON 自动化学习之路
  10. 如何判断一个进程已经完成初始化?
  11. matlab 图像保存为视频教程,山东大学《数字图像处理(MATLAB)》江铭炎视频教程
  12. cad添加自己线性_如何自定义自己需要的CAD线型?
  13. 问卷设计与统计分析——常用的量表
  14. 庄子(公元前369年-公元前286年)
  15. R语言探索性因子分析练习
  16. 扒一扒物理层里的那些事
  17. 基于R16标准的5G电力高精度授时解决方案PTP授时方案
  18. 计算机显示pc19,19寸显示器最佳分辨率是多少 怎么设置【图文教程】
  19. 【解析】心田上的百合花开——心田花开
  20. 中国LED芯片行业市场竞争状况分析及十si五发展趋势研究报告2021~2027年

热门文章

  1. CF1594F-Ideal Farm【构造】
  2. P4151-[WC2011]最大XOR和路径【线性基】
  3. nssl1478-题【dp】
  4. P2824-[HEOI2016/TJOI2016]排序【线段树,二分】
  5. 上学要迟到了【最短路转化】
  6. 初一模拟赛总结(3.30)
  7. springmvc常用注解
  8. Java基于socket服务实现UDP协议的方法
  9. Oracle入门(十四.15)之捕获Oracle服务器异常
  10. hashCode到底有什么用?