NIO学习笔记(四)——利用NIO替换大文件内容
来源:互联网 发布:mac奶瓶粉底液好用吗 编辑:程序博客网 时间:2024/06/06 12:57
这一次我们着重来讨论如何用NIO来修改较大文件里的内容。如果是较小的文件,利用传统IO来进行修改并不难,思路是:
(1)使用输入流读出文件内容。
(2)读的过程中判断符合替换条件的内容。
(3)如果符合,把这些内容写入到输出流,这个输出流最后会写入文件的原始位置。
其实这个过程相当于重新写了一份文件,然后将原来的文件替换掉。然后在替换的过程中,去处理数据。
但是一旦文件较大,而且改动又很小,这种模式其实是十分浪费资源的。比如说我要把一个较大文件里的所有某种所有字符,修改为另一种字符。有没有一种方法能够边读边换呢?
我们先把整体的框架写出来:
/** * 利用NIO替换大文件内容。 */public class NIOFileContentReplace { public static void main(String[] args) { //创建channel对象 try(FileChannel channel = FileChannel.open(Paths.get("f:/test.txt"), StandardOpenOption.READ,StandardOpenOption.WRITE);) { //读取文件内容,读取buffer ByteBuffer buffer = ByteBuffer.allocate(4); int flag = channel.read(buffer); while(-1 != flag) { buffer.flip(); //替换内容 //写回文件 buffer.clear(); flag = channel.read(buffer); } } catch (IOException e) { e.printStackTrace(); } }}
这部分框架已经成为一种定式,加以练习即可掌握。
替换内容的时候,我们要做的就是把这部分内容取出来。举个例子,将文本里所有的“你”替换成“我”:
//替换内容String content = new String(buffer.array(), "GBK");String newContent = content.replace('你', '我');
替换的过程中,有可能有的语句中没有“你”字。那么我们做一个判断,判断的依据是,遍历buffer,有“你”字我们才执行内容替换。
buffer.flip();CharBuffer charBuffer = Charset.forName("GBK").decode(buffer);while(charBuffer.hasRemaining()) { if('你' == charBuffer.get()) { //替换内容 String content = new String(buffer.array(), "GBK"); String newContent = content.replace('你', '我'); //写回文件 }}buffer.clear();flag = channel.read(buffer);
接着进行写回文件,写回文件它需要依赖channel.write方法,write需要一个buffer。我们将这个newContent声明成一个数组,构建一个ByteBuffer:
//写回文件 channel.write(ByteBuffer.wrap(newContent.getBytes()));
那么是不是这样写就可以了呢?经过测试,显然,并不是我们所希望的结果。它找出了这些“你”字,但是在替换的过程中出现了错位。之所以会出现这种情况,是因为读和写共用的都是一个channel。channel和buffer一样,都有position这个属性。这让channel具有了回头读的功能,传统IO则不具备这项功能,而恰恰这个功能,使得刚才没有得到正确的替换。channel在read的时候,position已经偏移了,而就着这个偏移值,导致出现错误。所以我们在查找到了指定字符之后,应该调整偏移量:
//重置channel的position,由于channel.read会影响这个值channel.position(channel.position() - buffer.limit());
这样一来我们就可以利用NIO而且高效地得到正确的替换结果,全文代码如下:
import java.io.IOException;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.FileChannel;import java.nio.charset.Charset;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;/** * 利用NIO替换大文件内容。 * @author 青葉 * */public class NIOFileContentReplace { public static void main(String[] args) { //创建channel对象 try(FileChannel channel = FileChannel.open(Paths.get("f:/test.txt"), StandardOpenOption.READ,StandardOpenOption.WRITE);) { //读取文件内容,读取buffer ByteBuffer buffer = ByteBuffer.allocate(4); int flag = channel.read(buffer); while(-1 != flag) { buffer.flip(); CharBuffer charBuffer = Charset.forName("GBK").decode(buffer); while(charBuffer.hasRemaining()) { if('你' == charBuffer.get()) { //替换内容 String content = new String(buffer.array(), "GBK"); String newContent = content.replace('你', '我'); //重置channel的position,由于channel.read会影响这个值 channel.position(channel.position() - buffer.limit()); //写回文件 channel.write(ByteBuffer.wrap(newContent.getBytes())); } } buffer.clear(); flag = channel.read(buffer); } } catch (IOException e) { e.printStackTrace(); } }}
- NIO学习笔记(四)——利用NIO替换大文件内容
- NIO学习笔记(二)——NIO文件读取
- NIO学习笔记(三)——NIO复制文件
- NIO学习笔记四
- Java nio 学习笔记(四)
- Java NIO 学习(四)
- NIO学习笔记(一)——NIO的特点介绍
- 《Java NIO》学习笔记四 选择器(Selector)
- 学习笔记——NIO使用
- NIO学习笔记——选择器(selectors)
- IO、文件、NIO【四】
- NIO 读大文件
- NIO学习笔记——缓冲区(Buffer)详解
- NIO学习笔记——通道(channel)详解
- java nio学习(四)
- java nio学习(四)
- NIO利用磁盘映射 实现的文件内容查找
- NIO学习笔记(2)--NIO核心类(Selector)
- #9 自定义序列化器
- CodeForces
- PHP采用curl多线程抓取网页功能实现
- Tools_GetVtReport
- Java开发环境搭建(进阶配置二 ——Tomcat)
- NIO学习笔记(四)——利用NIO替换大文件内容
- react native 的坑
- Python-爬取音悦台MV列表以及反爬虫方法
- MapReduce的架构组成
- Angular4 绑定html内容 警告处理
- 也算是第一次开通博客
- 地宫取宝 (dfs+dp深搜)
- UVA1640TheCountingProblem
- 练习1-2 做个实验,当printf函数的参数字符串中包含\c(其中c是上面的转义字符未曾列出的某一个字符)时,观察一下输出