IO流
IO流:Input/Output Stream
流:指的是一串流动的数据,在数据在流中按照指定的方向进行流动,实现数据的读取,写入的功能
作用:实现两个设备之间数据的传递
File类:使用File类只能做关于文件的操作,获取属性,创建文件,修改文件,移动文件等操作,但不包含读取文件中的内容,如果需要读取,修改文件中的内容,此时就需要使用IO流
设备:
能输入或者输出数据的都可以称为设备
例如:硬盘(磁盘),内存,键盘,文件,网络,控制台
网络:当前主机外的网上资源
IO流的分类:
按照传输数据的单位分:字节流,字符流
按照数据传输的方向分:输入流,输出流
字节流的两个父类:
字节输入流:InputStream
字节输出流:OutputStream
字符流的两个父类:
字符读入流:Reader
字符写出流:Writer
IO流使用注意事项:
四大父类流都是抽象类,不能实例化对象,因此需要借助他们的子类实现数据的读写
流一旦实例化完成,将只会建立一个与此文件的连接,这个连接会持有这个文件,如果这个连接不断,此时这个文件就是一个被使用中的状态,此时将无法对这个文件进行其他的操作,例如删除
一个流在使用结束之后,一定要进行流的关闭!!!
文件操作:
相对路径和绝对路径:
路径:用来描述一个文件所在的地址,用来定位一个文件的,可以分为绝对路径和相对路径
绝对路径:从磁盘的根目录开始,一层层地向下查找,直到找到这个文件
相对路径:找到一个参照物,相对于这个参照物的路径
对比:
优点 | 缺点 | 举例 | |
---|---|---|---|
绝对路径 | 用来表示一个文件的地址,只要这个使用方法还在当前的磁盘上,一定可以找到这个文件 | 一旦更换一个文件系统,此时这个路径表示的文件将无法找到 | D:\SBigData\学习资料 |
相对路径 | 只要二者的相对位置保持不变,无论在哪一个文件系统中,都可以找到这个文件 | 只要两者的相对位置发生了改变,这个文件就无法被访问到 |
分隔符:
在描述路径的字符串中,由两种分隔符是比较常见的,目录分隔符和路径分隔符
目录分隔符:在Windows中使用“\”作为目录分隔符,在 Linux,Unix等非Windows操作系统中使用“/”作为目录分隔符
路径分隔符:在windows中使用“;”作为路径分隔符,在非windows的操作系统中使用“:”作为路径分隔符
获取分隔符的方法:
方法 | 描述 |
---|---|
File.separator() | 获取一个目录分隔符字符串 |
File.separatorChar() | 获取一个目录分隔符字符 |
File.pathSeparator() | 获取一个路径分隔符字符串 |
File.pathSeparatorChar() | 获取一个路劲分隔符字符 |
File类:
File是Java.io中的一个类,是对磁盘上的某一个文件,文件夹(目录)的描述,所谓的文件操作其实都是需要使用这个类来完成的
File类的构造方法:
参数 | 描述 |
---|---|
String pathName | 通过一个路径字符串,描述一个指定路径下的文件 |
String parent,String child | 将parent和child拼接到一起,形成一个新的路径 |
File parent,String child | 将parent所描述的路径和child拼接到一起 |
package bk.javase.p604.IO;
import java.io.File;
public class demo {
public static void main(String[] args){
//1.File(String pathName)
//如果这个路径下的文件不存在,不影响File对象的实例化
File file = new File("D:\\SBigData\\学习资料");
System.out.println(file.exists());
//2.File(String parent,String child)
//在这个构造方法中,会将parent和child合并在一起
File file1 = new File("D:\\SBigData\\学习资料","day06_数组相关\\day06_数组相关");
System.out.println(file1);
System.out.println(file1.exists());
//3.File(String parent,String child)
//在构造方法中,将parent的路径和child进行拼接,得到一个新的路径
File desktop = new File("C:\\Users\\16326\\Desktop");
File file2 = new File(desktop,"dayHomework");
System.out.println(file2);
System.out.println(file2.exists());
}
}
File类的常用方法:
文件属性的获取方法:
package bk.javase.p604.IO;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
测试常用类的基本方法
*/
public class Demo1 {
public static void main(String[] args){
//实例化一个对象
File file = new File("C:\\Users\\16326\\Desktop\\dayHomework","QQ截图20210525170125.png");
//1.判断一个File对象指向的路径上是否有文件或者文件夹
System.out.println("exists = "+file.exists());
//2.判断一个File对象指向的路径上是否是一个文件
System.out.println("isFile = "+file.isFile());
//3.判断一个File对象指向的路径上是否是一个目录
System.out.println("isDirectory = "+file.isDirectory());
//4.获取一个文件的大小
System.out.println("length = "+file.length());
//5.判断一个文件(目录)是否是隐藏的
System.out.println("hidden = "+file.isHidden());
//6.判断文件的权限
System.out.println("read = " + file.canRead());
System.out.println("write = "+file.canWrite());
System.out.println("execute = "+file.canExecute());
//7.获取文件的名字
System.out.println("name = "+file.getName());
//8.获取文件的路径
System.out.println("path = "+file.getPath());
System.out.println("absolutePath = "+file.getAbsolutePath());
//9.获取父级文件夹的路径(字符串)
System.out.println("parent = "+file.getParent());
//10.获取父级文件夹(File对象)
System.out.println("parentFile = "+file.getParentFile());
//11.获取上次修改的时间(时间戳)--最后修改的时间,不是查看时间
long lastTime = file.lastModified();
System.out.println(lastTime);
Date date= new Date(lastTime);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strData = sdf.format(date);
System.out.println(strData);
}
}
文件操作:
package bk.javase.p604;
import java.io.File;
import java.io.IOException;
/*
文件操作方法
*/
public class Demo2 {
public static void main(String[] args) {
//1.实例化一个File文件对象
File file = new File("C:\\Users\\16326\\Desktop\\dayHomework\\就业老师联系电话");
/*
2.1创建文件
1.必须保证文件以外的路径都是存在的
2.createNewFile只能用于创建文件
*/
try {
boolean flag = file.createNewFile();
System.out.println(flag);
} catch (IOException e) {
e.printStackTrace();
}
// 2.2创建文件夹(只能创建以及文件夹)
boolean flag2 = file.mkdir();
System.out.println(flag2);
//2.3创建文件夹(可以创建任何一级上的文件夹)
boolean flag3 = file.mkdirs();
System.out.println(flag3);
//2.4删除文件夹,可以删除文件夹,也可以删除目录
// 谨慎使用,这个方法会直接从磁盘上删除,不经过回收站,没有撤销的余地
boolean flag4 = file.delete();
System.out.println(flag4);
//2.5文件的重命名
File src = new File("C:\\Users\\16326\\Desktop\\dayHomework\\就业老师联系电话.png");
System.out.println(file.renameTo(src));
//2.6借助重命名实现文件移动
File from = new File("C:\\Users\\16326\\Desktop\\dayHomework\\单词.md");
File to = new File("C:\\Users\\16326\\Desktop\\dayHomework\\知识点\\单词.md");
System.out.println(from.renameTo(to));
}
}
子文件的获取:
package bk.javase.p604.IO;
import java.io.File;
public class Demo3 {
public static void main(String[] args){
//1.先实例化一个File对象
File file = new File("C:\\Users\\16326\\Desktop");
//1.列举一个目录下的所有子文件的名字
String[] names = file.list();
for (String s : names){
System.out.println(s);
}
System.out.println("++++++++++++++++++++++++++++++++++");
//2.列举一个目录下所有子文件的名字
String[] name = file.list((FatherFile,childName)->{
return childName.endsWith(".lnk");
});
for (String n : name){
System.out.println(n);
}
//3.列举一个目录下所以子文件
File[] files = file.listFiles();
for (File f : files){
System.out.println(f);
}
}
}
基础IO流:
建立程序和文件的连接:实质上就是建立程序与文件之间连接的管道,实现数据在这个管道中进行流动、管道的类型分为:字节输入流,字节输出流,字符输入流,字符输出流
标准流程:
package bk.javase.p604.IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/*
建立文件与程序之间的连接
*/
public class TestIO {
public static void main(String[] args){
//在外面声明变量
InputStream inputStream = null;
try {
//实例化一个FileInputStream对象,向上转型为InputStream类型
//这个实例化如果完成,就会建立程序与文件之间的连接
//建立好之后,数据就可以从文件中流动到程序中
//注意:一,数据流动到程序中,并不意味着文件中没有数据了
//二:如果只写文件的相对路径,不写绝对路径,默认路径是当前的工程
//FileNotFountException:(系统找不到指定的路径)
inputStream = new FileInputStream("C:\\Users\\16326\\Desktop\\dayHomework\\知识点\\单词.md");
//数据的读取操作
//在数据读取的过程中,也会出现IOException异常,一旦出现异常,后面的程序就直接运行不了
//直接执行catch语句了
//流的关闭。不能放到try里面,需要放到finally中
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
//流的使用结束之后,一定要进行关闭
if (inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
try结构的特殊使用:
在jdk1.7之后可以在try后面添加(),将AutoClosable接口实现类的对象,实例化放到小括号中完成,此时,在try结构执行结束的时候,会自动的调用AutoClosable接口实现类中的close方法,进行流的关闭,这样写的流的建立比较简单,也是我们后面最主要使用的方式
package bk.javase.p604.IO;
import java.io.*;
/*
常用的IO流的创建方式
*/
public class Demo4 {
public static void main(String[] args){
/*
try结构的特殊用法:try()
将AutoClosable接口的实现类对象的实例化放到小括号中
此时在离开了try结构的之后,会自动的对这个类进行close方法的调用
*/
try(InputStream inputStream = new FileInputStream("C:\\Users\\16326\\Desktop\\dayHomework\\知识点\\单词.md")) {
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new File("C:\\Users\\16326\\Desktop\\dayHomework\\知识点\\单词.md").delete());;
}
}
InputStream
inputStream简介:
这是一个字节输入流,从方向上来说,是一个输入流,数据是从文件中流动到程序中(数据从其他设备到内存),是为了读取文件中的数据。从数据单位上来说,这个流中流动的数据直接是字节的形式
文件读取:
1.一次读取一个字节:
read():一个字节一个字节的读,每次读出一个字节
package bk.javase.p604.IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/*
一字节一字节的进行读取
*/
public class TestInputStream {
public static void main(String[] args){
//1.建立程序和文件之间的连接,用来读取这个文件
try ( InputStream input = new FileInputStream("C:\\TestIO\\hello.txt")){
//2.先声明一个变量,read方法的返回值,就是读取到的数据
//注意:返回-1,默认数据读完了
int num = 0;
//3.读取并显示内容
while((num = input.read()) != -1){
System.out.println((char)num);
}
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println((char)num);
// num = input.read();
// System.out.println(num);//当返回-1时,默认已经读完了
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.一次读取多个字节(推荐):
read(数组):一次可以读出多个字节,数组的作用:每次会将读出的字节临时存放到这个数组中
package bk.javase.p604.IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/*
一次读取多个字节
*/
public class TestIOStream2 {
public static void main(String[] args) {
//1.建立程序与文件之间的连接,用来读取这个文件
try (InputStream inputStream = new FileInputStream("C:\\TestIO\\hello.txt")) {
//2.创建一个字节数组,用来读取数据
//创建临时数组
/*
数组是临时存放数据的地方,我们会将读取到的字符放到临时数组中,数组的大小决定了我们一次可以读到的字符个数
一般这个数组的大小<=18KB
返回值为-1的时候表示这个数组已经读完了
*/
byte[] array = new byte[3];
//3.声明一个整形变量,用来记录每次读取到了多少字节的数据
int num = 0;
//5.使用循环读取数据
while((num = inputStream.read(array)) != -1){
System.out.println(new String(array,0,num));
}
// //4.直接读取数据
// num = inputStream.read(array);
// System.out.println(new String(array, 0, num));
// num = inputStream.read(array);
// System.out.println(new String(array, 0, num));
// num = inputStream.read(array);
// System.out.println(new String(array, 0, num));
// num = inputStream.read(array);
// System.out.println(new String(array, 0, num));
// num = inputStream.read(array);
// System.out.println(new String(array, 0, num));
// //转部分字符到字符串,第二个参数是指定的下标,第三个参数是字符数量
// //将读取到的字节数组中的数据转换成字符串输出
// //为了去除最后一次进行读取数据的时候,上次读取残留的问题
// //最后一次读取到的数据只有指定部分是我们需要的数据
num = inputStream.read(array);
System.out.println(new String(array,0,num));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.一次读取全部的字节:
可以通过available()方法获取全部的字节数
package bk.javase.p604.IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/*
一次读取全部的字节
*/
public class TestInputStream3 {
public static void main(String[] args){
//1.建立程序与文件之间的连接,用来读取这个数据
try(InputStream inputStream = new FileInputStream("C:\\TestIO\\hello.txt");) {
//需要有一个字节数组用来存储数据
//注意:这种方式适合文件的字节数比较小的时候,大概是几kb之内
int num = inputStream.available(); //获取文件中的字节个数
//2.读
byte[] bytes = new byte[num];
inputStream.read(bytes);
System.out.println(new String(bytes));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStream
OutPutStream简介:
字节输出流,从方向上来看是一个输出流,数据从程序中流动到文件中(数据从内存中到其他设备),实现文件的写操作,从流中流动的数据单位来分,是一个字节流,流中流动的数据直接是字节的形式
package bk.javase.p604.IO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/*
字节流写出数据
*/
public class TestOutStream1 {
public static void main(String[] args){
//1.实例化一个管道,连接文件和程序
//对于FileOutputStream来说,如果目标文件不存在,则会自动的创键,如果存在,会将原来的内容覆盖
//当无法创建这个文件的时候(父级目录不存在),创建会失败,会触发FileNotFoundException
//OutputStream outputStream = new FileOutputStream("C:\TestIO\");
//文件的续写,FileWriter(String file,boolean value)
//当vlaue为true时,不会将原来的内容进行覆盖,会接着写
try(OutputStream outputStream = new FileOutputStream("C:\\TestIO\\world.txt")) {
//2.准备需要写入到这个文件中的数据
String message = "你好,huber";
//3.将数据写入到输出流中,有输出流写入到文件中
//将字符串转成字节数组
outputStream.write(message.getBytes());
//冲刷缓冲区,会将缓冲区中的数据强制流动到文件中
//在流关闭的时候,会自动地调用
//注意当我们进行循环写入操作的时候,最好通过flush()方法刷新
outputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Reader
Reader简介:
字符输入流,从方向上来说,是一个输入流,数据是从文件中流动到程序中(数据从其他设备到内存),是为了读取文件中的数据的,从数据单位上来说,这个流中流动的数据以字节为单位的,不同的是在传输过程中加入了编码的操作,让我们的操作更加方便
读取文件
package bk.javase.p604.IO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class TestReader {
public static void main(String[] args){
//读取过程与字节输入流完全相同,只需要将使用得到的类型换一下即可
try(Reader reader = new FileReader("C:\\TestIO\\hello.txt");) {
//1.实例化一个字符数组
char[] array = new char[100];
//2.声明一个变量,用来记录每次读取到了多少个数据
int length = 0;
//3.循环读取数据
while((length = reader.read(array)) != -1){
String str = new String(array,0,length);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writer
Writer简介:
字符输出流。从方向上来分,是一个输出流,数据从程序中流动到文件中(数据从内存到其他设备),实现文件的写操作,从流中流动的数据单位来分,是一个字符流,流中流动的数据是以字节为单位,不同的是在传输过程中,加入了编码的操作,让我们的操作更加方便
写出文件:
package bk.javase.p604.IO;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class TestWriter {
public static void main(String[] args) {
//1.实例化相关的类
//当参数为true时,不会覆盖,会在后面追加
try (Writer writer = new FileWriter("C:\\TestIO\\hello.txt", true)) {
//2.将数据写入到输出流中
writer.write("王者荣耀是真的好玩");
//3.冲刷缓冲区
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}