Java笔记之文件

本笔记来自 计算机程序的思维逻辑 系列文章

字节流

InputStream

  • int read()

    从流中读取下一个字节,返回类型为int,但取值在 0255 之间

    当读到流结尾的时候,返回值为 -1 ,如果流中没有数据,该方法会阻塞直到数据到来、流关闭或异常出现

    异常出现时,该方法抛出异常,类型为IOException,是受检异常,调用者必须进行处理

  • int read(byte b[])

    一次读取多个字节,读入的字节放入参数数组中,第一个字节存入b[0],第二个字节存入b[1],依此类推

    一次最多读入的字节个数为数组的长度,但实际读入的个数可能小于数组长度,返回值为实际读入的字节个数

    当读到流结尾时,返回值同样为 -1 ,如果流中没有数据,同样会阻塞,异常时抛出IOException

  • long skip(long n) 跳过多少字节,返回实际跳过的字节数

  • int available() 返回下一次不需要阻塞就能读取到的字节数,默认为 0

    一般用于网络读取,有足够数据量才开始读取

  • boolean markSupported() 判断是否支持 markreset方法

  • void mark(int readlimit) 设置标记,并设置最多能够读取的字节数

  • void reset() 重置,回到标记的起始位置

markSupported mark reset 这3个方法用于支持从读过的流中重复读取;先用mark方法将当前位置标记下来,读取了一些字节后,希望重新从标记处读取时,调用reset方法

OutputStream

  • void write(int b) 向流中写入一个字节
  • void write(byte b[]) void write(byte b[], int off, int len) 向流中写入一个字节数组
  • void flush() 将缓冲而未实际写的数据进行实际写入

FileInputStream

用于读取文件字节流

FileOutputStream

  • FileOutputStream(String name, boolean append) FileOutputStream(File file, boolean append)

    append 指定追加还是覆盖

ByteArrayInputStream

  • 将字节数组包装成输入流
  • 支持markreset重复读取

ByteArrayOutputStream

  • void writeTo(OutputStream out) 将内容写到另一个输出流中
  • byte[] toByteArray() 以字节数组输出
  • String toString() String toString(String charsetName) 以字符串输出
  • int size() 返回当前写入的字节个数
  • void reset() 重置当前写入字节个数为 0 ,字节数组可重用

BufferedInputStream

  • 常用于包装FileInputStream
  • 缓冲区大小为 8192
  • 支持markreset重复读取

BufferedOutputStream

  • 常用于包装FileOutputStream
  • 缓冲区大小为 8192

字符流

Reader Writer

字符流基类,抽象类

InputStreamReader OutputStreamWriter

将字节流转换为字符流,适配器类

FileReader FileWriter

输入输出为文件的字符流

CharArrayReader CharArrayWriter

输入输出为字符数组的字符流

StringReader StringWriter

输入输出为字符串的字符流

BufferedReader BufferedWriter

  • 提供缓冲区,默认大小为 8192 ,默认行长度为 80
  • 提供按行读取功能
  • 装饰类

PrintWriter

将基本类型和对象转换为其字符串形式输出

Scanner

可以读取基本类型的字符串形式

小结

  • 写文件时,可以优先考虑PrintWriter,因为它使用方便,支持自动缓冲、支持指定编码类型、支持类型转换等
  • 读文件时,如果需要指定编码类型,需要使用InputStreamReader,不需要,可使用FileReader,但都应该考虑在外面包上缓冲类BufferedReader

文件和目录

File类的操作

文件元数据、文件操作和目录操作

File

  • 可以表示文件,也可以表示目录
  • 通过new创建File对象,不会实际创建一个对象,只是创建一个表示文件或目录的对象,new之后,File对象中的路径是不可变的

文件元数据

  • String getName() 返回文件或目录名称
  • String getParent() 返回父目录路径
  • File getParentFile() 返回父目录的File对象
  • String getPath() 返回构造File对象时的完整路径,包括路径和文件名
  • boolean isAbsolute() 判断File中路径是否绝对路径
  • String getAbsolutePath() 返回完整的绝对路径
  • File getAbsoluteFile() 返回完整绝对路径的File对象
  • String getCanonicalPath() 返回标准的完整路径,不含. ..
  • boolean exists() 判断文件或目录是否存在
  • boolean isDirectory() 判断是否为目录
  • boolean isFile() 判断是否为文件
  • long length() 返回文件大小,字节数;目录没有该属性
  • long lastModified() 返回文件最后修改时间,从纪元时开始的毫秒数
  • boolean isHidden() 判断是否为隐藏文件
  • boolean canRead() 判断文件是否可读
  • boolean canWrite() 判断文件是否可写
  • separator separatorChar 文件路径分隔符,如:/\
  • pathSeparator pathSeparatorChar 多个文件路径的分隔符,如::;

当构建File对象时是相对路径,则可能获取不到parentparentFile,需使用getAbsoluteFilegetCanonicalFile获取绝对路径的File对象,再获取父对象

文件操作

  • boolean createNewFile() 创建实际文件,文件内容为空;如果文件已存在则不会创建
  • boolean delete() 删除文件或目录;如果File是目录且不为空,则删除不成功,要删除目录,必须先删除所有子目录和文件
  • void deleteOnExit()File加入待删列表,在JVM正常退出时进行实际删除
  • boolean renameTo(File dest) 重命名文件
  • boolean canExecute() 判断文件是否可执行
  • boolean setReadOnly() 设置文件为只读文件

目录操作

  • boolean mkdir() 创建目录
  • boolean mkdirs() 创建目录及必需的中间目录
  • String[] list()返回一个目录下的直接子目录和文件的文件名数组
  • File[] listFiles() 返回一个目录下的直接子目录和文件的File对象数组
  • String[] list(FilenameFilter filter) 筛选

随机读写文件

构造方法

RandomAccessFile(String name, String mode) RandomAccessFile(File file, String mode)

mode 打开模式

  • r 只读
  • rw 读写
  • rwd 读写,要求文件内容的任何更新都同步到设备上
  • rws 读写,要求文件内容和元数据的任何更新都同步到设备上

其它方法

  • void readFully(byte b[]) 可以确保读够期望的长度,如果到了文件结尾也没读够,会抛出EOFException
  • long getFilePointer() 获取当前文件指针,该指针指向当前读写的位置,读写操作会自动更新该指针
  • void seek(long pos) 更新当前文件指针
  • int skipBytes(int n) 跳过 n 个字节,通过更改文件指针实现
  • long length() 返回文件大小,字节数
  • void setLength(long newLength) 当前文件长度较小则扩展;大则多出的部分会被截取,长度变成 newLength

实际应用

键值数据库

  • 提供类似于Map的接口,可以按键保存、查找、删除,但数据可以持久化保存到文件
  • 只把元数据(如索引信息)保存在内存,值的数据保存在文件,内存消耗大大降低

内存映射文件

概念

  • 将文件映射到内存,文件对应于内存中的一个字节数组,对文件的操作变为对这个字节数组的操作,而字节数组的操作直接映射到文件上
  • 映射可以是映射文件全部区域,也可以是只映射一部分区域
  • 文件不会马上加载到内存,而是当发生读写时,才会按需加载
  • 按需加载的方式,方便处理大文件
  • 比普通的读写效率更高,只有一次拷贝,且内存分配在操作系统内核

用法

  • FileChannel getChannel() 获取FileChannel对象,由FileInputStreamFileOutputStreamRandomAccessFile类持有该方法

  • MappedByteBuffer map(MapMode mode, long position, long size)

    mode 映射模式

    READ_ONLY 只读

    READ_WRITE 读写

    PRIVATE 私有,更改不映射到文件,也不被其它程序看到

映射完成后,文件就可以关闭,后续对文件的读写可以通过MappedByteBuffer

MappedByteBuffer

  • int position() 获取当前读写位置
  • Buffer position(int newPosition) 修改当前读写位置
  • byte get() 从当前位置获取一个字节
  • ByteBuffer get(byte[] dst) 从当前位置拷贝dst.length长度的字节到dst
  • ByteBuffer put(byte[] src) 将字节数组src写入当前位置

实际应用

消息队列

  • 持久化保存在文件中,重启程序消息不会丢失
  • 可以供不同的程序进行协作,比如:两个不同的程序,一个生产者,一个消费者,生产者只将消息放入队列,消费者只从队列取消息

序列化

Serializable

  • 标记接口,没有定义任何方法
  • 实现该接口,即可使用ObjectInputStreamObjectOutputStream进行读写对象

复杂对象的序列化

  • 如果不同对象引用了同一对象,序列化后该对象只保存一份,反序列化后,仍指向同一对象
  • 如果不同对象互相引用,反序列化后仍保持原来的引用关系

定制序列化

  • 类中将字段声明为transient,默认序列化机制将忽略该字段,不会进行保存和恢复
  • 实现writeObject方法,以自定义该类对象的序列化过程
    • 声明为private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
    • s.defaultWriteObject(); 调用默认的序列化机制,默认机制会保存所有没声明为transient的字段,即使类中所有字段都是transient,也应该写这行,因为Java的序列化机制不仅会保存纯粹的数据信息,还会保存一些元数据描述等隐藏信息
  • 实现readObject方法,以自定义该类对象的反序列化过程
    • 声明为private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException
    • s.defaultReadObject();调用默认的反序列化机制,必需

用途

  • 对象持久化
  • 跨网络的数据交换,远程过程调用

局限

  • 不能实现跨语言的数据交换
  • 保存了很多描述信息,格式比较大
  • 使用反射遍历对象,性能比较低
  • 二进制格式,不方便查看和修改

JSON/XML/MessagePack

目前市场上通用的数据格式有 JSONXML ,容易阅读和理解

MessagePack 是一种二进制形式的JSON,编码更为精简高效

工具库

  • JSONgson fastjson
  • XMLSAX DOM Poll
  • MessagePackJackson

常见文件处理

属性文件

使用Properties类处理此类文件

优点
  • 自动处理空格
  • 自动忽略空行
  • 可以添加注释,以字符#!开头的行会被视为注释而忽略
限制
  • 不能直接处理中文,在配置文件中,所有非 ASCII 字符都需要使用 Unicode 编码
  • 可以使用 JDKnative2ascii命令转换为 Unicode 编码

CSV文件

Comma-Separated Values 表示逗号分隔值

一行表示一条记录,一个记录包含多个字段,字段之间用逗号分隔

使用Apache Commons CSV处理此类文件

Excel文件

使用Apache POI类库处理此类文件

  • xls:使用HSSFWorkbook
  • xlsx:使用XSSFWorkbook

HTML文件

使用jsoup处理此类文件

压缩文件

Java SDK 支持两种格式 gzipzip

gzip 只能压缩一个文件,而 zip 文件中可以包含多个文件

如果需要更多格式,考虑Apache Commons Compress

  • gzipGZIPInputStream GZIPOutputStream
  • zipZipInputStream ZipOutputStream

你可能感兴趣的:(Java笔记之文件)