1、流
1.1 流的概念
- 内存与内存设备之间的数据传输通道
- 水借助管道传输;数据借助流传输
1.2 流的分类
1.2.1 按方向(重点)
- 输入流:将存储设备中的数据读入到内存中
- 输出流:将内存中的内容写入到存储设备中
1.2.2 按单位
- 字节流:以字节为单位,可以读取任何文件的数据
- 字符流:以字符为单位,可以读取文本文件的数据
1.2.3 按功能
- 节点流:具有具体传输数据的能力
- 过滤流:在节点流的基础上加强功能
2、File、FileFilter
2.1 Filel类
概念:代表物理盘符中的一个文件或者文件夹
常见方法:
方法名 | 描述 |
---|---|
createNewFile() | 创建一个新文件。 |
mkdir() | 创建一个新目录。 |
delete() | 删除文件或空目录。 |
exists() | 判断File对象所对象所代表的对象是否存在。 |
getAbsolutePath() | 获取文件的绝对路径。 |
getName() | 取得名字。 |
getParent() | 获取文件/目录所在的目录。 |
isDirectory() | 是否是目录。 |
isFile() | 是否是文件。 |
length() | 获得文件的长度。 |
listFiles() | 列出目录中的所有内容。 |
public class Demo01 {
public static void main(String[] args) {
//路径都是从盘符开始
//File file = new File("E:\\File\\IO1.txt");
//File file = new File("E:\\File", "IO1.txt");
//File file = new File(new File("E:\\File"), "IO1.txt");
//路径从项目开始
File file = new File("file\\IO1.txt");
System.out.println("文件是否可读:"+file.canRead());
System.out.println("文件是否可写:"+file.canWrite());
System.out.println("文件是否隐藏:"+file.isHidden());
//相对于项目
System.out.println("相对路径:"+file.getPath());
//从盘符开始
System.out.println("绝对路径:"+file.getAbsolutePath());
System.out.println("文件名:"+file.getName());
System.out.println("文件的长度:"+file.length());
//返回的是从1970年1月1日到文件最后修改时间的毫秒数
System.out.println("文件的最后修改时间1:"+file.lastModified());
System.out.println("文件的最后修改时间2:"+getTime(file.lastModified()));
System.out.println("是否为文件:"+file.isFile());
System.out.println("是否为目录:"+file.isDirectory());
}
public static String getTime(long time){
//Date date = new Date(time);
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//String str = sdf.format(date);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(time);
return str;
}
}
2.2 FileFilter接口
FileFilter:文件过滤器接口
- boolean accept(File pathanme)
- 当调用File类中的listFile()方法时,支持传入FileFilter接口的接口实现类,当获取文件进行过滤,只有满足条件的文件才会出现在listFile()的返回值中
private static void test04(File file){
//数组中包含txt文件和目录
File[] files = file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
//过滤非txt文件的内容
if(pathname.isFile()){
//是否为txt文件
if(!pathname.getName().endsWith(".txt")){
return false;
}
}
return true;
}
});
for (File f:files) {
//判断是文件还是目录
if(f.isFile()){
System.out.println(f.getAbsolutePath());
}else{
test03(f);
}
}
}
3、字节流(重点)
3.1 字节抽象类
InputStream:字节输入流
- public int read(){}。
- public int read(byte[] b){}。
- public int read(byte[] b,int off,int len){}。
OutputStream:字节输出流
- public void write(int n){}。
- public void write(byte[] b){}。
- public void write(byte[] b,int off,int len){}。
3.2 字节节点流
FileOutputStream:
- public void write(byte[] b)。
- 一次写多个字节,将b数组中所有字节,写入输出流。
FileInputStream:
- public int read(byte[] b)。
- 从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数。
- 如果达到文件的尾部,则返回-1。
案例演示:FileInputStream读取文件。
package com.qf.ran.stream;
import com.qf.ran.utils.IOUtils;
import org.junit.Test;
import java.io.*;
/**
* @author Ran
* @since JDK 1.8
* IO流
* 1.根据数据的传输方向:
* 输入流/输出流
* 2.根据读写的单位:
* 字节流,字符流
* 3.根据功能划分:
* 基础流,包装类
*
*
* FileInputStream -- 文件字节输入流,基类为InputStream
*/
public class Demo01 {
//读取单个字节
@Test
public void test01(){
//文件字节输入流
FileInputStream fis = null;
try {
//fis = new FileInputStream(new File("IO1.txt"));
fis = new FileInputStream("IO3.txt");
//读取单个字节
int read = fis.read();
System.out.println((char)read);
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读取单个字节 -- 循环读取完毕
@Test
public void test02(){
//文件字节输入流
FileInputStream fis = null;
try {
//fis = new FileInputStream(new File("IO1.txt"));
fis = new FileInputStream("IO1.txt");
//读取到的数据字节
int read;
while((read = fis.read())!= -1){
System.out.println((char)read);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test03(){
FileInputStream fis = null;
try {
fis = new FileInputStream("IO1.txt");
//1024代表数组的长度,也代表一次读取1024个数据字节到数组中
byte[] b = new byte[1024];
//读取到数组中的数据长度
int len;
while((len = fis.read(b)) != -1){
//第一个参数为存放数据的数组(缓冲区)
//第二个参数是偏移量
//第三个参数是存放在数组中的数据长度
System.out.println(new String(b,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
IOUtils.closeAll(fis);
}
}
}
3.3 字节缓冲流
字节缓冲流:BufferedOutputStream、BufferedInputStream
- 提高IO效率,减少访问磁盘的次数
- 数据存储在缓冲区中,fush是将缓存区的内容写入文件中,也可以自己close,但是内存无法手动关闭
代码示例:
public class Demo01 {
//带缓冲区的字节输出流
@Test
public void test01() throws IOException {
//默认缓冲区大小为8192
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO1.txt"));
bos.write("good good study!".getBytes());
bos.close();
}
@Test
public void test02() throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO1.txt",true));
bos.write("day day up!".getBytes());
bos.close();
//刷新,会把缓冲区的数据写入文件中
//bos.flush();
}
//带缓冲区的字节输入流
@Test
public void test03() throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("IO1.txt"));
byte[] b = new byte[1024];
int len;
while((len = bis.read(b)) != -1){
System.out.println(new String(b,0,len));
}
bis.close();
}
//带缓冲区的字节流拷贝
}
3.4 对象流
对象流
- ObjectInputStream
- ObjectOutputStream
- 使用对象流进行读写操作是,本质上是在进行序列化与反序列化操作
- 写入对象的操作为序列化操作
- 读取对象的操作为反序列化操作
- 序列化和反序列化的序列号保持一致
- 私有的静态属性不会被序列 私有的transient属性不会被序列化
案例演示:使用对象流实现序列化和反序列化。
public class User implements Serializable {
//默认存在的序列号
//private static final long serialVersionUID = 1L;
//2个属性拥有对应的序列号 -- 序列化时的序列号
//private static final long serialVersionUID = -3904710604062277395L;
//3个属性拥有对应的序列号 -- 反序列化时的序列号
//private static final long serialVersionUID = 4353974749186785642L;
private String name;
private int age;
//会被序列化
//private int id;
//会被序列化
//static int id;
//不会被序列化
//private static int id;
//会被序列化
//public static int id;
//会被序列化
//protected static int id;
//会被序列化
//private final int ID = 1;
//会被序列化
//public final int ID = 1;
//不会被序列化
//private static final int ID = 1;
//会被序列化
//transient int id;
//不会被序列化
private transient int id;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo01 {
public static void main(String[] args) throws IOException {
//把对象存储到集合中,把集合通过对象流写入文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
ArrayList<User> list = new ArrayList<>();
list.add(new User("霞姐",18));
list.add(new User("泽哥",28));
list.add(new User("昌老师",28));
list.add(new User("波老师",28));
oos.writeObject(list);
oos.close();
/*
写入对象完毕后添加null对象
null对象添加有可能遗漏或者null对象后续再添加对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
oos.writeObject(new User("霞姐", 18));
oos.writeObject(new User("四青", 19));
oos.writeObject(new User("银珍", 20));
oos.writeObject(new User("玲苑", 20));
oos.writeObject(new User("玲苑", 16));
oos.writeObject(null);
oos.close();*/
//在写入对象之前写入int类型的数据,数据值为对象个数
//数据值与对象个数可以存在不匹配的情况
/* ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
oos.writeInt(4);
oos.writeObject(new User("霞姐", 18));
oos.writeObject(new User("四青", 19));
oos.writeObject(new User("银珍", 20));
oos.close();*/
/*BufferedWriter bw = new BufferedWriter(new FileWriter("IO3.txt"));
String str = user.getName()+user.getAge();
bw.write(str);
bw.close();*/
}
}
4、字符流(重点)
4.1 字节抽象类
Reader:字节输入流
- public int read(){}.
- public int read(char[] c){}.
- public int read(char[] int off, int len){}
Write:字符输出流
- public void write(int n){}.
- public void write(String str){}.
- public void write(char[] c){}.
4.2 字节节点流
FileWriter:
- public void write(String str).
- 一次写多个字符,将b数组中所有的字符,写成输出流
FileReader:
- public int read(char[] c)
- 从流中读取多个字符,将读到的内容存入c数组中,返回实际读取到的字符数,若是到达文件末尾,则返回-1.
public class TestFileReader {
public static void main(String[] args) throws Exception{
//1创建FileReader 文件字符输入流
FileReader fr=new FileReader("d:\\hello.txt");
//2读取
//2.1单个字符读取
//int data=0;
//while((data=fr.read())!=-1) {//读取一个字符
// System.out.print((char)data);
//}
char[] buf=new char[1024];
int count=0;
while((count=fr.read(buf))!=-1) {
System.out.println(new String(buf, 0, count));
}
//3关闭
fr.close();
}
}
public class TestFileWriter {
public static void main(String[] args) throws Exception {
//1创建FileWriter对象
FileWriter fw=new FileWriter("d:\\write.txt");
//2写入
for(int i=0;i<10;i++) {
fw.write("java是世界上最好的语言\r\n");
fw.flush();
}
//3关闭
fw.close();
System.out.println("执行完毕");
}
}
4.3 字节缓冲流
缓冲流:BufferedWriter、BufferedReader
- readLine()是BufferedReader独有的方法,作用是读取一行数据
- newLine()是BufferedWriter独有的方法,作用是写入换行符
public class Demo02 {
@Test
public void test01() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("IO1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("IO2.txt"));
/*char[] c = new char[1024];
int len;
while((len = br.read(c)) != -1){
bw.write(c,0,len);
}*/
String str;
//br.readLine()读取一行数据
while((str = br.readLine()) != null){
//写入一行数据
bw.write(str);
//写入换行符
bw.newLine();
}
br.close();
bw.close();
}
}
4.4 打印流
- PrintStream:打印字节流
- PrintWriter:打印字符流
- 支持数据原样打印
public class Demo01 {
@Test
public void test01() throws FileNotFoundException {
PrintStream ps = new PrintStream(new FileOutputStream("IO1.txt"));
//ps.write(97);
//打印流独有的方法,直接打印数据
ps.print(98);
ps.close();
}
@Test
public void test02() throws IOException {
PrintWriter pw = new PrintWriter(new FileWriter("IO2.txt"));
pw.write(97);
pw.print(97);
pw.close();
}
}
4.5 转换流
转换流: InputStreamReader、OutputStreamWriter
- 可以将字节流转换成字符流
- 可以设置字符的编码方式
public class Demo01 {
//转换流输出流
@Test
public void test01() throws Exception {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("IO5.txt"));
osw.write("净化广告");
osw.close();
}
//转换流输入流
@Test
public void test02() throws Exception {
InputStreamReader isr = new InputStreamReader(new FileInputStream("IO5.txt"));
char[] c = new char[1024];
int len;
while((len = isr.read(c)) != -1){
System.out.println(new String(c,0,len));
}
isr.close();
}
//使用场景
@Test
public void test03() throws Exception {
//方法返回字节流
FileInputStream fis = new FileInputStream("IO5.txt");
//需要使用BufferedReader的readLine()
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
//使用对应的方法..
}
//使用文件字节输入流读取不同编码格式的文件
@Test
public void test04() throws Exception {
FileInputStream fis = new FileInputStream("E:\\File\\File.txt");
byte[] b = new byte[1024];
int len;
while((len = fis.read(b)) != -1){
System.out.println(new String(b,0,len));
}
fis.close();
}
//使用文件字符输入流读取不同编码格式的文件
@Test
public void test05() throws Exception {
FileReader isr = new FileReader("E:\\File\\File.txt");
char[] c = new char[1024];
int len;
while((len = isr.read(c)) != -1){
System.out.println(new String(c,0,len));
}
isr.close();
}
//使用转换输入流读取不同编码格式的文件
@Test
public void test06() throws Exception {
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\File\\File.txt"),"GBK");
char[] c = new char[1024];
int len;
while((len = isr.read(c)) != -1){
System.out.println(new String(c,0,len));
}
isr.close();
}
}