IO/NIO 知识点记录
IO流目录
1、数据流的基本概念
(1)输入数据流
(2)输出数据流
2、基本字节数据流
(1)文件数据流
(2)过滤流
(3)管道数据流
(4)对象流
(5)可持久化
3、基本字符流
(1)读者和写者
(2)缓冲区读者和缓冲区写者
4、文件的处理
(1)File类
(2)随机访问文件
IO流
数据流
可粗略分为输入流(inputstream)输出流(outputstream)
1、输入数据流,只能读不能写(input stream)
java io包中所有的输入数据流都是从抽象类InputStream继承而来,并且实现了其中的所有方法。从数据流中读取数据时,必须有一个数据源与该数据流相连
int read()方法 所读取的数据默认为字节类型,读取结束时会得到-1
int read(byte[] b)方法 将多个字节读取到数组中,填满整个数组
int read(byte[] b,int off,int len)方法 从输入流中读取长度为len的数据,从数组b中下标为off的位置开始放置读取的数据,读取完毕返回读取的字节数,读取结束是也会得到-1
void close() 释放与该数据流相关的资源
int available()返回目前可读取的最大字节数,但实际的读操作读取的字节数可能大于该返回值
long skip() 跳过数据流中指定数量的字节不读,返回实际跳过的字节数
boolean markSupported() 指示数据流是否支持回退操作
void mark(int markarea) 标记数据流当前位置,并且划出缓冲区,大小至少为指定的参数
void reset() 回到数据流被标记的位置
2、输出数据流,只能写不能读
继承抽象类OutputStream
void write(int i)将字节i写入数据流中,是抽象方法,需要加以实现才能使用
void write(byte b[]) 将数组中的全部字节写入数据流
void write(byte b[],int off,int len) 将数组中的第off个字节开始的len个字节写入数据流,通常以系统允许的最大数据块长度为单位进行操作
void close() 关闭流和资源
void flush() 数据以特定长度的单位进行传输,可能会存在最后一部分的数据不够一个单位,而被保留在缓冲区里,flush()可以将这部分数据强制提交基本字节数据流类
基本字节数据流类
文件数据流
文件数据流包括FileInputStream和FileOutputStream,这两个类用来进行文件的IO处理,其数据源或数据重点都应当是文件,不支持mark()和reset()方法
//文件myFile作为数据流的输入源
FileInputStream fis = new FileInputStream("myFile")
//文件数据流示例,将“HELLO!”写入文件myFile.txt中
try{
FileOutputStream out = new FileOutputStream("E:/files/myFile.txt");
out.write('H');
out.write('E');
out.write('L');
out.write('L');
out.write('O');
out.write('!');
out.close();
}catch (Exception e){
e.printStackTrace();
}
//文件数据流示例,从myFile.txt中读取文件内容
try{
FileInputStream in = new FileInputStream("E:/files/myFile.txt");
while (in.available()>0){
System.out.println(in.read()+" ");
}
in.close();
}catch (Exception e){
e.printStackTrace();
}
对于FileOutputStream实例对象,如果指定的文件不存在,则系统创建一个新文件;如果文件存在,那么新写入的内容会覆盖原有数据。如果在读写文件或者生成新文件时发生错误,则会产生IOException;对于指定的文件不存在,则会产生FileNotFoundException,需要对这些异常进行声明或者捕获处理。
过滤流
过滤器数据流可以理解为对原始数据流进行处理过滤,这样从过滤流中读取的数据是对输入数据流的内容进行了特定处理之后的数据
1、缓冲区数据流
缓冲区数据流有BufferedInputStream和BufferedOutputStream,都属于过滤器数据流
缓冲区可以降低不同硬件设备之间的差异,提高IO操作的效率
这两个流提供了对mark()、reset()和skip()等方法的支持
//创建该类的实例对象时,有两种方法可以使用,一种取默认缓冲区大小:
FileInputStream fis = new FileInputStream("myFile");
InputStream is = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("myFile");
OutputStream os = new BufferedOutputStream(fos);
//另一种是自行设置缓冲区大小
FileInputStream fis = new FileInputStream("myFile");
InputStream is = new BufferedInputStream(fis,1024);
FileOutputStream fos = new FileOutputStream("myFile");
OutputStream os = new BufferedOutputStream(fos,1024);
!!注意,一般在关闭缓冲区输出流之前,应该使用flush()方法强制输出剩余数据,确保缓冲区所有数据都写入输出流
2、数据数据流
在前面提到的数据流中,处理的数据都是指字节或者字节数组,这是进行数据传输系统默认的数据类型
但实际很多时候所要处理的数据不止这两种类型,这时候就需要一种专门的数据流来处理
DataInputStream和DataOutputStream就是这样两个过滤器数据流,他们允许通过数据流读取Java基本数据类型boolean、float等
//创建方式
FileInputStream is = new FileInputStream("myFile");
DataInputStream dis = new DataInputStream(is);
这两个类提供了特定的方法操作不同的基本类型
//DataInputStream类提供了如下方法
byte readByte()
long readLong()
double readDouble()
boolean readBoolean()
String readUTF()
int readInt()
float readFloat()
short readShort()
char readChar()
//根据方法名字可以看出,上述方法分别对基本类型进行读取
//DataOutputStream类提供了如下方法
void writeByte(byte aByte)
void writeLong(long aLong)
void writeDouble(double aDouble)
void writeBoolean(boolean aBool)
void writeUTF(String aString)
void writeInt(int anInt)
void writeFloat(float aFloat)
void wrietShort(short aShort)
void writeChar(char aChar)
可以看出,两个类的方法都是成对出现的,要注意的是,由于字符编码的原因,对字符串进行操作时,应该使用Reader和Writer两个类中的方法,而不是readUTF()和wirteUTF(),后续会讲到
3、管道数据流
管道数据流主要用于线程间的通信,一个线程中的PipedInputStream对象要从另一个线程中的PipedOutputStream对象中接收输入,
所以这两个类必须要一起使用,建立一个通信通道,也就是说管道数据流必须同时具备可用的输入端和输出端
//创建一个通信信道可以分为三个步骤
//1、建立输入数据流
PipedInputStram pis = new PipedInputStream();
//2、建立输出数据流
PipedOutputStream pos = new PipedOutputStrean();
//3、将输入输出流连接起来
pis.connect(pos);
//或者pos.connect(pis);
//上面的创建形式用的是无参构造,也可以利用有参构造方法
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
//进行数据通信
public void testPiped() throws IOException {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
byte data = 0;
System.out.println("开始传输-----");
try{
System.out.println("将数据-"+data+"-传输至pos");
//pos将数据写入管道
pos.write(data);
//pis从管道中读取数据
System.out.println("接收数据"+pis.read());;
}finally {
pis.close();
pos.close();
}
}
4、对象流
5、可持久化
基本字符流
字符流是在字节流的基础上,加上编码形成的数据流,因为字节流在操作中文时可能会出现乱码
字节流可以支持声音,视频,图片,文本等所有文件类型,而字符流只支持文本文件
读者和写者
Reader和Writer
字符输入流Reader
Reader常用子类 FileReader
//文件字符输入流常用方法
read();
read(char []);
read(char [],offset,len);
//字符输入流示例
try{
File file = new File("E:/files/myFile.txt");
FileReader fileReader = new FileReader(file);
char[] ca = new char[1024];
int count = 0;
while ((count = fileReader.read(ca)) != -1){
System.out.println(new String(ca,0,count));
}
}catch (FileNotFoundException e){
System.out.println("文件未找到");
}catch (Exception e){
e.printStackTrace();
}
字符输出流Wirter
Writer常用子类 FileWriter
//文件字符输出常用方法
wirter();
writer(char []);
writer(char[],offset,len);
writer(String);
flush();
//注意,close()方法中默认调用了flush()方法
//字符输出流示例
FileReader fileReader = new FileReader(new File("E:/files/myFile.txt"));
FileWriter writer = new FileWriter(new File("E:/files/myFile2.txt"));
char[] ca = new char[1024];
int count = 0;
while ((count = fileReader.read(ca)) != -1){
System.out.println(new String(ca,0,count));
writer.write(ca,0,count);
}
System.out.println("完成---------");
fileReader.close();
writer.close();
缓冲区读者和缓冲区写者
BufferedReader/BufferedWriter 带缓冲区的字符输入流与字符输出流
缓冲区读者
BufferReader带缓冲区的字符输入流
常用方法:
readLine() 读取一行,如果为文件末尾,返回值为nul
//代码示例
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("E:/files/myFile.txt")));
String value = "";
while((value=bufferedReader.readLine())!=null){
System.out.println(value);
}
bufferedReader.close();
缓冲区写者
BufferedWriter
常用方法:
writer(string) //将字符串写入 到输出流
newLine() //根据系统的行分割符进行换行
//代码示例
BufferedReader bufferedReader = new BufferedReader(new FileReader("E:/files/myFile.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("E:/files/myFile3.txt"));
String value = "";
while((value = bufferedReader.readLine()) != null){
bufferedWriter.write(value);
bufferedWriter.newLine();
}
bufferedWriter.close();
bufferedReader.close();
文件的处理
File类
在对一个文件进行I/O操作之前,必须获得有关这个文件的基本信息,例如文件能不能被读取,写入,绝对路径,文件长度等;
java.io.File类提供了获得文件基本信息和操作文件的一些工具
//创建一个新的File对象可以使用以下三种构造方法
//第一种
File myFile;
myFile = new File("myFile");
//第二种
myFile = new File("/","myFile");
//第三种
File myDir = new File("/");
myFile = new File(myDir,"myFile");
创建File类对象之后,可以应用其中的相关方法来获取文件的信息
1.与文件名相关的方法
String getName()//获取文件名
String getPath()//获取文件路径
String getAbsolutePath()//获取文件绝对路径
String getParent()//获取文件父目录名称
boolean renameTo(File newName)//更改文件名,成功则返回true,否则返回false
2.文件测定方法
boolean exists()//文件对象是否存在
boolean canWrite()//文件对象是否可写
boolean canRead()//文件对象是否可读
boolean isFile()//文件对象是否是文件
boolean isDirectory()//文件对象是否是目录
boolean isAbsolute()//文件对象是否是绝对路径
3.常用文件信息和方法
long lastModified()//获取文件最后修改时间
long length()//获取文件长度
boolean delete()//删除文件对象指向的文件,成功则返回true,否则返回false
//样例程序
File file = new File("E:/files/myFile.txt");
System.out.println("文件是否存在---"+ file.exists());
System.out.println("文件是否可写---"+file.canWrite());
System.out.println("文件是否可读---"+file.canRead());
System.out.println("文件是否为文件---"+file.isFile());
System.out.println("文件是否为目录---"+file.isFile());
System.out.println("文件是否为绝对路径---"+file.isAbsolute());
System.out.println("文件名为---"+file.getName());
System.out.println("文件路径为---"+file.getPath());
System.out.println("文件绝对路径为---"+file.getAbsolutePath());
System.out.println("文件父级路径为---"+file.getParent());
System.out.println("文件上次修改时间为---"+file.lastModified());
System.out.println("文件长度为---"+file.length());
File newFile = new File("newFile");
file.renameTo(newFile);
System.out.println("文件名更改为-->"+newFile.getName());
System.out.println("myFile是否存在?---"+file.exists());
newFile.delete();
System.out.println("删除"+newFile+"......");
System.out.println(newFile+"是否存在?"+newFile.exists());
目录工具
boolean mkdir()//创建新目录
boolean mkdirs()//创建新目录,层级
String[] list()//列出符合模式的文件名
类file同样可以描述目录,但是不可以更改目录名,也不能进行删除。如果目录不存在,可以用mkdir()和mkdirs()创建新目录,两者区别在于后者能一次生成多个层次的子目录