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

过去,我讨论过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中读取和写入文件的第二快的方法。

ByteBuffer FileChannel 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符,字符串,int之间互相转换

字符转换成字符串:String str String.valueOf(ch); 字符转换成int: int a ch; 字符串转换成字符:char ch str.charAt(0); 字符串转换成Int:只包含数字的字符串可以通过Integer.parseInt(str)转换为int,但是包含字母…

mysql 导入百万级数据 几种 java_Java 修行第034天--执行计划及其使用--Oracle数据导入导出--第三章MySQL使用...

执行计划中牢记几句话:-- 尽量避免是*代替所有列,编写查询语句时使用具体列名代替*,可以防止全表扫描-- 尽可能少的使用like关键字进行模糊查询-- 建立适当的索引可以提高查询效率十三. 执行计划--通过PL/SQL Developer查看查询的1 执行计划是一条查询语句在Oracle中的执行过程…

10g添加用户 oracle_oracle 10g中如何创建用户

登录身份 说明sys/change_on_install SYSDBA或SYSOPER 不能以NORMAL登录,可作为默认的系统管理员system/manager SYSDBA或NORMAL 不能以SYSOPER登录,可作为默认的系统管理员sysman/oem_temp sysman 为oms的用户名scott/tiger NORMAL 普通用户aqadm /aqad…

摄像头分辨率怎么调整_亿联CAM50 - 智能话机专属高清摄像头

亿联CAM50是通过USB连接的高清视频摄像机,适用于亿联桌面高端智能话机(SIP-T58V和SIP-T58A),致力于提供一流的个人视频通信体验,优化视频协作。CAM50高清摄像机即插即用,无需额外安装驱动软件,也…

C orm mysql_Simple MySQL-C ORM

当你需要在纯C语言的应用程序中访问 MySQL 表中的数据时,是非常繁琐的事情,而该框架可以帮你大量的简化编码的工作,该框架采用 Python 开发,适用于 C 语言程序。示例代码:#include #include #include #include int mai…

jdbc:log4jdbc_使用Log4jdbc记录JDBC操作

jdbc:log4jdbc当我们开发任何应用程序,完成它或结束其任何模块时,我们都会开始优化过程。 大多数应用程序都包含数据库访问权限,如果您使用的是ORM ,则可能会使用hibernate 。 优化Hibernate持久层,要求准备阅读&#…

Mac 编译安装 Redis-3.2.3

Redis官方下载地址:http://redis.io/download Redis安装 cd /usr/local/src/redis-3.2.3 sudo make sudo make installcp ./src/redis-benchmark /usr/local/redis/redis-3.2 cp ./src/redis-check-aof /usr/local/redis/redis-3.2 cp ./src/redis-check-rdb /usr/l…

linux c mysql教程_linux下c操作mysql之增删改查

书接上文,继续进行linux 下c操作mysql。1.创建表/插入数据mysql> desc children-> ;----------------------------------------------------------| Field | Type| Null | Key | Default | Extra |----------------------------------------------------------| childno …

ios系统python编译器_MacBook如何安装Python编译器-百度经验

编程是一门需要动手实践的技能,由于Python的性能,许多人都将其作为学习编程的入门语言。而要想学好Python,首先要在电脑上安装Python,并安装一个可以解释Python的文本编辑器。在此以在MacBook上安装Sublime Text为例。 工具/原料 …

jvm需要多长时间进行转义分析? 可能比您想象的要长。

这篇文章着眼于转义分析,特别是jvm在运行的程序中执行转义分析需要多长时间。 我做了一些观察,但目前还没有全部解释。 作为介绍,让我们绕道看看jvm -Xcomp中一个鲜为人知且使用更少的标志(这将是一件好事)。 该标志…

Java补漏(一)

第一章前言 在学长的建议下,为了弥补之前学Java漏下的或者不是非常清楚的知识点,买了本蛮好的教科书-《Java学习笔记(JDK6)》,正式又一次学习。为了记下一些让我恍然大悟的知识。写了本文档。…

子集和问题 算法_子集问题 主要是去重算法

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。示例:输入: [1,2,2]输出:[[2],[1],[1,2,2],[2,2],[1,2],[]]

mysql存储引擎使用教程_mysql教程:如何写MySQL存储引擎

在MySQL 5.1中开发一个存储引擎已经是比较方便了。所谓存储引擎实际上是按照MySQL的约定,提供某些接口的实现而已,如MySQL插入一条记录时将调用write_row方法,通过索引检索时将调用index_read和index_next方法等。MySQL与存储引擎之间的接口主…

express中connect-flash中间件的使用

在学习node的时候,flash是困扰我最久的一个中间件,之前一直都没有很好的理解,这里做一个总结。 参考自:http://yunkus.com/connect-flash-usage/ 什么是flash? The flash is a special area of the session used for s…

spring environment_程序员:Spring项目中简单几步实现多个动态数据源切换

每一个请求与其他的用户是面对不同的数据库,这就需要用到动态数据源切换,来满足不同数据库、不同数据表(不同数据源)的灵活调用。动态数据源切换满足mysql、oracle等主流数据库进行动态数据源切换。使用方法在 WEB-INF 目录下建立 lib 目录,并…

算法笔记_163:算法提高 最大乘积(Java)

目录 1 问题描述 2 解决方案 1 问题描述 问题描述对于n个数&#xff0c;从中取出m个数&#xff0c;如何取使得这m个数的乘积最大呢&#xff1f;输入格式第一行一个数表示数据组数每组输入数据共2行&#xff1a;第1行给出总共的数字的个数n和要取的数的个数m&#xff0c;1<n&…

ServletRequest startAsync()的用途有限

前段时间我遇到了Servlet 3.0中AsyncContext.start&#xff08;…&#xff09;的目的是什么&#xff1f; 题。 引用上述方法的Javadoc &#xff1a; 使容器调度线程&#xff08;可能从托管线程池中&#xff09;运行指定的Runnable 。 提醒大家&#xff0c; AsyncContext是Servl…

python3.7下载tensorflow_【AI初体验】在anaconda中python3.7版本安装Tensorflow 与 Keras来玩玩...

哈啰&#xff0c;大家好&#xff0c; 单纯分享自己摸索学习AI的过程&#xff0c; 在自己的文章【Python 超入门】(1) 心原一马从零开始带你学程序中&#xff0c; 记录了安装撰写python的工具-anaconda 的方法&#xff0c; 当时安装的版本是python3.7版&#xff0c; 但是据说目前…

com/mysql/jdbc/sqlerror_com.mysql.jdbc.sqlerror

at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)在MYSQL中的BLOB字段中插入图片&#xff0c;提示出错&#xff01;&#xff01;&#xff01;加载MYSQL驱动成功com.mysql.jdbc.JDBC4Connection1479febc:\Users\hjx\Desktop\pic.jpgfile:8202com/search?q38…

Cocos2d-x3.1FileUtilsTest使用

Cocos2d-x3.1中FileUtils的使用&#xff1a;本使用教程是基于HelloWorld的。仅仅需在HelloWorld的init()函数中加入例如以下代码 //头文件 #include "platform/CCFileUtils.h"//FileUtils头文件 #include <stdio.h>//使用文件操作 #include "deprecated/C…