- 浏览: 2183276 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (682)
- 软件思想 (7)
- Lucene(修真篇) (17)
- Lucene(仙界篇) (20)
- Lucene(神界篇) (11)
- Solr (48)
- Hadoop (77)
- Spark (38)
- Hbase (26)
- Hive (19)
- Pig (25)
- ELK (64)
- Zookeeper (12)
- JAVA (119)
- Linux (59)
- 多线程 (8)
- Nutch (5)
- JAVA EE (21)
- Oracle (7)
- Python (32)
- Xml (5)
- Gson (1)
- Cygwin (1)
- JavaScript (4)
- MySQL (9)
- Lucene/Solr(转) (5)
- 缓存 (2)
- Github/Git (1)
- 开源爬虫 (1)
- Hadoop运维 (7)
- shell命令 (9)
- 生活感悟 (42)
- shell编程 (23)
- Scala (11)
- MongoDB (3)
- docker (2)
- Nodejs (3)
- Neo4j (5)
- storm (3)
- opencv (1)
最新评论
-
qindongliang1922:
粟谷_sugu 写道不太理解“分词字段存储docvalue是没 ...
浅谈Lucene中的DocValues -
粟谷_sugu:
不太理解“分词字段存储docvalue是没有意义的”,这句话, ...
浅谈Lucene中的DocValues -
yin_bp:
高性能elasticsearch ORM开发库使用文档http ...
为什么说Elasticsearch搜索是近实时的? -
hackWang:
请问博主,有用solr做电商的搜索项目?
Solr中Group和Facet的用法 -
章司nana:
遇到的问题同楼上 为什么会返回null
Lucene4.3开发之第八步之渡劫初期(八)
现有如下的一个需求,向已存在1G数据的txt文本里末尾追加一行文字,内容如下“Lucene是一款非常优秀的全文检索库”。可能大多数朋友会觉得这个需求很easy,说实话,确实easy,然后XXX君开始实现了,直接使用Java中的流读取了txt文本里原来所有的数据转成字符串后,然后拼接了“Lucene是一款非常优秀的全文检索库”,又写回文本里了,至此,大功告成。后来需求改了,向5G数据的txt文本里追加了,结果XXX君傻了,他内存只有4G,如果强制读取所有的数据并追加,会报内存溢出的异常。
其实上面的需求很简单,如果我们使用JAVA IO体系中的RandomAccessFile类来完成的话,可以实现零内存追加。其实这就是支持任意位置读写类的强大之处。
在这之前,散仙还是喜欢先啰嗦的介绍下RandomAccessFile这个类,RandomAccessFile是Java中输入,输出流体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。
如果我们只希望访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将会带来更简洁的代码以及更好的性能。
下面来看下RandomAccessFile类中比较重要的2个方法,其他的和普通IO类似,在这里,就不详细说明了。
下面散仙给出示例,分析下怎么使用RandomAccessFile
首先,我们先看下散仙要操作的文本文件的内容截图。
功能one,读取任意位置的数据,代码如下
测试代码
运行效果:
功能two,追加数据,代码如下
测试代码
运行效果:
功能three,任意位置插入数据,代码如下
测试代码
运行效果:
至此,RandomAccessFile类的几个功能,散仙在代码中已给出实现了,现在回到本文开始前的提的那个需求,用RandomAccessFile类就可以轻而易举的完成了,另外需要注意的是,向指定位置插入数据,是散仙自己改造的功能,RandomAccessFile并不直接支持,需要新建一个缓冲区临时空间,存数据,然后在写,因为一旦数据量上了级别,在任意位置插入数据,是很耗内存的,这个也就是为什么hadoop的HDFS文件系统,只支持append的方式,而没有提供修改的操作。
另外我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。
其实上面的需求很简单,如果我们使用JAVA IO体系中的RandomAccessFile类来完成的话,可以实现零内存追加。其实这就是支持任意位置读写类的强大之处。
在这之前,散仙还是喜欢先啰嗦的介绍下RandomAccessFile这个类,RandomAccessFile是Java中输入,输出流体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。
如果我们只希望访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将会带来更简洁的代码以及更好的性能。
下面来看下RandomAccessFile类中比较重要的2个方法,其他的和普通IO类似,在这里,就不详细说明了。
方法名 | 作用 |
getFilePointer() | 返回文件记录指针的当前位置 |
seek(long pos) | 将文件记录指针定位到pos的位置 |
下面散仙给出示例,分析下怎么使用RandomAccessFile
首先,我们先看下散仙要操作的文本文件的内容截图。
功能one,读取任意位置的数据,代码如下
/** * 读的方法 * @param path 文件路径 * @param pointe 指针位置 * **/ public static void randomRed(String path,int pointe){ try{ //RandomAccessFile raf=new RandomAccessFile(new File("D:\\3\\test.txt"), "r"); /** * model各个参数详解 * r 代表以只读方式打开指定文件 * rw 以读写方式打开指定文件 * rws 读写方式打开,并对内容或元数据都同步写入底层存储设备 * rwd 读写方式打开,对文件内容的更新同步更新至底层存储设备 * * **/ RandomAccessFile raf=new RandomAccessFile(path, "r"); //获取RandomAccessFile对象文件指针的位置,初始位置是0 System.out.println("RandomAccessFile文件指针的初始位置:"+raf.getFilePointer()); raf.seek(pointe);//移动文件指针位置 byte[] buff=new byte[1024]; //用于保存实际读取的字节数 int hasRead=0; //循环读取 while((hasRead=raf.read(buff))>0){ //打印读取的内容,并将字节转为字符串输入 System.out.println(new String(buff,0,hasRead)); } }catch(Exception e){ e.printStackTrace(); } }
测试代码
public static void main(String[] args) { String path="D:\\3\\test.txt"; int seekPointer=20; randomRed(path,seekPointer);//读取的方法 //randomWrite(path);//追加写的方法 //insert(path, 33, "\nlucene是一个优秀的全文检索库"); }
运行效果:
RandomAccessFile文件指针的初始位置:0 is a teacher hadoop is perfect
功能two,追加数据,代码如下
/** * 追加方式 * 写的方法 * @param path 文件路径 * ***/ public static void randomWrite(String path){ try{ /**以读写的方式建立一个RandomAccessFile对象**/ RandomAccessFile raf=new RandomAccessFile(path, "rw"); //将记录指针移动到文件最后 raf.seek(raf.length()); raf.write("我是追加的 \r\n".getBytes()); }catch(Exception e){ e.printStackTrace(); } }
测试代码
public static void main(String[] args) { String path="D:\\3\\test.txt"; //int seekPointer=20; // randomRed(path,seekPointer);//读取的方法 randomWrite(path);//追加写的方法 //insert(path, 33, "\nlucene是一个优秀的全文检索库"); }
运行效果:
功能three,任意位置插入数据,代码如下
/** * 实现向指定位置 * 插入数据 * @param fileName 文件名 * @param points 指针位置 * @param insertContent 插入内容 * **/ public static void insert(String fileName,long points,String insertContent){ try{ File tmp=File.createTempFile("tmp", null); tmp.deleteOnExit();//在JVM退出时删除 RandomAccessFile raf=new RandomAccessFile(fileName, "rw"); //创建一个临时文件夹来保存插入点后的数据 FileOutputStream tmpOut=new FileOutputStream(tmp); FileInputStream tmpIn=new FileInputStream(tmp); raf.seek(points); /**将插入点后的内容读入临时文件夹**/ byte [] buff=new byte[1024]; //用于保存临时读取的字节数 int hasRead=0; //循环读取插入点后的内容 while((hasRead=raf.read(buff))>0){ // 将读取的数据写入临时文件中 tmpOut.write(buff, 0, hasRead); } //插入需要指定添加的数据 raf.seek(points);//返回原来的插入处 //追加需要追加的内容 raf.write(insertContent.getBytes()); //最后追加临时文件中的内容 while((hasRead=tmpIn.read(buff))>0){ raf.write(buff,0,hasRead); } }catch(Exception e){ e.printStackTrace(); } }
测试代码
public static void main(String[] args) { String path="D:\\3\\test.txt"; //int seekPointer=20; // randomRed(path,seekPointer);//读取的方法 // randomWrite(path);//追加写的方法 insert(path, 33, "\nlucene是一个优秀的全文检索库"); }
运行效果:
至此,RandomAccessFile类的几个功能,散仙在代码中已给出实现了,现在回到本文开始前的提的那个需求,用RandomAccessFile类就可以轻而易举的完成了,另外需要注意的是,向指定位置插入数据,是散仙自己改造的功能,RandomAccessFile并不直接支持,需要新建一个缓冲区临时空间,存数据,然后在写,因为一旦数据量上了级别,在任意位置插入数据,是很耗内存的,这个也就是为什么hadoop的HDFS文件系统,只支持append的方式,而没有提供修改的操作。
另外我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。
发表评论
-
记一次log4j不打印日志的踩坑记
2019-09-22 01:58 1563### 起因 前几天一个跑有java应用的生产集群(200多 ... -
在Java里面如何解决进退两难的jar包冲突问题?
2019-07-23 19:10 1229如上图所示: es api组件依赖guava18.0 ... -
如何轻松理解二叉树的深度遍历策略
2019-07-03 23:33 1122我们知道普通的线性数据结构如链表,数组等,遍历方式单一 ... -
为什么单线程Redis性能也很出色
2019-01-21 18:02 2204高性能的服务器,不一 ... -
如何将编程语言里面的字符串转成数字?
2019-01-11 23:23 2089将字符串转成数字在很 ... -
为什么Java里面String类是不可变的
2019-01-06 18:36 1665在Java里面String类型是不可变对象,这一点毫无疑问,那 ... -
关于Java里面volatile关键字的重排序
2019-01-04 18:49 1064Java里面volatile关键字主 ... -
多个线程如何轮流打印ABC特定的次数?
2018-12-11 20:42 6038之前的一篇文章,我给 ... -
聊聊Java里面的引用传递
2018-11-16 21:21 988长久以来,在Java语言里面一直有一个争论,就是Java语言到 ... -
理解计数排序算法的原理和实现
2018-10-11 10:03 2089计数排序(Counting sort) ... -
理解Java7和8里面HashMap+ConcurrentHashMap的扩容策略
2018-09-06 11:31 3387### 前言 理解HashMap和Con ... -
关于Java里面多线程同步的一些知识
2018-07-18 09:45 1105# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
Java单例模式之双检锁深入思考
2018-07-08 12:25 3288# Java单例模式之双检锁 ... -
关于Java里面多线程同步的一些知识
2018-07-08 12:23 1120# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
重新认识同步与异步,阻塞和非阻塞的概念
2018-07-06 14:30 1471# 重新认识同步与异步 ... -
线程的基本知识总结
2018-06-27 16:27 1059### (一)创建线程的方式 (1)实现Runnable接口 ... -
Java里面volatile关键字修饰引用变量的陷阱
2018-06-25 11:42 1385# Java里面volatile关键字修饰引用变量的陷阱 如 ... -
关于Java里面的字符串拼接,你了解多少?
2018-06-25 11:28 1367# 关于Java里面的字符串 ... -
深入理解Java内存模型的语义
2018-06-25 11:39 737### 前言 Java内存模型( ... -
如何证明Java多线程中的成员变量数据是互不可见的
2018-06-21 10:09 1499前面的几篇文章主要介绍了Java的内存模型,进程和线程的定义, ...
相关推荐
首先,Java IO体系基于流(Stream)的概念,流是数据的序列,可以是从输入源读取或向输出目标写入。Java IO提供了多种流类型,包括字节流和字符流。字节流处理单个字节的数据,如InputStream和OutputStream家族;字符...
1. InputStream与OutputStream:这是Java IO体系中的两大基本接口,分别用于数据的读取和写入。InputStream代表字节输入流,OutputStream代表字节输出流。它们是所有字节流类的基类,包括文件读写的相关类。 二、...
Java IO体系主要由流(Stream)组成,分为字节流和字符流两大类,分别处理字节数据和字符数据。字节流包括InputStream和OutputStream家族,字符流则包括Reader和Writer家族。这些基类都有许多子类,如...
本文将通过分析一张清晰明了的Java IO类层次图,详细介绍Java IO体系中的主要类及其关系。 #### 二、Java IO 类层次结构详解 ##### 2.1 字节流类层次结构 Java IO中的字节流类主要分为两大类:`InputStream`和`...
Java IO体系主要包括字节流(Byte Stream)和字符流(Character Stream),以及缓冲流(Buffered Stream)、转换流(Convert Stream)、对象流(Object Stream)等。其中,字节流处理单字节的数据,如InputStream和...
Java的IO系统是Java编程中的核心部分,它允许程序与外部世界进行数据交换,包括读取文件、写入文件、网络通信以及设备交互等。理解并掌握Java的IO系统对于任何Java开发者,尤其是新手,都是至关重要的。在这个实例...
Java IO框架体系结构中,流被组织成一个层次结构,包括许多子类,如`FileInputStream`、`FileOutputStream`、`FileReader`、`FileWriter`等,这些类实现了特定的I/O功能。同时,`FilterInputStream`和`...
### Java语言编程-IO体系知识点概述 #### 一、引言 Java的IO体系是Java编程中的重要组成部分,它提供了丰富的API用于实现文件操作、网络通信等功能。本篇将详细介绍Java IO体系的基础概念、核心类及接口,并通过...
### Java IO流详解 #### 一、概述 Java的I/O操作主要涉及使用Java语言进行输入和输出操作。Java的所有I/O机制都是基于数据流来进行输入输出,这些数据流表示了字符或字节数据的流动序列。理解Java的I/O模型对于...
本部分文档介绍的主要是Java编程语言中的输入输出(IO)操作,尤其是Java的文件处理技术。...此外,文档中还涉及了异常处理和跨平台文件路径表示等高级话题,为深入理解Java IO体系提供了良好的基础。
总结,Java中的IO流体系庞大且功能强大,理解并熟练掌握IO流的使用对于Java开发者至关重要,无论是进行文件操作、网络通信还是数据存储,都能发挥关键作用。通过学习不同类型的流以及它们的应用场景,开发者可以更加...
在本文中,我们将深入探讨Java IO体系结构,关键概念以及常见用途。 Java IO系统的核心是流(Stream),流可以被视为数据的双向通道,既可以用来从源头获取数据,也可以将数据发送到目的地。Java IO分为字符流和...
### Java基础——IO流及File、RandomAccessFile对象 #### IO流概述 在Java中,IO流主要用于处理设备上的数据,这里的“流”可以被理解为数据的流动过程,即数据从一个地方移动到另一个地方的过程。Java中的IO流通过...
在实际编程中,理解并熟练掌握Java IO体系,能够有效地处理数据输入输出,构建更高效、更稳定的程序。对于初学者来说,多练习、多上机操作是掌握这些知识的关键。通过不断地实践和探索,可以更好地理解和运用Java IO...
Java的IO体系自Java 1.0以来就一直存在,并且随着时间的发展不断演进和完善。其中,NIO(New IO)是Java 1.4版本引入的一种新的IO处理方式,相较于传统的阻塞IO,NIO提供了更高的效率和灵活性。 #### 二、传统IO与...
总之,Java的IO流是其强大的功能之一,提供了丰富的类和接口来满足各种输入输出需求。理解并熟练掌握IO流,对于Java开发人员来说至关重要,无论是在处理文件操作、网络通信还是数据存储方面,都能发挥出巨大的作用。
### 李兴华Java IO笔记知识点详述 #### 流和基础知识 ...通过以上详细解析,我们可以看到Java的IO体系结构非常丰富,涵盖了从基本字节流到高级数据流的各种操作,满足了从文件读写到网络通信的广泛需求。
Java的IO体系主要由流(Stream)、缓冲区(Buffer)和转换(Converter)组成。流是数据传输的通道,分为字节流和字符流两大类。字节流处理单个字节的数据,如InputStream和OutputStream;字符流处理Unicode字符,如...
Java IO体系主要通过一系列抽象类和接口构建而成,形成了丰富的类层次结构。这种结构不仅方便了程序员理解和使用,也极大地扩展了Java语言处理文件的能力。Java IO体系主要包括两个方面:字节流和字符流。字节流主要...