IO 的概述
- 概述:数据存到内存里面,程序运行结束之后,数据就没了,此时就需要把数据持久化存储起来
- input 输入(读)
- output输出(写)
- java.io 包中
File 类
-
file类:文件目录的抽象
-
文件路径的分隔符:
- windows:使用 \ 来进行路径分割,在java中使用 \\ 来分割, ; 来分割属性
- unix: / 分割路径, : 分割属性(要区分大小写)
- windows 不区分大小写
-
获取当前系统的分隔符:
- 分割属性的获取
//获取分割属性 String s = File.pathSeparator; System.out.println(s); char pathSeparatorChar = File.pathSeparatorChar; System.out.println(pathSeparatorChar); //获取斜线的分隔符 String separator = File.separator; System.out.println(separator);
-
获取路径和名称
-
相对路径
-
绝对路径:从根目录直接能进入的路径
//获取绝对路径 public String getAbsolutePath() { return fs.resolve(this); } //获取绝对路径的文件 public File getAbsoluteFile() {} //获取路径 public String getPath() {} //获取上级目录 public String getParent() {} //获取文件名称 public String getName() {}
-
如何创建一个文件,以及基本方法
- 构造器
//直接使用路径创建文件 public File(String pathname) {} //根据绝对路径创建文件 File file = new File("D:\\software\\hello.txt"); //先创建目录对象,然后再创建文件 File file1 = new File("D:\\software"); File file2 = new File(file1, "hello.txt"); //目录和文件分成两个参数传 File file3 = new File("D:\\software", "hello.text");
-
-
- 方法的学习
//判断是不是文件
public boolean isFile() {}
//判断是不是目录
public boolean isDirectory() {}
//删除文件
public boolean delete() {}
//判断文件或目录是否存在
public boolean exists() {}
//创建目录(存在就不创建)
public boolean mkdir() {}
//查看当前目录所有的文件
public String[] list() {}
//列出所有的文件对象
public File[] listFiles() {
//在目录里创建新的文件
File file4 = new File("D:\\software\\我爱祖国.mp3");
boolean newFile = file4.createNewFile();
//重命名
public boolean renameTo(File dest) {}
-
需求:列出指定目录中的所有文件,包括子文件夹中的所有文件及其子文件。递归
- 回顾递归(5的阶乘)
public static void main(String[] args) { //5的阶乘 int i = recursion(5); System.out.println(i); } public static int recursion(int a) { if (a == 1) { return 1; } else { return a * recursion(a - 1); } }
需求:列出指定目录中的所有文件,包括子文件夹中的所有文件及其子文件。递归
public static void main(String[] args) {
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day13");
fileRecursion(file);
}
public static void fileRecursion(File file){
//第一层级
File[] files = file.listFiles();
System.out.println(file.getAbsolutePath());
for (File f : files) {
if (f.isFile()){
System.out.println(" -"+f.getName());
}else {
fileRecursion(f);
}
}
需求:批量修改文件名
public static void main(String[] args) {
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day13\\day13_work");
File[] files = file.listFiles();
//需要修改的文件名字符串
String deleteName = "呃呃呃饿";
for (File f : files) {
//删选包含字符串的文件
if (f.getName().contains(deleteName)){
//使用replace进行更改名字
String replace = f.getName().replace(deleteName, "");
File renameFile = new File(file, replace);
f.renameTo(renameFile);
}
}
}
需求:打印指定目录下面 .java 结尾的资源
-
文件过滤器
FilenameFilter filenameFilter = new FilenameFilter() { //匿名内部类 @Override public boolean accept(File dir, String name) { return false; } };
-
需求实现
public static void main(String[] args) {
File file = new File("D:\\java\\29");
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(file,name).isFile() && name.endsWith(".java");
}
});
for (File f : files) {
System.out.println(f.getName());
}
}
IO流
-
I O 设备
- 输入:键盘,鼠标,麦克风
- 输出:显示器,打印机,音响
-
程序
- 输入:从磁盘到内存里
- 输出:从内存写数据到磁盘文件里
-
IO 流的分类
- 按流向(输入输出流)
- 按数据单位(字符字节流)
- 四大基本流:
- 字节输出流
- 字节输入流
- 字符输出流
- 字符输入流
- 注意:不管是什么流,最后都需要关闭资源。close,如果不关闭,磁盘文件一直被占用,不能够删除和修改。**
文件流
-
字节流
-
FileOutputStream 文件输出流
-
需求:读 C:\Users\wxj\Desktop\Study change life\day14\task02\任务作业.txt 文件,并且写入 wangxiaoj进去
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\任务作业.txt"); FileOutputStream stream = new FileOutputStream(file,true); stream.write("wangxiaoj".getBytes()); stream.close();
-
需求:C:\Users\wxj\Desktop\Study change life\day14\task02\任务作业.txt 读出来,在程序中打印
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\任务作业.txt"); //创建输入流 FileInputStream inputStream = new FileInputStream(file); //创建数组,设置每次最大读取空间 byte[] bytes = new byte[1024]; System.out.println(Arrays.toString(bytes)); int length = -1; //循环读,读一次只能读一个 while ((length = inputStream.read(bytes) )!= -1){ String str = new String(bytes, 0, length); System.out.println(str); } inputStream.close();
-
使用字节流实现文件的拷贝
public static void main(String[] args) throws IOException { //源文件 File srcFile = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\任务作业.txt"); //目标文件 File deskFile = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\拷贝目标文件.txt"); //源文件 输入流 FileInputStream srcInputStream = new FileInputStream(srcFile); //目标文件输出流 FileOutputStream deskOutputStream = new FileOutputStream(deskFile); byte[] buffer = new byte[10]; int length= -1;// 表示读了多少个字节, -1 表示还没有读完 //不等于 -1 表示还没有读完,就一直读下去 while ((length=srcInputStream.read(buffer))!=-1){ //把读到的写到目标文件里面 System.out.println(Arrays.toString(buffer)); deskOutputStream.write(buffer); } //关闭资源 srcInputStream.close(); deskOutputStream.close(); }
-
-
-
-
字符流
- FileReader (字符输入流)
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\任务作业.txt");
FileReader fileReader = new FileReader(file);
char[] chars = new char[12];
int length = -1;
while ((length = fileReader.read(chars))!= -1){
String s = String.valueOf(chars);
System.out.println(s);
}
fileReader.close();
- FileWrite (字符输出流)
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\wxj\\Desktop\\Study change life\\day14\\task02\\任务作业.txt");
FileWriter fileWriter = new FileWriter(file,true);、//没有加true则会覆盖之前的数据
fileWriter.write("这是新写进来的数据:376783487<br>");
fileWriter.close();
}
- 字节流和字符流的选择
- 二进制文件,图片,视频,音频,必须使用字节流
- 文本文件可以使用字符流
- 不清楚就全部使用字节流
-
fiush 刷新操作
- 计算机直接访问外部的磁盘文件,比直接操作内存会慢很多,可以设置一个缓冲区,写的时候先写到内存里面,达一个设定值才写到磁盘,减少与与磁盘的交互。
- 使用缓冲区的意义:
- 提高cpu的使用率
- 回滚写入的数据
- 操作系统使用 -1 来表示磁盘文件 结尾的标志
- io 是最影响程序性能的。缓冲区一般设置使用容量的整数倍,可以提高io性能
-
try()… catch() 资源自动释放
缓冲流
-
就是个包装流,目的是起到缓冲的作用,提升io性能
-
字节流的缓冲流
-
BufferedInputStream //缓冲输入流 BufferedOutputStream //缓冲输出流
-
-
字符流的缓冲流
- BufferedReader 字符输入缓冲流
- BufferedWriter 字符输出缓冲流
- 目的:习惯的去操作我们的byte char数组,先与内存进行交互,然后达到一定量之后,再去与磁盘交互。减少与磁盘交互的次数,提高性能。
字符编码
-
字符编码的发展流程
-
一开始只能认识数字 0 1,后来可以识别一些字母 (ASCII 美国标准信息交换码)
-
随着计算机的普及,很多国家将自己的字符引入计算机,汉字,一个字节的存储范围太小,两个字节来存储汉字
中文的二进制最高位规定为1 (负数) GB2312编码 —GBK
-
汉字在其他国家的编码问题,别人不认识,显示出乱码的情况。需要统一的编码, Unicode编码
-
-
常用的字符编码集
- ASCII:占一个字节,包含128个符号,不能表示汉字
- ISO-8859-1(lantin-1)占一个字节:收录西欧的语言,不能表示汉字
- GB-312(ANSI):占两个字节
- UTF-8:(存储汉字占三个字节)针对Unicode可变长字符编码,成为后来的通用编码(IETF要求所有的互联网协议都使用)
-
字符的编码以及解码(使用相同的编码规范)
- 编码:把字符串转换成byte数组
- 解码:把byte数组转换成字符串
合并流
SequenceInputStream
//创建两个流对象,以供合并
FileInputStream inputStream1 = new FileInputStream("D:\\D-Test\\aaaa.txt");
FileInputStream inputStream2 = new FileInputStream("D:\\D-Test\\bbbb.txt");
//调用合并流方法
SequenceInputStream sequenceInputStream = new SequenceInputStream(inputStream1,inputStream2);
//读取
byte[] bytes = new byte[1200];
int length = -1;
while ((length = sequenceInputStream.read(bytes))!=-1){
System.out.println(new String(bytes, 0, length));
}
sequenceInputStream.close();
对象流
-
序列化以及反序列化
- 序列化:把我们堆内存中的java对象数据,存储到磁盘中去,或者给其他的网络节点使用
- 反序列化:把磁盘文件的数据恢复成一个java对象的过程
-
为什么我们要使用序列化?
- 在分布式系统里面,数据的共享都需要使用序列化,(redis)
- 服务钝化:把不常用的对象存储到磁盘中去,节约内存开销
- 使用json传输的时候
-
做序列化和反序列化的要求:必须去实现java.io.Serializable 接口
- java中大多数的类都先实现了序列化接口的
-
对象流
- 序列化:ObjectInputStream
- 反序列化:ObjectOutputStream
public static void main(String[] args) throws IOException, ClassNotFoundException { File file = new File("D:\\D-Test\\obj.txt"); // writeObject(file); readObject(file); } //序列化操作 public static void writeObject(File file) throws IOException { ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file)); outputStream.writeObject(new Student("王曼七",24)); outputStream.close(); } //反序列化操作 public static void readObject(File file) throws IOException, ClassNotFoundException { ObjectInputStream InputStream = new ObjectInputStream(new FileInputStream(file)); Object o = InputStream.readObject(); Student stu = (Student)o; System.out.println(stu.getName() + "," + stu.getAge()); InputStream.close(); }
-
常见错误(NotSerializableException)实现序列化接口
-
序列化版本号的作用:相当于一个密码,引入了版本号,避免因为升级导致版本不兼容的问题。
打印流
-
PrintStream 字节流
-
PrintWrite 字符流
-
格式化输出
String name; int age; Object[] obj = {"王曼七",24}; //设置格式 String s = "姓名:%s ,年龄:%d "; System.out.printf(s,obj);//姓名:王曼七 ,年龄:24
Properties 加载配置文件
public static void main(String[] args) throws IOException {
//创建properties对象
Properties properties = new Properties();
//创建一个输入流
FileInputStream inputStream = new FileInputStream
("D:\\idea_workspace\\day16\\src\\cn\\xiaojun\\practice\\conf\\db.properties");
properties.load(inputStream);
System.out.printf("url:%s",properties.getProperty("url"));
System.out.printf("用户名:%s",properties.getProperty("username"));
System.out.printf("密码:%s",properties.getProperty("password"));
}
NIO
- jdk1.4开始提供,可以把一块磁盘文件映射到内存中去,java.nio
- 应用领域(云服务器中)
- jdk1.7提供了一个工具类---->files(操作文件类)
public static void main(String[] args) throws IOException {
Files.copy(Paths.get("D:\\D-Test\\obj.txt"),
new FileOutputStream("D:\\D-Test\\obj333.txt"));
}
- 与io的不同点
- Channels Buffers(通道缓冲区):通过通道和缓冲区
- 异步(Asynchronous):线程读取通道数据到缓冲区时,线程可以做其他事情
- 选择器(Selectors): 用来监听多个通道,单线程可以去监听多个数据通道