Java IO流

File

文件类概述和构造方法

File:它是文件和目录路径名的抽象示

  • 文件和目录是可以通过File封装成对象的
  • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.
  • 将来是要通过具体的操作把这个路径的内容转换为具体存在的

File类创建功能

 public boolean createNewFile():

                        如果文件不存在,就创建文件,并返回true

                        如果文件存在,就不创建文件,并返回false

public boolean mkdir():

                        如果目录不存在,就创建目录,并返回true

                        如果目录存在,就不创建目录,并返回false

(creatNewFile和mkdir的区别是一个是创建文件,一个是创建目录)

public boolean mkdirs():

                        如果目录不存在,就创建目录,并返回true

                        如果目录存在,就不创建目录,并返回false

(mkdir和mkdirs的区别是一个是创建单个目录,一个可以创建多级目录)


创建的是文件还是目录,不是通过文件路径名字来看的。

比如如果我们这样子

得到的不是txt文件 而是名为“javase.txt”的目录

 所以我们要看方法来判断创建的是文件还是目录

再次总结:creatNewFile()是创建文件,mkdir()和mkdirs()是创建目录。 

File类删除功能

绝对路径和相对路径的区别

●绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如: E:\itcast\Vjava.txt

●相对路径:必须使用取自其他路径名的信息进行解释。例如: myFile\Vjava.txt

删除目录时的注意事项:
●如果一个目录中有内容(目录, 文件),不能直接删除。应该先删除目录中的内容,最后才能删除目录

File类判断和获取功能

import java.io.File;
import java.io.IOException;

public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        //创建一个File对象
        File f = new File("File\\java.txt");
        //f.createNewFile();
//        public boolean isDirectory(): 测试此抽象路径名表示的File是否为目录
//        public boolean isFile(): 测试此抽象路径名表示的File是否为文件
//        public boolean exists(): 测试此抽象路径名表示的File是否存在
        System.out.println(f.isDirectory());
        System.out.println(f.isFile());
        System.out.println(f.exists());
        System.out.println("--------");

//        public String getAbSplutePath(): 返回此抽象路径名的绝对路径名字符串
//        public String getPath(): 将此抽象路径名转换为路径名字符串
//        public String getName():返回由此抽象路径名表示的文件或目录的名称
        System.out.println(f.getAbsolutePath());
        System.out.println(f.getPath());
        System.out.println(f.getName());
        System.out.println("--------");

//        public String[] list(): 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
//        public File[] listFiles(): 返回此抽象路径名表示的目录中的文件和目录的File对象数组
        File f2 = new File("E:\\itcast");
        String[] strArray = f2.list();
        for(String str : strArray)
        {
            System.out.println(str);
        }
        System.out.println("--------");

        File[] fileArray = f2.listFiles();
        for(File file : fileArray)
        {
            System.out.println(file);
        }
        System.out.println("--------");

        //得到绝对路径的意义是可以调用File方法进行操作
        for(File file : fileArray)
        {
            if(file.isFile())
            System.out.println(file);
        }

    }
}

得到结果

false
true
true
--------
E:\untitled2\File\java.txt
File\java.txt
java.txt
--------
java.txt
JavaSE
javase.txt
JavaWEB
--------
E:\itcast\java.txt
E:\itcast\JavaSE
E:\itcast\javase.txt
E:\itcast\JavaWEB
--------
E:\itcast\java.txt

字节流

IO流概述和分类

I0流分类:

按照数据的流向
        输入流:读数据
        输出流:写数据

按照数据类型来分
        字节流
                字节输入流,字节输出流
        字符流
                字符输入流,字符输出流
一般来说, 我们说IO流的分类是按照数据类型来分的

如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流
否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流。

字节流写数据

字节流写数据的三种方式 

一个利用getBytes实现的输入字符串的简便方法:

文件输出流对象.write("我是要输入的字符串".getBytes());

1:字节流写数据如何实现换行呢? 

        写完数据后加换行符号(不同系统换行符不同)       

                window: \r\n 

                Linux: \n

                mac: \r


2:字节流写数据如何实现追加写入呢?

        public FileOutputStream (String. name, boolean append)
        在创建文件输出流时用该方法指定追加写入
        如果第二个参数为true,则字节将写入文件的末尾而不是开头

字节流写数据加异常处理 

 finally :在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源

    特点:被finally控制的语句一定会执行,除非JVM退出

  格式:

   

 如果文件路径不存在为null,则无需close。

字节流读数据(一次读一个字节数据)

用循环输出文件数据直至末尾读完文件

 首次用read函数读数据返回的是字符所对应的ascall码,所以是int类型,我们如果想原样输出,就在输出时加一个char强转。

另外,注意输出System.out.print()不要加ln哦,要换行的地方循环会识别到,无需手动换行。

当文件都到末尾时,读到空返回的是null。

所以代码是这样子的

int by;
while(by=file.read()!=-1){
    System.out.print((char)by);
}

字节流复制图片

思路:
①根据数据源创建字节输入流对象
②根据目的地创建字节输出流对象
③读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
④释放资源

字节缓冲流

 BufferOutputStream:  该类实现缓冲输出流。通过设置这样的输出流, 应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用

BufferedInputStream:  创建BufferedInputStream将创建一 个内部缓冲区数组。 当从流中读取或跳过字节时, 内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节

构造方法:(注意:参数类型为字节流哦)

●字节缓冲输出流: BufferedOutputStream(OutputStream out)
●字节缓冲输入流: BufferedInputStream(InputStreamin) 


为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?

●字节缓冲流仅仅提供缓冲区 而真正的读写数据还得依靠基本的字节流对象进行操作

ps:不要因为字节缓冲流中有个缓字就以为它比普通字节流慢!!因为字节缓冲流可以一次内部缓冲很多内容,所以它是更快的!!faster!!在后面的传输视频处就可以体现字节缓存流的优越性

通过实操体现字节缓存流的优越性

测试得到的结果

 四种方式实现复制视频,并记录每种方式复制视频的时间
        1:基本字节流一次读写-一个字节            共耗时:285557毫秒
        2:基本字节流一次读写一个字节数组          共耗时:413毫秒
        3:字节缓冲流一次读写一 个字节            共耗时:2693毫秒
        4:字节缓冲流一次读写一 个字节数组         共耗时:124毫秒

import java.io.*;

/*
    //待复制视频地址:C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
    思路:
        1.根据数据源创建字节输入流对象
        2.根据目的地创建字节输出流对象
        3.读写数据,复制视频
        4.释放资源

    四种方式实现复制视频,并记录每种方式复制视频的时间
        1:基本字节流一次读写-一个字节            共耗时:285557毫秒
        2:基本字节流一次读写一个字节数组          共耗时:413毫秒
        3:字节缓冲流一次读写一 个字节            共耗时:2693毫秒
        4:字节缓冲流一次读写一 个字节数组         共耗时:124毫秒
 */
public class FileDemo6 {
    public static void main(String[] args) throws IOException {
        //记录开始时间
        long startTime = System.currentTimeMillis();

        //复制视频
//        method1();
//        method2();
//        method3();
        method4();

        //记录结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("共耗时:"+(endTime-startTime)+"毫秒");
    }

    //基本字节流一次读写-一个字节
    public static void method1() throws IOException {
        //C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
        FileInputStream fis = new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4");
        FileOutputStream fos = new FileOutputStream("E:\\untitled2\\视频.mp4");

        int by;
        while((by=fis.read())!=-1){
            fos.write(by);
        }

        fos.close();
        fis.close();
    }

    //基本字节流一次读写一个字节数组
    public static void method2() throws IOException {
        //C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
        FileInputStream fis = new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4");
        FileOutputStream fos = new FileOutputStream("E:\\untitled2\\视频.mp4");

        byte[] bys = new byte[1024];
        int len;
        while((len=fis.read(bys))!=-1){
            fos.write(bys,0,len);
        }

        fos.close();
        fis.close();
    }

    //字节缓冲流一次读写一个字节
    public static void method3() throws IOException {
        //C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\untitled2\\视频.mp4"));

        int by;
        while((by=bis.read())!=-1){
            bos.write(by);
        }

        bos.close();
        bis.close();
    }

    //字节缓冲流一次读写一 个字节数组
    public static void method4() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\untitled2\\视频.mp4"));

        byte[] bys = new byte[1024];
        int len;
        while((len= bis.read(bys))!=-1){
            bos.write(bys,0,len);
        }

        bis.close();
        bos.close();
    }
}

字符流(字符流的底层还是字节流)

编码表 

按照某种规则,将字符存储到计算机中,称为编码

反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码

ps:按照A编码存储,必须按照A编码解析,才能显示正确的文本符号,否则就会导致乱码现象

常见字符集:ASCll字符集,GBXXX字符集,Unicode字符集

常见编码表:GBK(最常用中文码表),GB18030(最新中文码表),UTF-8编码

【这里与字节流的区别就是字节流是读写字节(byte或byte[ ])数据,而字符流是读写字符(char或char[ ])数据 】

字符流中的编码解码

 注意:InputStreamReader和OutputStreamWrite所传的参数是FileInputStream和FileOutputStream哦!

import java.io.*;

public class FileDemo7 {
    public static void main(String[] args) throws IOException {
        //默认字符集写入,”中国“
//        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\untitled2\\ows.txt"));
        //指定GBK字符集写入 ,”�й�“
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\untitled2\\ows.txt"),"GBK");
        osw.write("中国");
        osw.close();
        //默认字符集读出
//        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\ows.txt"));
        //指定GBK字符集读出
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\ows.txt"),"GBK");

        //一次读取一个字符数据
        int ch;
        while((ch=isr.read())!=-1){
            System.out.print((char)ch);
        }

        isr.close();//不要忘了关闭噢
    }
}

字符流写数据的5种方式

void flush():刷新流,让数据从缓冲区出来

void close():关闭流,先刷新

 字符流读数据的2种方式

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileDemo8 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\File\\src\\aba.txt"));

        /*
        //一次读一个字符数据
        int ch;
        while((ch=isr.read())!=-1){
            System.out.print((char)ch);
        }
         */

        //一次读一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while((len=isr.read(chs))!=-1){
            System.out.print(new String(chs,0,len));
        }
        isr.close();
    }
}

注意,一次输入一个字符数组数据的方法是

char[] chs = new char[1024];
int len;
while((len=isr.read(chs))!=-1){
     System.out.print(new String(chs,0,len));
}

先设置一个字符数组,令其容量为1024,再设置一个整型变量len,

输出的地方,要将读出的数据用String函数转为字符型输出。

在上面实操中会发现,转换流的名字很长很不方便,所以转化流提供了对应便捷子类,它们继承了 转换流,也就是继承了他们的读写方法。

字符流对应的也有字符缓冲流

 它的使用方法和字节缓冲流差不多,但是也有它的特有功能哦!

 

 

 

特殊操作流

标准输入输出流

 

打印流

 

 对象序列化流

 

 被序列化的对象必须实现Serializeble接口!!,但无需重写任何方法。

import java.io.*;

public class FileDemo9 {
    public static void main(String[] args) throws IOException {
        //ObjectOutputStream(OutputStream):创建一个写入指定的OutputStream的ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\untitled2\\oos.txt"));
        //创建对象
        Student s = new Student("AK刘璋","20");
        //void writeObject(Object obj):将指定的对象写入ObjectOutputStream
        oos.writeObject(s);
        //释放资源
        oos.close();
    }
}

序列的反序列化流

 

import java.io.*;

public class FileDemo10 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\untitled2\\oos.txt"));

        //object readObject():从ObjectInputStream读取一个对象
        Object obj = ois.readObject();

        Student s= (Student) obj;
        System.out.println(s.getName()+","+s.getAge());

        ois.close();

    }
}

对象序列化流的三个问题!

用对象序列化流序列化了-一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?

会!抛出InvalidClassExpection异常


如果出问题了,如何解决呢?

给对象所属的类加一个serialVersionUID

                 private static final long serialVersionUID = 42L;


如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢? 

给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

Properties

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值