自学内容网 自学内容网

Java——IO流

目录

前言:

IO流的体系总览

一、 字节流:

1.1:写数据(FileOutputStream):

1.1.1:写单个字符或数组

1.先创建对象

2.写入数据:

3.批量插入

4.释放资源:

1.1.2:写字符串与换行符 

1.创建对象

2.写出数据

3.换行

4.释放资源

1.2:读数据(FileInputStream)

1.创建对象

2.开始读取

3.循环遍历

3.1:正确遍历方法

3.2:错误遍历方法

4.释放资源: 

1.3:文件操作: 

1.3.1:拷贝文件(普通版):

1.3.2:编码与解码:

补充:

1.3.3:文件拷贝(会员版):

 1.3.4:文件压缩:

1.3.5:文件解压: 

1.3.6:字节打印流: 

 1.3.7:字符打印流:

二、字节缓冲流:

2.1:写数据:

2.2:读数据 

2.3:字节缓冲流提高提高效率的原理:

三、 字符流:

3.1:读数据:

3.1.1:JDK11前后区别:

3.2:写数据: 

3.2.1:单个数据写入文件

3.2.2: 文件数据传输

3.2.3:文件夹的拷贝 

 4.使用工具类的一些快捷方法来实现文件的操作

 4.1:拷贝文件

  4.2:拷贝文件夹

  4.3:删除文件夹

 4.4:清空文件夹

  4.5:读取文件(注意是文件)中的数据变成字符串

 四、字符缓冲流

(1)介绍: 

(2)构造方法 

(3)代码演示

(4)字符缓冲流特有功能

结尾: 


前言:

        在 Java 程序设计中,IO(Input/Output)流是一项至关重要的功能,它允许程序与外部世界进行数据的交换。无论是从文件中读取数据,将数据写入文件,还是通过网络进行通信,IO 流都扮演着核心角色。理解和掌握 Java 的 IO 流机制对于开发强大、可靠和高效的应用程序是必不可少的。本章节将带你深入探索 Java IO 流的奥秘,从基础概念开始,逐步深入到各种类型的 IO 流及其实际应用,帮助你轻松应对不同场景下的数据输入和输出需求。

IO流的体系总览

一、 字节流:

1.1:写数据(FileOutputStream):

写出一段文字到本地文件当中

FileOutputStream()形参可以是字符串也可以是file对象

1.1.1:写单个字符或数组
1.先创建对象
FileOutputStream fos = new FileOutputStream("E:\\aaa\\abc.txt");//如果它存在,就清空内容

2.写入数据:

将97对应的Ascll码值输出到文件夹里,一次只能写一个,下次写的数据会将上次写的数据覆盖

fos.write(97);
3.批量插入
byte[] b = {97, 98, 99, 100, 101, 102, 103, 104, 105};
fos.write(b);//将整个数组的内容都插入到文件夹中
fos.write(b, 1, 3);//将数组b中从起始索引1一直往后个数为3插入到文件夹中
4.释放资源:

也就是说让idea停止占用这个文件夹。

fos.close();

1.1.2:写字符串与换行符 
1.创建对象

新写入元素会清空文件夹,此时你加了true,表示可以续写,默认开关是flase,

FileOutputStream fos = new FileOutputStream("E:\\aaa\\abc.txt",true);
2.写出数据

写字符串一般需要用byte字节数组

String str="asdfgjhkl";
byte[] bytes1 = str.getBytes();
fos.write(bytes1);

String str2="666";
byte[] bytes3 = str2.getBytes();
fos.write(bytes3);
3.换行
String str1="\r\n";
byte[] bytes2 = str1.getBytes();
fos.write(bytes2);
4.释放资源
fos.close();

1.2:读数据(FileInputStream)

1.创建对象
FileInputStream fis=new FileInputStream("E:\\aaa\\abc.txt");

读的函数,每次只读一个字符串,读到最后没有数据了,那就返回-1。
如果最后一个数据是-1,则先打印“-”再打印1(转了Char)

2.开始读取
int read1 = fis.read();
System.out.println((char)read1);

 int read2 = fis.read();
System.out.println((char)read2);

 int read3 = fis.read();
System.out.println((char)read3);
3.循环遍历
3.1:正确遍历方法
int b;
while((b=fis.read())!=-1){
    System.out.println(b);
}
3.2:错误遍历方法
while(fis.read()!=-1){
//read函数的细节:他是获取到每一个元素并且将指针指向下一个元素
    System.out.println(fis.read());
//到这里输出的时候其实就已经指向的时第二个元素了
4.释放资源: 
fis.close();

1.3:文件操作: 

1.3.1:拷贝文件(普通版):

        //文件拷贝

        FileInputStream fis=new FileInputStream("E:\\反诈视频2.mp4");
        FileOutputStream fos=new FileOutputStream("MyIo\\copy.mp4");

         long start= System.currentTimeMillis();
        int b;
        while((b=fis.read())!=-1){
            fos.write(b);
        }
           long end=System.currentTimeMillis();
        System.out.println(end-start);

        //释放资源
        //一般来说:先创建的对象先释放
        fos.close();
        fis.close();
  
1.3.2:编码与解码:
        //1.编码
        String str = "ai你哟";
        byte[] b = str.getBytes();//变成字节数组 默认情况下为utf-8编码规则
        System.out.println(Arrays.toString(b));//转换成字符串,变成Ascll码值

        byte[]b2=str.getBytes("GBK");//编码规则为GBK
        System.out.println(Arrays.toString(b2));


        //2.解码
        String str2=new String(b);//默认解码的方式为utf-8
        System.out.println(str2);

        String str3=new String(b2,"GBK");//用GBK的编码方式
        System.out.println(str3);
补充:

编码表
(1)什么是字符集
是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBXXX字符集、Unicode字符集等。

(2)常见的字符集
ASCII字符集

ASCII:是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号) 。

基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符集使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等

GBXXX字符集

GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。

Unicode字符集

UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用 中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用一至四个字节为每个字符编码。

(3)编码规则

 128个US-ASCII字符,只需一个字节编码
  拉丁文等字符,需要二个字节编码
  大部分常用字(含中文),使用三个字节编码
  其他极少使用的Unicode辅助字符,使用四字节编

1.3.3:文件拷贝(会员版):
  FileInputStream fis = new FileInputStream("E:\\反诈视频2.mp4");
        FileOutputStream fos = new FileOutputStream("MyIo\\copy1.mp4");


         long start= System.currentTimeMillis();
        int b;
        byte[] buf = new byte[1024*1024*5];//5Mb/s
        while((b=fis.read(buf))!=-1){
            fos.write(buf,0,b);
        }
           long end=System.currentTimeMillis();
        System.out.println(end-start);//6ms就已经搞完了,没有加速要11秒,快了2000多倍

        //释放资源
        //一般来说:先创建的对象先释放
        fos.close();
        fis.close();
 1.3.4:文件压缩:
//压缩文件
        //本质就是将文件中的Entry对象变成文件

        //创建file对象表示要压缩的文件
        File file = new File("E:\\aaa\\abcd.txt");

        //创建file对象表示压缩包的位置
        File dest = new File("E:\\");

        toZip(file, dest);

    }

    public static void toZip(File src, File dest) throws IOException {
        //1.创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest, "a.zip")));

        //2.创建ZipEntry对象,用来表示压缩包里的文件和文件夹
        ZipEntry entry = new ZipEntry("a.txt");
        //参数:其实是压缩包里的路径

        //3.把ZipEntry对象放到压缩包里
        zos.putNextEntry(entry);

        //4.将file文件的数据写到压缩包里
        FileInputStream fis = new FileInputStream(src);
        int b;
        while ((b = fis.read()) != -1) {
            zos.write(b);
        }
        zos.closeEntry();
        zos.close();
        fis.close();
    }
1.3.5:文件解压: 
 //文件解压


        //1.创建一个File表示要解压的压缩包
        File f=new File("E:\\ccc.zip");

        //创建一个新的File表示解压的目的地
        File dest=new File("E:\\");//表示将其解压到D盘的根目录下面

        unZip(f,dest);

    }
    //创建一个方法来实现
    public static void unZip(File f,File dest) throws IOException {
        //文件解压的本质就是将文件中的entry对象拷贝到目的文件中

        //创建一个解压缩流来读取压缩包中的数据
        ZipInputStream zip=new ZipInputStream(new FileInputStream(f));

        //先获取数据中的Entry对象
        ZipEntry entry = zip.getNextEntry();
        while(entry!=null){//如果是获取不到对象了,那就返回null
            if(entry.isDirectory()){//如果是文件夹,那就要创建新的文件夹
                File file=new File(dest,entry.getName());//父级路径dest,子级路径entry.getName()
                file.mkdirs();//创建一个文件夹,boolean类型的,创建成功,返回true,创建失败:返回flase

            }else{//如果是文件,就直接拷贝
                FileOutputStream fos=new FileOutputStream(new File(dest,entry.getName()));
                int b;
                while((b=zip.read())!=-1){
                  fos.write(b);
                }
                fos.close();
                zip.closeEntry();
            }
        }

zip.close();

    }
1.3.6:字节打印流: 
        //字节打印流
        PrintStream ps = new PrintStream(new FileOutputStream("MyIo\\fun.txt"));

        ps.println("Hello World");//写出,自动刷新,自动换行
        ps.print("Hello World");
        ps.println();
        ps.printf("%s爱上了%s","阿珍","阿强");


        //System.out.println();
        //输出语句的底层就是一个打印流
        PrintStream p= System.out;
        p.println("hello world");
        p.print("hello world");

        p.println("你好你好");


        //第一个打印流,释放资源
        ps.close();
 1.3.7:字符打印流:
      //字符打印流
        PrintWriter pw = new PrintWriter(new FileWriter("MyIo\\fun.txt"));

        pw.println("Hello World");
        pw.print("Hello World");
        pw.println();
        pw.printf("%s爱上了%s", "阿珍", "阿强");
        pw.close();

二、字节缓冲流:

       字节缓冲流是在 Java 的输入输出(IO)体系中,用于提高字节流读写效率的一种流。它内部包含了一个缓冲区,通过将数据先读入缓冲区或者先写入缓冲区,减少了对底层物理设备(如硬盘、网络等)的直接读写次数,从而提高了数据传输的效率。

众所周知:没有什么是加一层中间层不能解决的

2.1:写数据:

将对象集合写入文件

        Student s1=new Student("张三",23,"南京");
        Student s2=new Student("李四",24,"红京");
        Student s3=new Student("王五",23,"天京");
        Student s4=new Student("赵六",23,"北京");

        ObjectOutputStream oos = new ObjectOutputStream(new 
        FileOutputStream("C:\\Users\\IdeaProjects\\string\\MyIo\\abcd.txt"));

        ArrayList<Student> list=new ArrayList<Student>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        oos.writeObject(list);

        oos.close();

2.2:读数据 

 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\IdeaProjects\\string\\MyIo\\abcd.txt"));
        ArrayList<Student> list1 = (ArrayList<Student>) ois.readObject();

        for (Student student : list1) {
            System.out.println(student);
        }


        ois.close();

2.3:字节缓冲流提高提高效率的原理:

1.我们知道字节流是没有缓冲区的,而字节缓冲流就加了缓冲区
                                    内存
数据源-------缓冲区1              缓冲区2----------目的地

内存中间就加了俩个缓冲流,如果没加byte数组进行传输,那就内存里从缓冲区1往缓冲区2里面一个一个搬数据
如果加了byte数组,那就按照byte数组的长度进行搬运数据
注意:其实内存里搬运数据是非常快的(因为是硬件实现的)
所以提高速度的真实原因是缓冲区的建立,减少了内存与文件之间的交互

三、 字符流:

3.1:读数据:

FileReader fr=new FileReader("E:\\bbb\\a.txt");

read函数是一个字节一个字节的读,当遇到中文时,就会读取多个字节(utf-8为3个,GBK为2个)
底层会把读到的二进制数据转换成十进制
也就是文件里的中文被系统utf-8编码成二进制数据,然后read函数会将其转换成十进制
如果想再读取到中文,用(char)强转

int ch;
while((ch=fr.read())!=-1){
    System.out.print((char)ch);
}
释放资源
fr.close();
     FileReader fr = new FileReader("E:\\bbb\\a.txt");

        char[] ch=new char[2];
        int len;
        while((len=fr.read(ch))!=-1){//read函数与没有参数的read函数不同,这个有参数的read函数=没有参数的read+强转
            System.out.println(new String(ch,0,len));
        }

3.1.1:JDK11前后区别:

  JDk11之前是这么个事:

InputStreamReader isr = new InputStreamReader
(new FileInputStream("C:\\Users\\IdeaProjects\\string\\MyIo\\abcd.txt"),"UTF-8");
        int b;
        while ((b=isr.read())!=-1){
            System.out.print((char)b);
        }
        isr.close();

 JDK11之后变成这么个事了:

FileReader fr=new FileReader("C:\\Users\\IdeaProjects\\string\\MyIo\\abcd.txt", Charset.forName("UTF-8"));
        int b;
        while((b=fr.read())!=-1){
            System.out.print((char)b);
        }
        fr.close();

3.2:写数据: 

3.2.1:单个数据写入文件
 FileWriter fw=new FileWriter("E:\\bbb\\a.txt",true);

        //写出一个字符
        fw.write(97);

        //写出一个字符串
        fw.write("我爱中国");

        //写出字符串的一部分
        fw.write("我爱中国",1,3);//从一索引到三索引

        //写出一个字符数组
        char []c={'a','b','c'};
        fw.write(c);

        //写出字符数组的一部分
        fw.write(c,1,2);


        fw.close();

 

3.2.2: 文件数据传输
 //底层:缓冲区

        //注意:只有字符流才有缓冲区,字节流是没有缓冲区的
        FileReader fr = new FileReader("E:\\bbb\\a.txt");
        fr.read();//第一次调用这个方法,内存里就会开辟一个缓冲区(容量为8192字节),会将这个缓冲区尽可能的装满

        FileWriter fr1 = new FileWriter("E:\\bbb\\a.txt");//注意此时文件里的数据会被清空
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.print((char) ch);
        }//此时,虽然文件里的数据被清空了,但是在第一个read方法时他就将数据都存在了缓冲区里
        //所以此时我们是从缓冲区里拿数据,所以此时依然可以获取到数据

        fr1.close();
        fr.close();
3.2.3:文件夹的拷贝 
  //文件夹的拷贝

        //1.创建对象来确定数据源
        File src=new File("E:\\bbb");
        //2.创建对象来确定目的地
        File dest=new File("E:\\ccc");

        copydir(src,dest);

    }
    private static void copydir(File src, File dest) throws IOException {
        //进入数据源
        File[] files=src.listFiles();

        if (files!=null) {
            //遍历数组
            for (File file : files) {
                if(file.isFile()) {
                    //直接拷贝,拷贝使用字节流
                    FileInputStream fis = new FileInputStream(src);     //父级路径,//子级路径,二者相拼接
                    FileOutputStream fos = new FileOutputStream(new File(dest, file.getName()));
                    byte[] b = new byte[1024];
                    int len;
                    while((len=fis.read(b))!=-1){
                        fos.write(b,0,len);
                    }
                }else{
                    copydir(file, new File(dest, file.getName()));
                }
            }
        }
    }

 4.使用工具类的一些快捷方法来实现文件的操作

 4.1:拷贝文件
 File src=new File("MyIo\\fun.txt");
 File dest=new File("MyIo\\copyfun.txt");
  FileUtils.copyFile(src,dest);
  4.2:拷贝文件夹
  File src=new File("E:\\ccc");
  File dest=new File("E:\\ddd");

  FileUtils.copyDirectory(src, dest);//(将src中的文件拷贝到dest当中去)
  FileUtils.copyFileToDirectory(src, dest);//(将src本身一起打包复制给dest)
  4.3:删除文件夹
      File src = new File("E:\\ccc");
      FileUtils.deleteDirectory(src);
 4.4:清空文件夹
  FileUtils.cleanDirectory(src);
  4.5:读取文件(注意是文件)中的数据变成字符串
  File src = new File("E:\\ddd\\abc.txt");
  String s = FileUtils.readFileToString(src);
  System.out.println(s);

 四、字符缓冲流

BufferedWriter

(1)介绍: 

将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途。

BufferedReader

从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。 

(2)构造方法 

| BufferedWriter(Writer out) | 创建字符缓冲输出流对象 |

| BufferedReader(Reader in)  | 创建字符缓冲输入流对象 |

(3)代码演示

public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //BufferedWriter(Writer out)
        BufferedWriter bw = new BufferedWriter(new                                                            FileWriter("myCharStream\\bw.txt"));
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();
 
        //BufferedReader(Reader in)
        BufferedReader br = new BufferedReader(new                                                           FileReader("myCharStream\\bw.txt"));
 
        //一次读取一个字符数据
//        int ch;
//        while ((ch=br.read())!=-1) {
//            System.out.print((char)ch);
//        }
 
        //一次读取一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while ((len=br.read(chs))!=-1) {
            System.out.print(new String(chs,0,len));
        }
 
        br.close();
    }
}


(4)字符缓冲流特有功能

void newLine()写一行行分隔符,行分隔符字符串由系统属性定义

String readLine()读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null

结尾: 

         至此,我们已经对 Java IO 流进行了全面的探讨,从基本概念到各种类型的流及其高级功能,相信你已经对如何使用 Java 中的 IO 流有了深入的了解。掌握这些知识,你将能够在自己的 Java 开发中熟练地处理各种数据输入和输出任务,为你的程序带来更强的交互性和数据处理能力。然而,Java IO 流的世界还在不断发展,新的特性和改进也会随着 Java 版本的更新而不断涌现,希望你能够将这里所学的基础作为起点,持续探索和学习,为自己的编程之旅打开更广阔的天地。

        请记住,在使用 IO 流时,始终要注意资源的管理,确保及时关闭打开的流,以避免资源泄漏。同时,根据不同的数据类型和处理需求,合理选择使用字节流还是字符流,以及适当的缓冲和过滤机制,将有助于你编写出更高效、更稳定的代码。不断地实践和尝试,会让你在 IO 流的使用上越来越得心应手,为你的 Java 开发工作带来更多的便利和创新。


原文地址:https://blog.csdn.net/2301_78506180/article/details/145173737

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!