Java 输入/输出笔记

File类

File类通过文件路径字符串来创建File实例,该文件路径字符串既可以是绝对路径,也可以是相对路径。用于代表与平台无关的文件和目录名

1、访问文件和目录

//访问文件名相关方法
String getName()
String getPath()
File getAbsoluteFile()
String getParent()
boolean renameTo(File newName)

//文件检测相关方法
boolean exists()
boolean canWrite()
boolean canRead()
boolean isFile()
boolean isDirectory()

//文件操作相关方法
boolean createNewFile()
boolean delete()
static File createTempFile(String prefix,String suffix)
static File createTempFile(String prefix,String suffix,File directory)

//目录操作相关方法
boolean mkdir()
String[] list()
File[] listFiles()

2、文件过滤器
File类的list方法可以接受一个FilenameFilter参数,通过该参数选择符合条件的文件。
FilenameFilter接口里包含了一个accept(File dir,String name)方法,该方法将依次对指定的File的所有子目录或文件进行迭代,如果该方法放回TRUE,则list()方法会列出该子目录或文件

Java的IO流(重点)

1、输入流和输出流
输入流:只能从中读取数据 in,主要由inputStream,Reader作为基类
输出流:只能从中写如数据 out,主要由outputStream,Writer作为基类

2、字符流和字节流
字符流:由inputStream,outputStream作为基类
字节流:由Reader、Writer作为基类

3、流的模型概念
输入流模型:这里写图片描述
输入流使用隐式的记录指针来表示当前正在整备从哪一个“水滴”开始读取,每当程序从InputStream或Reader里取出一个或者多个“水滴”,记录指针向后移动,其中InputStream和Reader记录了一些方法来控制记录指针的移动。

输出流模型:这里写图片描述
输出流同样采取隐式的记录指针来标记当前水滴即将放入的位置,每当程序向OutputStream或Writer里输出一个或者多个水滴后,记录指针自动向后移动

4、字节流、字符流解析

InputStream的方法

int read() //从输出流中读取单个字节
int read(byte[] b)//从输出流中读取b.length个字节,并且将字节存放在字节数组b中,放回读取的字节数
int read(byte[] b.int off,int len) //从输出流中最多读取len个字节,并且从字节数组的off位置开始读取

Reader里面包含如下三个方法:

int read() //从输出流中读取单个字符
int read(byte[] b)//从输出流中读取b.length个字符,并且将字节存放在字符数组b中,返回读取的字符数
int read(byte[] b.int off,int len) //从输出流中最多读取len个字符,并且从字符数组的off位置开始读取,返回读取的字符数
//InputStream和Reader支持如下几个方法来移动记录指针
void mark(int readAheadLimit):在当前位置记录一个标记
Boolean markSupported()
void reset()
long skip(long n)

inputSteam和Reader的实现类:FileInputStream和FileReader,是节点流,与文件直接相关


outputStream

//outputStream、Writer的共同方法
void write(int c)//将指定的字节、字符输出到输出流中
void write(byte[]/char[] buf) //将指定的字节数组或字符数组中的数据输出到指定输出流中
void write(byte[]/char[] buf,int off,int len)

Writer支持

void write(String str)//将str字符串里包含的字符输出到输出流中
void write(String str,int off,int len)

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点

字节流与字符流的区别
字节流和字符流使用是非常相似的,那么除了操作代码的不同之外,还有哪些不同呢?
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容。

处理流的用法
处理流
这里写图片描述

处理流可以隐藏底层设备上节点流的差异,并且对外提供更加方便的输入输出方法,让程序员只关心高级操作
识别处理流和节点流
只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流一定是处理流,而且所有节点流都是以物理IO节点作为构造器参数的。

5、输入输出流体系(按功能分类)
这里写图片描述

7、RandomAccessFile(支持“随机访问”的方式,程序可以直接跳转到文件的任意地方读写数据)

RandomAccessFile移动制动指针的方法:

long getFilePointer()//返回文件当前指针位置
void seek(long pos)//将文件指针定位到pos位置

对象序列化(将对象转化为二进制流)

对象序列化(Serialize)的目的是将对象保存到磁盘上,或者是允许在网络中直接传输对象。
对象的反序列化(Deserialize)则是从IO流中恢复为原来的对象。

如果需要让某个对象支持 序列化机制,则必须让他的类是可序列化的,该类必须实现如下的两个接口之一。

Serializable //该接口是个标记接口,仅仅是代表该类是可序列化的,没有实现任何方法
Externalizable

1、使用对象流实现序列化
一旦某个类实现了Serializable接口,该类的对象就是可序列化的,程序可以通过如下两个步骤来序列化该对象

//1、创建一个ObjectOutputStream,这是一个处理流,所以必须建立在其他节点流上
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("Object.txt"));

//2、调用ObjectOutputStream对象的writeObject()方法输出可序列化对象
oos.writeObject(per);

如果希望从二进制流中恢复Java对象,则需要使用反实例化。

//创建一个ObjectInputStream输入流,这个输入流是个处理流,必须建立在节点流的基础之上。
 ObjectinputStream ois = new ObjectInputStream(
 new FileInputStream("object.txt"))
 //2、调用ObjectInputStream对象的readObject()方法读取流中的对象,返回一个Object类型的Java对象
 Person p = (Person)ois.readObject();

注意:反序列化读取的仅仅是Java对象的数据,而不是Java类,因此采用反序列化恢复Java对象时,必须提供该Java对象所属的class文件,否则将会引起ClassNotFoundException异常。

对象引用的序列化
当程序序列化一个对象时,如果该对象持有另一个对象的引用时,为了在反序列化时可以正常恢复该Teacher对象,程序会顺带将该对象也进行序列化,所以该引用的对象必须是可序列化的,否则对象将不可序列化。

NIO

新IO采用内存映射文件的方式来处理输入输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存的方式访问文件(模拟了操作系统上的虚拟内存概念)

Channel(通道)和Buffer(缓冲)是新IO的核心对象,Channel是对传统的输入输出系统的模拟,在新IO系统中所有的数据都需要通过通道传输;它与传统的InputStream和OutputStream的最大区别在于它提供了一个Map()方法,通过该方法可以直接将“一块数据”映射到内存中。

Buffer可以被理解为一个容器,他的本质是一个数组,发送到Channel中所有对象都必须首先放到Buffer中,而从Channel中读取的数据也必须先放进buffer中。

1、使用buffer
Buffer是一个抽象类,其最常用的子类为byteBuffer,他可以在底层字节数组上进行get/set操作。除了ByteBuffer之外,对应的其他基本数据类型有相应的Buffer类:CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。

//创建一个容量为capacity的XXXBuffer对象
static XxxBuffer allocate(int capacity)

Buffer的三个重要概念:容量、界限、位置
容量:表示该Buffer的最大数据容量
界限:第一个不应该被读出或写入的缓冲区的索引位置
位置:用于指明下一个可以被读出的或写入的缓冲区位置索引

//满足关系:
0<=mark<=position<=limit<=capacity

这里写图片描述

这里写图片描述
概括:flip()为从Buffer中取出数据做好准备、clear()为再次向Buffer中装入数据做好准备

2、使用Channel
Channel类似于传统的流对象、但与传统的流对象有两个主要的区别
1、Channel可以直接将指定的文件的部分或全部直接映射成Buffer
2、程序不能直接访问Channel中取得数据,包括读取和写入,Channel只能与Buffer交互

注意:所有Channel都不应该通过构造器直接创建,而是通过传统的InputStream和OutputStream的getChannel方法来返回Channel,不同的节点返回的Channel不一样。

Channel最常用的方法:read()、write()、map()
map()方法用于将Channel对应的部分或全部数据映射成ByteBuffer;而read()或write()方法都有一些列重载形式,这些方法用于Buffer中读取数据或向Buffer中写数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值