问题背景
如果我们要存数据,我们可以存在数组里集合里,但是他们都有一个共性,那就是存在内存当中。优点就是我们读取的比较快。缺点就是当我们重新启动项目的时候,这些数据就会消失。 为了对数据进行持久化的保存,就可以把数据存在文件当中,为了解决这个,java为我们提供了IO流。
流(数据流动)
数据流动的方向分为
- 读数据(输入Input)
- 写数据(输出Output)
什么叫文件
一种电脑的存储形式
File是一个java.io
包中的类
File是在内存中的一个对象<---映射--->硬盘上的文件或文件夹
路径是看创建的对象能否与硬盘中的一个真实的文件产生对应映射关系,编译不会报错,只有当通过文件流去读取文件的内容时才会报错。
系统内硬盘上文件的名字是不区分大小写的。
File类常用API
File file = new File("D:"+ File.separator + "testFile.txt");
System.out.println(file.canRead());
System.out.println(file.canWrite());
System.out.println(file.isDirectory());
System.out.println(file.isHidden());
System.out.println(file.isFile());
什么是文件流
顾名思义 读取文件的信息(in) 将信息写入文件中(out)
按照读取或写入的单位(字节数)大小来区分
字节型文件流(1字节)
FileInputStream/FileOutputStream
字符型文件流(2字节--1字符)
FileReader/FileWriter
/*
测试FileInputStream
read():从管道一个字节一个字节的读,返回值是Unicode码,其中要注意的是\r\n的字节码是13和10
read(byte[] b):每次从流管道中读取若干个字节,存入数组中,返回值为有效元素个数
available():返回值显示流管道中缓存的字节数
skip(long n):跳过几个字节,再读取(多线程读文件可以利用)
*/
FileInputStream fileInputStream = null;
try {
File file = new File("D:" + File.separator + "testFile.txt");
fileInputStream = new FileInputStream(file);
int available = fileInputStream.available();//显示流管道中有多少缓存字节
System.out.println(available);
byte[] b = new byte[5];
int read = fileInputStream.read(b);
while (read != -1) {
String string = new String(b, 0, read);
System.out.println(string);
read = fileInputStream.read(b);
}
/*int i = fileInputStream.read();//读不到则返回值为-1
while (i != -1) {
System.out.println(i);
i = fileInputStream.read();
}*/
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
//将流通道关闭
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
测试FileOutputStream
将String转成byte,调用getBytes()方法
*/
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("D:" + File.separator + "lili.txt"), true);
String str = "dgergdfgdfgdfg";
byte[] bytes = str.getBytes();
fos.write(bytes);
//fos.write(97);//将b写入到管道中
fos.flush();//刷新,将管道中的字节推送到File中
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/*
文件的复制
*/
public void copyFile(File file, String path) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(new File(path + File.separator + file.getName()));
byte[] b = new byte[1024];
int read = fis.read(b);
while (read != -1) {
fos.write(b, 0, read);//将文件的有效字节写入
fos.flush();
read = fis.read(b);
}
System.out.println("复制完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new OperationFile().copyFile(new File("D:" + File.separator + "lili.txt"), "G:");
}
/*
加强版
*/
public void copyPlusFile(File file, String newPath) {
//获取当前File的绝对路径,用拼串的方式获取新的路径的名字
String oldFilePath = file.getAbsolutePath();
String newFilePath = newPath + oldFilePath.split(":")[1];
//创建一个新的文件夹
File newFile = new File(newFilePath);
File[] files = file.listFiles();
if (files != null) {//是一个文件夹
newFile.mkdir();
if (files.length != 0) {
for (File file1 : files) {
this.copyFile(file1, newPath);
}
}
} else {//是一个文件
//读取旧的文件和写入新的文件
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(oldFilePath);
fos = new FileOutputStream(newFilePath);
byte[] b = new byte[1024];
int count = fis.read(b);//读取的有效字节
while (count != -1) {
fos.write(b, 0, count);
fos.flush();//将流管道元素清空出去
fis.read(b);
}
System.out.println(newFile.getName() + "文件复制完毕");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符型文件流
只能操作纯文本文件(文件右键,记事本能打开)
//read(char[] c)
FileWriter fr = new FileReader(file);
String srt = "abc";
char[] c = srt.toCharArray();
FileWriter fw = new FileWriter(file);
fw.write(c);
fw.write(srt);
存储信息的方式(为什么要操作File)
变量 只能存一份
数组 存储好多个 数据类型统一
-
集合 存储好多个 存储后个数还能改变 泛型----数据类型统一
以上三个都是Java中的类型==(对象存储在内存中)==
都存储在内存中,程序执行完毕,Java虚拟机停止的时候,内存空间就被回收了。所以存储的数据都是临时性存储的。
-
文件 ==存储好多信息==
文件是存储在硬盘上的----》永久性保存。数据虽然安全,但是文件毕竟不在内存中,需要通过IO操作文件。
字符集
字母:数字 符号------1字节 8bit
需要将除了字母以外的其他语言进行字符编码--->拆分和组合
拆分和组合的规则--所谓的字符编码
常见的字符编码
- ASCII
- ISO-8859-1
- GB2312 GB18030 GBK BIG(繁体字)
- Unicode
- UTF-8
缓冲流
在管道内增加缓冲的数据
让我们使用流读取的文字更加的流畅
BufferedInputStream/BufferOutputStream
BufferedReader/BufferedWriter
BufferedReader
//每次读取一行
String value = readLine();
BufferedWriter
write(String)
//光标移到下一行
newLine()
对象流
ObjectInputStream/ObjectOutputStream
对象序列化/反序列化
对象的序列化:将一个完整的对象拆分成字节碎片,记录在文件中
对象的反序列化:将文件记录的对象,反过来组合成一个完整的对象
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
/*oos = new ObjectOutputStream(new FileOutputStream(new File("D:"+ File.separator + "lili.txt"), true));
oos.writeObject(new Person("zhangsan", 80));
oos.flush();*/
ois = new ObjectInputStream(new FileInputStream("D:" + File.separator + "lili.txt"));
Person o = (Person) ois.readObject();
System.out.println(o.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (oos != null) {
oos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}