I/O流
1、什么是I/O流
I:input输入
O:output输出
输入/输出流(读写文件/数据)
2、I/O分类
1、按照数据的处理格式
- 字节流:处理二进制数据(图片/音频/视频/…)
- InputStream:字节输入流
- OutputStream:字节输出流
- 字符流:处理字符(txt/…)
- Reader:字符输入流
- Writer:字符输出流
2、按照数据的流向
输入流
输出流
注意:如何判断使用输入流还是输出流?
以程序为参照物,观察数据的流向,如果数据流向程序,使用输入流,如果数据从程序流出,使用输出流
3、字节流
1、字节输入流
- InputStream :抽象类
- FileInputStream :操作文件(重点)
- BufferedInputStream:字节缓冲流( 了解)
1、InputStream常用方法
- int read()读一个(效率低)
- int read(byte[] b)读多个(提高效率)
- int read(byte[] b,int off,int len)
- void close()关闭
FileInputStream读文件的步骤
1、找到目标文件(路径)
2、和目标文件建立数据通道(流)
3、读文件 read()
4、关闭通道(释放资源)
BufferedInputStream读文件的步骤
1、找到目标文件(路径)
2、和目标文件建立数据通道(流)
3、建立缓冲流数据通道
4、使用缓冲流读数据
5、关闭缓冲通道(释放资源)
public static void main(String[] args) {
//1、读取文件
//(1)找到目标文件
String path = "C:\\Users\\贺天\\Desktop\\a.txt";
FileInputStream in = null;//in是局部变量,局部是没有初始值,必须要给初始值
try {
//(2)和目标文件建立输入流通道
in = new FileInputStream(path);
//(3)读取文件内容
//1、read():读一个,读取的内容是-1,代表读完了
int content=0;//定义变量,保存赢取内容
//循环
//(content=inread()):读取一个字节,保存到变量content中
while((content = in.read())!=-1){//如果读取的内容不是-1
//没有读完
System.out.print((char)content);//打印读取内容
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
//(4)关闭通道
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileNotFundException:找不到文件异常
字节流去读取字符:有可能出现乱码
//read(byte b)
//读取文件内容
String path = "C:\\Users\\贺天\\Desktop\\a.txt";
FileInputStream in = null;//in是局部变量,局部是没有初始值,必须要给初始值
try {
//(2)和目标文件建立输入流通道
in = new FileInputStream(path);
//缓冲数组
byte[] buf = new byte[1024*8];//默认8字节
int length = 0;//定义变量,保存读取长度
//循环
//(length = in.read(buf)):读取内容保存到缓冲数buf中,length代码读取长度
while((length = in.read(buf))!=-1){//如果读取的长度为-1,读完了
//没有读完
System.out.println(Arrays.toString(buf));
}
catch (Exception e) {
e.printStackTrace();
}finally {
try {
//(4)关闭通道
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读文件:缓冲字节输入流(仅做了解,实际用不上)
//注意:缓冲流不具备读写能力,要依赖具备读写能力的流
public static void main(String[] args){
long startTime = System.currentTimeMillis();
//(1)找目标文件
String path ="\\\";
//(2)建立数据通道
fileInputStream in = null;
try{
in = new FileInputStream(path);
//(3)创建缓冲流通道
BufferedInputStream bufIn = new BufferedInputStream(in);
//(4)使用缓冲流读数据
byte[] buf = new byte[1024 * 8];
int length = 0;//定义变量,保存读取长度
while((length = bufIn.read(buf))!=-1){
System.out.println(Arrays.toString(buf));
}
}catch(Exception e){
e.printStackTrace();
}finally{
//(5)释放资源
in.close();
}
}
2、字节输出流
- OutputStream :抽象类
- FileOutputStream :
1、FileOutputStream常用方法
write(int b):写一个
write(byte[] b):写多个
write(byte[] b,int off,int len)
close():关闭
2、写数据步骤:
1、找到目标文件
2、建立数据通道
3、使用通道写数据
4、关闭通道
//写数据 write(int b)
public static void test1(){
//(1)找到目标文件
String path = "C:\Users\贺天\Desktop\b.txt";
try{
//(2)建立数据通道
FileOutputStream out = new FileOutputStream(path,true);//true:拼接;加false:覆盖(默认)
//(3)使用通道写数据
out.write("hello world".getBytes());//字符串转字节数组
}catch(Exception e){
e.printStackTrace();
}finally{
//(4)关闭通道
out.close();
}
}
注意:stream:字节/二进制
input:输入
output:输出
Buffered:缓冲
3、拷贝图片:边读边写
write(byte b[] ,int off,int len)
b:要写的数组
off:偏移量,从数组那个位置开始写(一般是0)
len:要读取的长度
注意:使用字节流去写字符要手动进行编码,然后再写
4、字符流
读写字符
字符流:字节流+编码/解码(字符流:直接去写字符)
编码:把能看懂的字符转换成看不懂的二进制数据
解码:把看不懂的二进制数据转换成能看懂的字符
1、读数据
- Reader
- FileReader
- BufferedReader
- String readLine() 每次读一行,注意:不会读取换行操作
public static void main(String[])throws Exception{
//1、找到目标文件,建立数据通道
FileReader reader = new FileReader("\\");
//2、读取数据
//定义变量,保存读取内容
int content = 0;
//循环:不停地去读
while((content = reader.read())!=-1){
System.out.println((char)content);
}
//3关闭通道
reader.close();
}
使用缓冲数组(效率高)
public static void main(String[])throws Exception{
//1、找到目标文件,建立数据通道
FileReader reader = new FileReader("\\");
//2、读取数据
//定义缓冲数组
char[] buf = nwe char[1024*8];
//定义变量,保存每次读取长度
int length = 0;
//循环:不停地去读
while((length = reader.read())!=-1){
System.out.println(new String(buf,0,length);
}
//3关闭通道
reader.close();
}
//读数据,使用缓冲类
//注意:使用缓冲类不能直接读写数据
public static void main(String[] args)throws Exception{
//1、找到目标文件,建立数据通道
FileReader reader = new FileReader("\\");
//2、创建缓冲类
BufferedReader bufReader = new BufferedReader(reader);
//3、使用bufferedReader读取数据
//定义字符串,保存每次读取内容
String content = "";
//循环读取
while((content = bufReader.readLine())!=null){
System.out.print(content+"\r\n");//content:每次读取一行的数据,不再换行,需要手动加上换行
}
//4、关闭缓冲类,关闭数据通道
bufReader.close();
reader.close();
}
2、写数据
- Writer
- FileWriter
- BufferedWriter
//不用缓冲类写数据
public static void main(String[])throws Exception{
//1、找到目标文件,建立数据通道
FileWriter reader = new FileWriter("\\");
//2、使用通道写数据
writer.write("hello world,你好!");
//3关闭通道
reader.close();
}
//使用缓冲类写数据
public static void main(String[] args)throws Exception{
//1、找到目标文件,建立数据通道
FileWriter writer = new FileWriter("\\");
//2、创建缓冲类通道
BufferedWriter buf = new BufferedWriter(writer);
//3、使用通道写数据
bufferedWriter.write("hello world,你好!");
//4、关闭通道
bufferedWriter.close();
}
3、拷贝文件
public static void main(String[] args)throws Exception{
//1、找到目标文件,建立数据通道、创建缓冲通道
BufferedReader bufReader = new BufferedReader(new FileReader("\\"));
//2、和目标文件建立通道:输出
BufferedWriter bufWriter = new BufferedWriter(new FileWriter("\\"));
//3、循环
//定义变量保存读取内容
Sting consent = "";
while((consent =bufReader.readLine())!=null){
bufWriter.writer(consent+"\r\n");//换行方案一
//bufWriter.write(consent);
//bufWriter.newLine();//方案二
}
//4、关闭通道
bufReader.close();
bufWriter.close();
}
5、转换流
把字节流转换成字符流
(1)输入字节流转成字符流
public static void main(String[] args)throws Exception{
//(1)字节流
FileInputStream in = new FileInputStream("\\");
//(2)转字符流
InputStreamReader reader = new InputStreamReader(in);
//创建缓冲数组
char[] buf = new char[1024*8];
//定义变量保存每次读取长度
int length = 0 ;
//循环
while((length= reader.read(buf))!=null){
System.out.println(new String(buf,0,length));
}
reader.close();
}
(2)输出字节流转成字符流
public static void main(String[] args)throws Exception{
//(1)字节流
FileOutputStream out = new FileOutputStream("\\");
//(2)转字符流
InputStreamWriter writer = new OutputStreamReader(out);
writer.write("hello world");
//(3)关闭通道
writer.close();
}
6、对象流
读写java对象()
序列化:把java对象
反序列化:
public void Student() implements Serializable{
private int xh;
private String name;
private String sex;
}
1、把java对象写到文件中
序列化(活化)
public static void main(String[] args)throws Exception{
Student student = new Student();
student.setXh(120);
student.setName("小明");
student.setSex("男");
//写
//1、找到目标文件 ,建立通道
FileOutputStream out = FileOutputStream("student.txt");
//2、创建对象流
ObjectOutputStream objOut = new ObjectOutputStream(out);
//3写数据
objOut.writeObject(student);
//4、关闭数据通道
objOut,close();
}
2、从文件中读取java对象
反序列化(钝化)
public static void test2(){
//1、找到目标文件,建立数据通道
FileInputStream in = new FileInputStream("student.txt");
//2、创建对象流
ObjectInputStream objIn = new ObjectInputStream(in);
//3、读数据
Student student = (Student)objIn.readObject(student);
//4、关闭通道
objIn.close();
}
注意:创建对象会调用对应的构造函数?
反序列化时没有调用构造函数
问题:修改类中的成员后,反序列化失败:
serialVersionUID:根据类,属性方法…计算得来的值
通过对象流序列化对象时,会把UID写入到文件中
修改类中的属性uid的值就会发生改变
解决:1、重新序列化
2、在实体类中把serialVersionUID写死
private static final long serialVersionUID = 1L;
7、File类
File类:文件(文档/目录)类(封装文件 )
1、构造函数
File(String pathname)
public static void test1(){
//(1)File(String pathname):直接传文件路径
File file = new File("\\");
}
File (String parent,String child)
public static void test1(){
//(1)File (String parent,String child)
//parent:父路径 child:文件名
File file = new File("\\","b.txt");
}
File(File parent,String child)
public static void test1(){
//(1)File(File parent,String child)
//parent:父路径对应的File对象 child:文件名
File file = new File(new File("\\"),"b.txt");
}
2、常用方法
1、boolean exists(),判断文件是否存在
File file1 = new File("\\c.txt");
//判断文件是否存在file1.exists()
System.out.println("file存在吗?"+file1.exists());
//判断是不是文件isFile()
System.out.println("file是文件吗"+file1.isFile());
//判断是不是文件夹isDirectory()
System.out.println("file是文件夹吗?"+file1.isDirectory())
if(!file1.exists()){//判断文件是否存在
if(file1.isFile()){
//创建文件
file1.createNewFile();
}
//获取操作
String name = file1.getName();//获取文件路径
System.out.println("name ="+name);
String parent = file1.getParent();//获取文件名
System.out.println("Parent="+parent);
String path = file1.getPath();//获取完整的文件路径
System.out.println("path="+path);
}
//创建文件夹
public static void test3(){
//创建file对象
File file1 = new File("\\a");
//判断:是否存在
if(!file1.exists()){//如果不存在
//创建文件夹 mkdir():只能创建单级目录
file1.mkdir();
}
File file2 = new File("\\a\\b");
if(!file1.exists()){//如果不存在
//创建多级目录 mkdirs()
file1.mkdirs();
}
}
获取所有文件
String[] list()
public static void test3(){
//创建File对象
File file1 = new File("\\");
//获取目录中的所有文件String[] list()
String[] list = file.list();
for(String name :list){
System.out.println(name);
}
}
File[] listFiles()获取目录中所有文件对象
//获取目录中所有文件对象:File[] listFiles()
File[] files = file.listFiles();
for(File file1 : files){
System.out.println(file1);
}
String[] list(FilenameFilter filter)获取目录中过滤后的文件
//获取目录中过滤后的所有文件String[] list(FilenameFilter filter)
//FilenameFilter filter:文件名过滤器
String[] list1 = file.list(new filenameFilter({
public boolean accept(File dir,String name){
//过滤代码:只要java源文件(以.java结尾的文件)
//name:
if(name.endsWith(".java")){//判断是不是java源文件
//是
return true;//要
}
return false;//不要
}
}));
File[] listFiles(FilenameFilter filter)获取目录中过滤后的文件对象
File[] list2 = file.listFiles(new FilenameFilter(){
public boolean accept(File dir,String name){
//只要图片
if(name.endWith(".png")||name.endsWith(".jpg")){
return true;//要
}
return false;//不要
}
});
删除
public static void test5(){
//创建File对象
File file = new File("\\a.txt");
//删除文件
file.delete();//删除文件或空的文件夹
//删除文件夹
File file2 = new("\\a");
file2.delete();
}
使用File对象进行I/O流操作
public static void test6(){
//1 找到目标对象
File file = new File("\\a.txt");
//2、建立数据通道
FileReader reader = new FileReader(file);
//3、读数据
char[] buf = new char[1024*8];
int length = 0;
while((length = reader.read(buf))!=-1){
System.out.println(new String(buf,0,length));
}
//4、关闭通道
reader.close();
}