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

Java文件的简单读写、随机读写、NIO读写、使用MappedByteBuffer读写

时间:2023-03-13 04:28:20 科技观察

文件和目录的创建和删除都比较简单,所以忽略这部分内容的介绍,我们重点学习文件读写。本文包括:简单文件读写随机访问文件读写NIO文件读写-FileChannel使用MappedByteBuffer读写文件简单文件读写FileOutputStream由于流是单向的,可以使用FileOutputStream进行简单的文件写入,和FileInputStream用于读取文件。任何输出到文件的数据都是以字节为单位输出的,包括图片、音频和视频。以图片为例,如果没有图片格式解析器,那么图片文件实际上只存储了以某种格式存储的字节数据。FileOutputStream是指文件字节输出流,用于向文件输出字节数据。只支持顺序写和追加写,不支持指定位置写。打开文件输出流并写入数据的示例代码如下。publicclassFileOutputStreamStu{publicvoidtestWrite(byte[]data)throwsIOException{try(FileOutputStreamfos=newFileOutputStream("/tmp/test.file",true)){fos.write(data);fos.flush();}}}注意,如果not指定附加模式以打开流。使用newFileOutputStream时,文件内容会被清空,FileOutputStream的默认构造函数以非追加方式打开流。FileOutputStream的参数1为文件名,参数2为是否以append方式打开流,如果为true,字节将写入文件末尾而不是开头。调用flush方法的目的是在stream关闭前清空buffer数据。其实使用FileOutputStream是不需要调用flush方法的。这里的flushing是指调用系统函数write将缓存在JVM内存中的数据写入。比如BufferedOutputStream,当调用BufferedOutputStream方法时,如果缓存没有满,实际上并不会调用系统函数write,如下代码所示。publicclassBufferedOutputStreamextendsFilterOutputStream{publicsynchronizedvoidwrite(byteb[],intoff,intlen)throwsIOException{if(len>=buf.length){flushBuffer();out.write(b,off,len);return;}if(len>buf.length-count){flushBuffer();}System.arraycopy(b,off,buf,count,len);//只写入缓存count+=len;}}FileInputStreamFileInputStream指的是文件字节输入流,用于转换wordsinthefileSection数据读入内存,只支持顺序读,不允许跳读。打开文件输入流读取数据的案例代码如下。publicclassFileInputStreamStu{publicvoidtestRead()throwsIOException{try(FileInputStreamfis=newFileInputStream("/tmp/test/test.log")){byte[]buf=newbyte[1024];intrealReadLength=fis.read(buf);}}}其中buf数组中realReadLength下标为0的字节数据为实际读取的数据。如果realReadLength返回-1,表示已经读到文件末尾,没有读到数据。当然,我们也可以逐字节读取,如下代码所示。publicclassFileInputStreamStu{publicvoidtestRead()throwsIOException{try(FileInputStreamfis=newFileInputStream("/tmp/test/test.log")){intbyteData=fis.read();//返回值范围:[-1,255]if(byteData==-1){return;//已经读取到文件末尾}bytedata=(byte)byteData;//data为读取的字节数据}}}至于读取的字节数据如何使用,需要看是什么数据存储在您的文件中。如果整个文件存储一张图片,则需要读取整个文件,然后按照格式解析成一张图片。如果整个文件是一个配置文件,可以逐行读取,遇到\n换行符就是一行,代码如下。publicclassFileInputStreamStu{@TestpublicvoidtestRead()throwsIOException{try(FileInputStreamfis=newFileInputStream("/tmp/test/test.log")){ByteBufferbuffer=ByteBuffer.allocate(1024);intbyteData;while((byteData=fis.read())!=-1){if(byteData=='\n'){buffer.flip();Stringline=newString(buffer.array(),buffer.position(),buffer.limit());System.out.println(line);buffer.clear();continue;}buffer.put((byte)byteData);}}}}Java基于InputStream,OutputStream也提供了很多方便读写文件的API,比如BufferedReader,但是如果你懒得记住这些API的话,你只需要记住FileInputStream和FileOutputStream。随机访问文件读写RandomAccessFile相当于FileInputStream和FileOutputStream的结合,即可以读也可以写,RandomAccessFile支持移动到文件的指定位置开始读或写。RandomAccessFile的使用如下。publicclassRandomAccessFileStu{publicvoidtestRandomWrite(longindex,longoffset){try(RandomAccessFilerandomAccessFile=newRandomAccessFile("/tmp/test.idx","rw")){randomAccessFile.seek(index*indexLength());randomAccessFile.write(toByte(index));randomAccessFile.write(toByte(offset));}}}RandomAccessFile构造方法:参数1为文件路径,参数2为模式,'r'为读,'w'为写;seek方法:在linux和unix操作系统下接下来就是调用系统的lseek函数。RandomAccessFile的seek方法是调用native方法实现的,源码如下。JNIEXPORTvoidJNICALLJava_java_io_RandomAccessFile_seek0(JNIEnv*env,jobjectthis,jlong??pos){FDfd;fd=GET_FD(this,raf_fd);if(fd==-1){JNU_ThrowIOException(env,"StreamClosed");返回;}if(pos