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

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

您可以将数据写入Array的任何位置,也可以从任何位置读取。 为此,它使用保存当前位置的指针,并提供诸如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. android读取assets中的html文件,android读取assets文件.htm

    android读取assets文件 android读取assets文件 style='FONT-SIZE: 14px; FONT-FAMILY: verdana, "ms song" ...

  3. java 读取dwg_jdwglib java dwg文件的读取,写入开发包. dwg使用当前 常方便,测试代码和jar都有 CAD 247万源代码下载- www.pudn.com...

    文件名称: jdwglib下载  收藏√  [ 5  4  3  2  1 ] 所属分类: CAD 开发工具: Java 文件大小: 608 KB 上传时间: 2015-12-08 下载次数: 0 提 ...

  4. linux用户读取文件过程,Python中读取写入文件并进行文件与用户交互的操作

    一.提前知识点 在Python中是同样和其他语言一样可以进行文件的读取写入操作,值得注意的是,Python中打开文件读取的方式有几种,分别是以下几种: f = open('username.txt') ...

  5. C#中File类中文件的读取写入

    C#中File类中文件的读取写入 注意:使用File读取写入文件非常简单,但FIle的操作方式决定只能读取小文件,读写时全部加载进行读取.读写大文件时建议使用文件流. 常用方法 //获取所有编码方式 ...

  6. java中读取mp3文件_java读取mp3文件

    JMF实际上是Java的一个类包.JMF 2.1.1技术提供了先进的媒体处理能力,从而扩展了Java平台的功能.这些功能包括:媒体捕获.压缩.流转.回放,以及对各种主要媒体形式和编码的支 持,如M-J ...

  7. Java NIO 读取文件、写入文件、读取写入混合

    前言 Java NIO(new/inputstream outputstream)使用通道.缓冲来操作流,所以要深刻理解这些概念,尤其是,缓冲中的数据结构(当前位置(position).限制(limi ...

  8. java nio 追加写文件_Java NIO写入文件

    用NIO写文件,总结一下,主要有如下步骤: 1.打开通道. 2.包装到缓冲区. 3.写入文件. 4.不忘记关闭通道,关闭流.package what21.nio; import java.io.Fil ...

  9. gdal java shp_【GDAL/OGR】利用GDAL/OGR读取shp文件并转换为json文件(Java版)

    前言: 对于GIS开发者来说,GDAL/OGR是最熟悉不过的开源GIS库了,GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间 ...

最新文章

  1. linux tar压缩解压命令
  2. 为什么switch里的case没有break不行
  3. 九个工作谎言_书评:关于工作的九种谎言
  4. (转)Spring中的事务操作
  5. oracle错误01653,oracle 10g 错误 ORA 01653 的解决过程
  6. ModuleNotFoundError: No module named ‘matplotlib‘ 解决办法
  7. BZOJ3781 小B的询问
  8. selenium 浏览器驱动下载安装
  9. 安卓屏幕朗读app_android录屏app推荐?安卓手机屏幕录制方法步骤教程
  10. 用易语言对DNF卡顿进行批处理
  11. ICMAX解析运行内存发展新趋势 LPDDR4X将会给手机带来哪些改变?
  12. vue点击按钮打开下拉菜单_vue+element下拉框样式的点击按钮
  13. 项目启动时就执行某些操作、@Scheduled定时项目启动时执行一次
  14. 电气-NPN、PNP传感器应用
  15. 百度地图API申请——服务端
  16. 分析了漫威电影后,才知道竟如此流弊
  17. Mac下浏览器安装证书
  18. 澳洲留学生论文写作必备好用软件or网站
  19. doraemon的python(大更新) 实例讲解 图书管理系统的配置和应用
  20. element-plus表单验证使用 个人总结

热门文章

  1. FileInputStream
  2. 什么样的事才是有意义的
  3. Ajax基本案例详解之$.getjson的实现
  4. Ajax基本案例详解之$.get的实现
  5. React中的方法调用
  6. java 读取svg元素_svg动态添加元素
  7. 单位矩阵的逆矩阵是它本身吗_矩阵运算、单位矩阵与逆矩阵(二)
  8. thinking-in-java(21)并发2
  9. MySQL的source命令不加分号和delimiter的使用
  10. java数据库编程——执行SQL 语句