当前位置: 首页 > 科技观察

Java文件I-O的三种方法

时间:2023-03-16 18:33:21 科技观察

面试中我被问了两次,如何用Java写文件读取、输入、输出。总结了这方面的内容,想写出来分享给大家。首先,常用的文件读取输出流有3种:FileInputStream/FileOutputStream、FileReader/FileWriter、RandomAccessFile。下面是一些简单的例子供参考:基础:1.FileReadfr=newFileReader(filename);Strings;while((s=fr.readLine())!=null){...}fr.close();//FileWriter同理,可以使用write()函数进行输出//JavaI/O中所有Reader和Writers都是面向字符流输出的2.FileInputStreamfi=newFileInputStream(filename);intin;while((in=fi.read())!=-1){...}fi.close();//FileOutputStream同理//JavaI/O中所有Reader和Writers都是面向字节流的输出和输出3.RandomAccessFilera=newRandomAccessFile(filename,"rw");//后面的参数指定文件流的打开方式,"rw"表示读写,"r"表示只读,Java没有提供只写ra.seek(number);//将文件指针移动到number,这里文件指针可以理解为文件开始读取的位置ra.skipByte(number);//跳过number字节ra.read();ra.close();//RandomAccessFile可读可写,可使用seek()函数指定位置。以下是百度百科的一些介绍:RandomAccessFile不属于InputStream和OutputStream类。其实除了实现了DataInput和DataOutput接口(DataInputStream和DataOutputStream也实现了)之外,与这两个类没有任何关系,甚至没有使用InputStream和OutputStream已经准备好的函数;它是一个完全独立的类,所有方法(绝大多数只属于它自己)都是从头开始编写的。这可能是因为RandomAccessFile可以在文件中前后移动,所以它的行为与其他I/O类有些根本不同。总而言之,它是一个自包含的类,直接继承自Object。进阶篇:在nio中,Java重新实现了I/O流,并引入了一些新的方法来提高速度。我主要介绍channel和内存映射文件1.Channel:channel和buffer是一对概念。ThinkinginJava中的一个例子特别好理解:我们把要读取的文件看成煤矿,数据就是我们要的煤。通道就像输送煤矿的传送带。我们没有办法直接从传送带上取煤,只好用卡车装煤。truck是一个buffer,主要负责从channel中取出数据,传递给我们写的程序。***能与通道交互的缓冲区是ByteBuffer。可以看出,通道支持的流解析方式是字节流。所以它使用FileInputStream/FileOutputStream,RandomAccessFileExample:a.FileChannelfc=newFileOutputStream(filename).getChannel();fc.write(ByteBuffer.wrap("somethingtest".getBytes()));//这里使用ByteBuffer来比较简单,其实ByteBuffer可以用一个put()函数写入字节数组fc.close();b.fc=newFileOutputStream(filename).getChannel();ByteBufferbuff=ByteBuffer.allocate(size);//对,ByteBuffer是如果没有显式的构造函数,如果要创建一个新的对象,就必须使用allocate()函数来分配空间。fc.read(buff);fc.close();为什么会想到使用通道进行I/O?主要考虑的是性能问题。Channels和buffers可以让程序读写一定数量的字符,并且只使用InputStream/OutputStream,Reader/Writer一次只能读写一个字节/字符。程序在进行I/O时,必须交给操作系统来解决这部分功能(调用系统调用)。减少操作系统的切换次数可以有效减少I/O花费的时间。2.Memory-mappedfiles:内存映射文件主要意思其实是假设所有文件都放入内存,作为一个非常大的数组访问,效率很高。为什么更好?让我们从Java虚拟机和操作系统开始。com/content...)本文主要介绍了JavaI/O的原理和内存映射文件的原理。我尝试总结一下:实现JavaI/O的主要手段肯定是使用系统调用,系统调用首先将你要使用的文件从硬盘传输到内核的I/O缓冲区。想要的文件有更多的内容(复制更多的内容是由于程序的局部性原则,可以获得更好的效率),然后从内核的I/O缓冲区导入到Java进程自己的私有内存空间中。内存映射文件放弃了两份拷贝的方法,直接在Java进程的虚拟空间和文件对象之间形成一个映射。当在私有内存空间中找不到想要的内容时,就会出现页面错误,然后使用下层系统。调用来解决这个问题(其实在I/O系统调用中也涉及pagefault异常处理),好处是减少了一次从内核I/O缓冲区到进程私有地址的开销。示例:FileChannelfc=newRandomAccessFile(filename,"rw").getChannel();MappedByteBuffermb=fc.map(FileChannel.MapMode.READ_WRITE,start,length);mb.put((byte)'x');mb.get();fc.close();写到这里突然想到《孔乙己》中“茴香”的4种写法,而现在Java打开文件的方式至少有5种,各有优缺点。以后你也可以披着长袍问问别人你是否知道Java读写文件的5种方式