Java学习笔记——IO流
1、 IO概述
根据数据的流向可以分为:输入流与输出流;而根据数据类型可分为字节流与字符流。几个重要的抽象基类如下图所示:
Java的IO流系统总结如下图所示:
节点流直接与数据源相连进行读取与写入,但因为直接使用节点流不方便,因此在节点流上再套接一层处理流。处理流的构造方法总是要以一个其他流作为参数。
常用节点流:
- 父类:InputStream 、OutputStream、 Reader、 Writer
- 文件处理:FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter
- 数组处理:ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter
- 管道处理:PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter
常用处理流:
- 避免频繁读写硬盘的缓冲流: BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter
- 用于读写基础数据类型的数据流: DataInputStream 、DataOutputStream
- 实现字符流与字节流直接转换的转换流: InputStreamReader 、OutputStreamReader
2、字节流
字节流以字节为单位一次写入或读取8位数据,因为所有数据都是以字节存在所以字节流可以应对各种情况;字符流则以字符为单位一次可读入多个字节,且只能处理字符类型数据,因此除了纯文本数据外通常都使用字节流。
2.1 字节输入流
InputStream是所有输入字节流的父类,是一个抽象类。它有几个子类:
- ByteArrayInputStream、StringBufferInputStream、FileInputStream这三个类分别用于从Byte数组、StringBuffer和文件中读取数据
- PipedInputStream从与其他线程共用的管道中获取数据
- ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)
2.2 字节输出流
OutputStream是所有输入字节流的父类,也是一个抽象类。它的几个子类与输入字节流类似,只不过将名字中的In改为Out,且是用于写入数据的。
2.3 代码示例
使用FileInputStream与FileOutputStream实现文件内容的读写
public class Myjava {
public static void main(String[] args) {
Myjava myjava = new Myjava();
String s="Hello,OUT";
//使用相对路径
File f=new File("src/Study/IO.txt");
myjava.Myread(f);
myjava.Mywrite(f,s);
}
public void Myread(File f){
//创建一个输入流对象
FileInputStream fin= null;
try {
fin = new FileInputStream(f);
//获取输入流中的可以读取的字节数
int length=fin.available();
//根据字节数创建字节数组并存储
byte[] a=new byte[length];
fin.read(a);
//利用字节数组创建字符串并打印
String s=new String(a);
System.out.println(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fin!=null) {
try {
//关闭流
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void Mywrite(File f,String s){
//输出流的处理方式类似于输入流
FileOutputStream fout=null;
try {
//这将替换掉之前文件的内容,想以追加模式打开:fout=new FileOutputStream(f,true);
fout=new FileOutputStream(f);
//将字符串转换为字节数组并写入到输出流中s
byte[] a=s.getBytes();
fout.write(a);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fout!=null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3、字符流
3.1 字符输出流
一图总览:
3.1.1 FileWriter
常用构造方法:
FileWriter(String fileName) //使用指定名字的文件创建
FileWriter(String fileName, boolean append) //使用指定名字的文件并以追加模式创建
FileWriter(File file) //使用给定的File类型对象创建
FileWriter(File file, boolean append) //使用给定的File类型对象并以追加模式创建
常用的方法(继承自OutputStreamWriter):
void write(char cbuf[], int off, int len) //从指定数组的指定下标开始写入len长度字符
Writer append(CharSequence csq, int start, int end)//将指定字符序列的子序列附加到内容中
Writer append(CharSequence csq)//将指定字符序列附加到内容中
void flush()//刷新流
void close()//关闭流,但在关闭前会先刷新
3.1.2 BufferedWriter
这是缓冲字符输出流,它为字符输出流添加了缓冲功能,可以提高写入文件的效率
常用构造方法:
BufferedWriter(Writer out) //使用默认大小的输出缓冲区创建输出流。
BufferedWriter(Writer out, int sz) //使用指定大小的输出缓冲区,创建一个新的缓冲字符输出流。
常用方法:
void flush()//刷新流
void close()//关闭流
void write(char[] cbuf, int off, int len) //写入数组的指定的一部分
void newLine() //写一行行分隔符
3.2 字符输入流
一图总览:
3.2.1 FileReader
常用构造方法:
FileReader(String fileName) //使用文件的名称创建
FileReader(File file) //使用File类型对象创建
常用方法(继承自InputStreamReader):
int read() //读取单个字符当读到流最后时返回-1
//读取字符存入指定数组中的一部分,返回读到的字符数量且当读到流的最后时返回-1
int read(char cbuf[], int offset, int length)
void close() //关闭流
3.2.2 BufferedReader
常用构造方法:
BufferedReader(Reader in) //使用默认大小的输入缓冲区创建缓冲字符输入流
BufferedReader(Reader in, int sz) //使用指定大小的输入缓冲区创建缓冲字符输入流
常用方法:
int read() //读取一个字符
int read(char[] cbuf, int off, int len) //读取字符到数组的一部分中
String readLine() //读取一行字符
long skip(long n) //读取时跳过字符
Stream<String> lines() //返回一个元素是从BufferedReader读取的行Stream
4、File
4.1 常用构造方法:
public File(URI uri) //使用文件的URI地址创建
public File(String pathname) //使用文件的绝对路径创建
public File(String parent, String child) //使用给定的父文件绝对路径、子文件绝对路径创建
public File(File parent, String child) //给定的父文件、子文件相对路径
4.2 用于创建的方法:
boolean mkdir() //创建目录,成功返回true,此文件夹已存在或父目录不存在则返回false
boolean mkdirs() //创建多级目录,成功返回true失败返回false,若父目录不存在则创建并返回true
boolean createNewFile() //创建新文件,文件不存在则创建并返回true,已存在则返回false
4.3 用于获取文件信息的方法:
String getName() //获取文件的名字(不是路径)
String getParent() //获取父目录的绝对路径,返回一个字符串
File getParentFile() //获取父文件,返回一个File对象
long lastModified() //返回文件最后一次修改的时间
long length() //返回文件的大小(单位字节)
boolean renameTo(File file) //文件重命名,成功时返回true否则返回false
boolean delete() //删除文件
File[] listFiles() //获取该目录下的所有的文件,若不是目录而是文件则返回null
String[] list() //获取该目录下所有文件的名字,若不是目录而是文件则返回null
4.4 用于判断文件信息的方法:
boolean isFile() //是否为文件
boolean isDirectory() //是否为目录
boolean exists() //文件是否存在
boolean isHidden() //是否被隐藏
boolean canRead() //是否可读
boolean canWrite() //是否可写
boolean canExecute() //是否可执行
boolean isAbsolute() //是否为绝对路径
4.5 FileFilter
这是IO包中的一个接口,拥有对文件的过滤功能,使用时需要重写accept方法
boolean accept(File pathname)
4.6 FilenameFilter
和FileFilter类似这也是IO包中的接口,能够根据文件的名字进行过滤,使用时需要重写accept方法
boolean accept(File pathname)
4.7 代码示例:
扫描某个目录下的所有文件:
public void GetFile(File f){
File[] files=f.listFiles();
for(File f1:files){
if(f1.isHidden())//判断是否被隐藏
continue;
else if(f1.isDirectory())//判断是否为目录
GetFile(f1); //递归调用此方法
else
System.out.println("文件:"+f1.getName()+" 绝对路径:"+f1.getAbsolutePath());
}
}
扫描某个目录下的所有目录:
public void GetFile(File f){
MyFilter myFilter = new MyFilter();
File[] files=f.listFiles(myFilter);
for(File f1:files){
if(f1.isHidden())
continue;
else
system.out.println("绝对路径:"+f1.getAbsolutePath());
}
}
class MyFilter implements FileFilter{
@Override
public boolean accept(File pathname) {
if(pathname.isDirectory())
return true;
return false;
}
}
扫描某个目录下所有的指定命名格式的文件:
public void GetFile(File f){
MyFilter2 myFilter2 = new MyFilter2(".txt");
File[] files=f.listFiles(myFilter2);
for(File f1:files){
if(f1.isHidden())
continue;
else
System.out.println("绝对路径:"+f1.getAbsolutePath());
}
}
class MyFilter2 implements FilenameFilter{
private String Filename;
public MyFilter2(String filename) {
this.Filename = filename;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(Filename); //查找名字的后缀为指定后缀的文件
}
}