1.概述
(1)字节流和字符流
字节流:以字节为单位进行数据的读写
字符流:以字符为单位进行数据的读写
(2)输入流:只能从流中读取数据,不能写入数据
输出流:只能向流中写入数据,不能读出数据
(3)节点流:低级流,可以从一个特定的I/O设备中读写数据的流
处理流:高级流,用于对一个已经存在的节点流进行连接和封装
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader
字符输入流:Writer
2.字节流
(1)概述
InputStream常用方法:
方法 | 功能 |
---|---|
int read() | 从输入流读取一个8位的字节,把它转换成0-255之间的整数,并返回。没有时返回-1 |
int read(byte[] b) | 从输入流读取若干字节,把他们保存到参数b指定的自己数组中,返回读取字节的数目 |
int read(byte[] b,int off,int len) | 从输入流读取若干字节,把它们保存到参数b指定的字节中,off指定字节数组开始保存数据的起始下标,len表示读取的字节数目 |
void close() | 关闭此输入流并释放相关的系统资源 |
OutputStream常用方法:
方法 | 功能 |
---|---|
void write(int b) | 向输出流写入一个字节 |
void write(byte[] b) | 把参数b指定的字节数组写到输出流 |
void write(byte[] b,int off,int len) | 将指定字节数组从偏移量off开始的len个字节写入输出流 |
void flash() | 刷新此输出流并强制写出所有缓冲的输出字节 |
void close() |
(2)字节流读写文件
读取文本文件:
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileInputStream in=new FileInputStream("test.txt");
int b=0;
while((b=in.read())!=-1){
System.out.println(b);//输出的是字母的ASCII码
}
in.close();
}
}
写文本文件:
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileOutputStream out=new FileOutputStream("test.txt");
String s="hello";
out.write(s.getBytes());//将字符串转换成字节数组进行写入操作
out.close();
}
}
注:写文件之前首先会创建文件,如果该文件已经存在则会把文件中的内容全部删除
写文本文件(追加内容):
FileOutputStream out=new FileOutputStream("test.txt",true);
(3)文件拷贝
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileInputStream in=new FileInputStream("src.jpg");
FileOutputStream out=new FileOutputStream("dest.jpg");
int len=0;
while((len=in.read())!=-1){
out.write(len);
}
in.close();
out.close();
}
}
(4)字节流缓冲区
当通过流的方式拷贝文件时,为了提高效率,也可以定义一个字节数组作为缓冲区。则可以将数据先保存在字节数组中,然后将字节数组中的数据一次性写入到新文件中。
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileInputStream in=new FileInputStream("src.jpg");
FileOutputStream out=new FileOutputStream("dest.jpg");
int len=0;
byte[] buff=new byte[1024];
while((len=in.read(buff))!=-1){
out.write(buff,0,len);
}
in.close();
out.close();
}
}
(5)字节缓冲流
BufferedInputStream
BufferedOutputStream
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("src.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("dest.jpg"));
int len=0;
while((len=bis.read())!=-1){
out.write(len);
}
bis.close();
bos.close();
}
}
3.字符流
(1)字符流操作文件
使用FileReader以字符的形式读取文件中的内容:
import java,util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileReader filereader=new FileReader("reader.txt");
int len=0;
while((len=filereader.read()!=-1){
System.out.println(char(len));//输出的是int类型数据,因此想得到字符必须进行强制类型转换
}
filereader.close();
}
}
使用FileWrite以字符的形式写文件:
import java,util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileWrite filewrite=new FileWrite("reader.txt");
filewrite.write("good good study\n");
filewrite.write("day day up\n");
filewrite.close();
}
}
字符流缓冲区实现文件的拷贝:
import java.util.io.*;
public class Example{
public static void main(String[] args){
FileReader filereader=new FileReader("src.txt");
FileWriter filewrite=new FileWrite("dest.txt");
int len=0;
char[] buff=new char[1024];
while((len=filereader.read(buff))!=-1){
filewrite.write(buff,0,len);
}
filereader.close();
filewrite.close();
}
}
同样也存在着待缓冲取得字符缓冲流BufferedRead,BufferedWrite
BufferedRead中有一个十分重要的方法readLine方法,用来一次读取一行文本
BufferedWrite有一个newLine方法会根据不同的操作系统生成不同的换行符
(2)转换流
实现字节流和字符流的转换
InputStreamReader:将字节输入流转换成字符输入流
OutputStreamWrite:将字节输出流转换成字符输出流
import java.util.io.*;
public class Example{
public static void main(String[] args)throws Exception{
FileInputStream in=new FileInputStream("reader.txt");//创建字节输入流对象
InputStreamReader isr=new InputStreamReader(in);//转换成字符输入对象
BufferedReader br=new BufferedReader(isr);//转换成缓冲流对象
FileOutputStream out=new FileOutputStream("out.txt");
InputStreamWrite isw=new InputStreamReader(out);
BufferedWrite bw=new BufferedReader(isw);
string line=null;
while((line=br.readline())!=null){
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
}
4.File类
针对文件的操作。
(1)常用方法
File类常用的构造方法:
方法 | 功能 |
---|---|
File(String pathname) | 通过指定的一个字符串类型的文件路径来创建一个新的File对象 |
File(String parent,String child) | 根据指定的一个字符串类型的父路径和一个字符串类型的子路径创建一个File对象 |
File(File parent,String child) | 根据指定的File类的父路径和字符串类型的子路径创建一个File路径 |
File类的常用方法:
方法 | 功能 |
---|---|
boolean exists() | 判断File对象是否存在 |
boolean delete() | 删除File’对象对应的文件或目录 |
boolean createNewFile() | 当File对象不存在时,将创建 |
String getName() | 返回文件夹的名称 |
String getPath() | 返回对应的路径 |
String getAbsolutePath() | 返回绝对路径 |
String getParent() | 返回对应的父目录(不包含最后一级子目录) |
boolean canRead() | 判断对应的文件或者目录是否可读 |
boolean canWrite() | |
boolean isFile() | 判断File对象是否是文件 |
boolean isDirectory() | 判断File对象是都是目录 |
boolean isAbsolute() | 判断File对象是否是绝对路径 |
long lastModified() | 返回文件最后修改时间的毫秒值 |
long length() | 返回文件的长度 |
String[] list() | 列出指定目录的全部内容,只是列出名称 |
String[] list(FilenameFilter filter) | 列出符合条件的文件 |
File[] listFiles() | 返回一个包含了File对象所有子文件和目录的File数组 |
(2)遍历目录下的文件
list方法:
import java.util.io.*;
public class Example{
public static void main(String[] args){
File file=new File("路径名");
if(file.isDirectory()){
String[] fileNames=file.list();//获取目录中所有文件的名称
Arrays.stream(fileNames).forEach(i->System.out.println(i));
String[] fileNames2=file.list((dir,name)->name.endWith(".txt"));//筛选txt文件
}
}
}
listFiles()返回一个File对象数组,当对数组中的元素进行遍历时,如果元素中还有子目录需要遍历,则可以使用递归再次遍历子目录。
import java.util.io.*;
public class Example{
public static void main(Sting[] args){
File file=new File("文件路径");
filedir(file);
}
public static void filedir(File file){
File[] listFiles=file.listFiles();
if(File files:listFiles){
if(files.isDirectory()){
filedir(files);//递归
}
System.out.println(files);
}
}
}
(3)删除文件及目录
import java.util.io.*;
public class Example{
public static void main(Sting[] args){
File files=new File("文件路径");
deletedir(files);
}
public static void deletedir(File files){
File[] listFiles=files.listFiles();
if(File file:listFiles){
if(file.isDirectory()){
deletedir(file);//递归
}
file.delete()//如果是文件,则删除
}
files.delete();//最后删除整个目录
}
}
注:java删除不走回收站,一旦删除就无法恢复
5.RandomAccessFile
它不属于流类,但是能够读写文件,而且可以从文件的任何位置开始执行读写数据的操作。
RandomAccessFile的构造方法:
方法 | 功能 |
---|---|
RandomAccessFile(File file,String mode) | File指定访问的文件,mode指定访问模式 |
RandomAccessFile(String file,String mode) |
r | 只读 |
---|---|
rw | 读写,文件不存在会自动创建 |
rws | 读写,要求对文件的内容或者元数据的每个更新都同步到写入到底层的存储设备 |
rwd | 读写,要求对文件的内容每个更新都同步到写入到底层的存储设备 |
RandomAccessFile针对文件的随机操作:
方法 | 功能 |
---|---|
long getFilePointer() | 返回当前读写指针所处的位置 |
void seek(long pos) | 设定读写指针的位置,与开头文件相隔pos个字节数 |
int skipBytes(int n) | 使读写指针从当前位置开始,跳过n个字节 |
void write(byte[] b) | 将指定字节数组写入到当前文件,并从当前文件指针开始 |
void setLength(long newLength) | 设置此文件的长度 |
final String readLine() | 从指定文件当前指针读取下一行内容 |
6.对象序列化
java中的对象序列化:将对象中的数据保存在磁盘上。
对象序列化机制可以使内存中的java对象转换成与平台无关的二进制流,既可以将这种二进制流持久的保存在磁盘中,又可以通过网络将这种二进制流传输到另一个网络节点,其他程序在获得了这种二进制流后,还可以将它恢复成原来的java对象。
在java中可序列化的类必须实现Serializable和Externalizable这两个接口。
public class Persion implements Serializable{
private static final long serialVersionUID=1L;//为该类指定一个serialVersionUID变量值,作用是标识java类的序列化版本。不定义系统也会自动给出
...
...
}
7.NIO
(1)概述
NIO采用内存映射文件的方式来处理输入输出,它将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件。
NIO使用的是通道和缓冲区,数据从通道读入缓冲区,或者从缓冲区写入通道。其三大核心部分为:Buffer、Channel、Selector
Buffer:本质是一个数组缓冲区
Chanel:对传统输入输出的模拟,所有的数据都需要通过通道流的形式传输
Selector:用于监听多个通道的事件,用于多线程处理
(2)Buffer
Buffer类的子类并没有提供构造方法,因此不能通过构造方法来创建对象。
创建一个容量为6的CharBuffer对象的语句:
CharBuffer buffer=CharBuffer.allocate(6);
其中的三个重要概念
capacity(容量):缓冲区的容量表示该Bufffer的最大数据容量
limit(界限):表示Buffer容量中不可被读取的区域的第一个索引
position(位置):用于指定下一个可以被读写的缓冲区位置索引
Buffer使用示例:
import java.nio.CharBuffer;
public class Example{
public static void main(String[] args){
CharBuffer charbuffer=CharBuffer.allocate(6);//创建一个容量为6的Buffer对象
charbuffer.capacity();//得到容量
charbuffer.limit();//得到界限值
charbuffer.position();//得到初始位置
charbuffer.put('x');//向charbuffer中放入元素
charbuffer.position();//加入元素后的位置
charbuffer.flip();//反转缓冲区,先将limit设置成当前position位置,然后将position设置为0
charbuffer.get();//取出数据
charbuffer.clear();//清除缓冲区,将position设置为0,limit设置为capacity
}
}
执行完clear方法后,对象中的数据依旧存在,而且通过索引取出元素值后,position的值并没有受到影响。
(3)Channel
Channel是一个接口对象,与传统的流对象的不同之处在于:它可以异步的执行I/O读写操作;它的读写操作是双向的,即可以从其中读取数据,也可以写数据到里面;它可以直接将指定文件的部分或者全部直接映射成Buffer;它只能Buffer进行交互。
Channel对象不是通过构造方法来创建的,而是通过传统I/O的getChannel方法来获取。
文件拷贝案例,FileChannel类的使用:
import java.io.*;
import java.nio.channels.*;
public class Example{
//创建RandomAccessFile对象,指定源文件
RandomAccessFlie infile=new RandomAccessFile(文件路径,"rw");
//读取源文件FileChannel通道
FileChannel inChannel=infile.getChannel();
//创建RandomAccessFile对象,指定目标文件
RandomAccessFlie outfile=new RandomAccessFile(文件路径,"rw");
//读取目标文件FileChannel通道
FileChannel outChannel=outfile.getChannel();
//使用transferTo方法进行整体复制
long transferTo=inChannel.transferTo(0,inChannel.size(),outChannel);
if(transferTo>0){
System.out.println("复制成功");
}
//关闭资源
infile.close();
outfile.close();
inChannel.close()
outChannel.close();
}
transferTo第一个参数表示所需转移文件的起始位置,第二个参数表示要传输的最大字节数,第三个参数表示目标通道。
8.NIO.2
(1)Path接口
该接口是一个共用在文件系统中定位文件的对象,通常表示一个依赖于系统的文件路径。
Path接口的基本使用:
import java.nio.file.Path;
import java.nio.file.Paths;
public class Example{
Path path=Paths.get(文件路径);
path.getRoot();//文件的根路径
path.getParent();//文件的父路径
path.getNameCount();//path文件中的路径名称数
Path name=path.getName(1);//获取索引为1的路径的名称
path.toUri();//path路径的URI路径
path.toAbsolutePath();//path的绝对路径
}
(2)Files工具类
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class Example{
public static void main(String[] args){
//定义一个目录路径的Path对象
Path directoryPath=Paths.get(目录路径);
//根据Path对象创建多级目录
Files.createDirectories(directoryPath);
//定义一个文件路径的Path对象
Path filePath=Paths.get(文件路径);
//根据Path对象创建多级目录
Files.createFile(filePath);
//创建一个list集合,并向集合中添加内容
List<String>list=new ArrayList<String>();
list.add("fjajfjhijije");
//将集合中的内容追加写入到指定的文件中
Files.write(filePath,list,StandarOpenOption.APPEND);
List<String>lines=Files.readAllLines(filePath);//读文件中写入的内容
}
}