首页 > 其他分享 >IO

IO

时间:2022-12-02 23:13:55浏览次数:33  
标签:IO 字节 stream read write File new

File类只能操作属性,无法操作文件里面的数据

IO

InputStream——OutputStream

从流向上划分:输入流/输出流

从操作内容上来划分:字节流 字符流

操作文件里面的数据:

  1. 读取文件里面的数据 --->read 输入流
  2. 将数据写入文件 –>write 输出流

1.字节流

计算机里面所有文件内存存储都是以字节的形式进行存储,也就是二进制文件。因此字节流就是万能流,可以操作计算机里面任意类型的文件

1.1 字节输入流InputStream

InputStream是一个抽象类,常用子类:

FileInputStream();//文件字节输入流
BufferedInputStream();//高效字节输入流
DataInputStream();//数据输入流
ObjectInputStream();//对象输入流

InputStream里面的方法:

abstract int read() 
int read(byte[] bytes);  读取字节数组长度的字节内容

FileInputStream 效率低

FileInputStream(File file)
FileInputStream(String name)

read(); 读取一个字节内容

private static void demo1() {
    //读取指定文件数据:文件必须存在
    String filePath="1129\\1129.iml";
    //创建字节输入流对象:
    InputStream inputStream=null;
    try {
         inputStream=new FileInputStream(filePath);
         //读取文件数据
        int len;
        while ((len=inputStream.read())!=-1){
            System.out.print((char) len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(inputStream!=null){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
//但是上面大部分代码都是用于处理异常,我们换下面的方式:
private static void demo2() {
        //jdk1.7之后提供了一种更加优雅的方式释放资源(自动释放资源)  try...with...resource
        try (
                //创建的对象(必须实现Closeable接口)
                InputStream stream = new FileInputStream("1129\\1129.iml");
        ) {
            //读取数据
            int read;
            while ((read = stream.read()) != -1) {
                System.out.print((char) read);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

read(byte[] bytes); 读取字节数组长度的字节内容

//让他来读取给定长度(一般是1024的整数倍)的字节内容,读取的内容会放到该数组里面,想看数据的话得看读取的字节数组
private static void demo3() {
        try(
                InputStream stream=new FileInputStream("1129\\src\\exercise.java");
                ){
              byte[] bytes = new byte[10];
            //这里我给了10,如果文件里面的字节小于10,读取字节数也会小于10
            // 文件长度超过10,也会只读10个
            System.out.println(stream.read(bytes));
            System.out.println(new String(bytes));
            //将字节数组转字符串输出,如果是中文,有可能会出现乱码:import jav
            System.out.println(stream.read(bytes));
           //该字节数组已经装满了,如果再去读byte.length长度个,读取内容会覆盖原先的字节数组
        }catch (IOException e){
            e.printStackTrace();
        }
    }

read(byte[] bytes,int startIndex,int lenth) 从起始位置读取数组长度的内容,读取指定字节长度

private static void demo4() {
    try(
            InputStream stream=new FileInputStream("1129\\src\\exercise.java");
            ){
        byte[] bytes=new byte[1024];
        stream.read(bytes,0,1024);
        System.out.println(new String(bytes));
    }catch (IOException e){
        e.printStackTrace();
    }
}

1.2.字节输出流

OutputStream:将数据内容写入文件中 也就是write,常用子类

FileOutputStream();//文件字节输出流
BufferedOutputStream();//高效字节输出流
DataOutputStream();//数据输出流
ObjectOutputStream();//对象输出流

outputstream的构造:

FileOutputStream(File file)
FileOutputStream(File file, boolean append)//给定是拼接原文件还是覆盖源文件,默认覆盖
FileOutputStream(String name)
FileOutputStream(String name, boolean append) 

FileOutputStream 效率低

private static void demo5() {
    try (
            //文件可以不存在,构造方法里面可以加一个布尔来判断是覆盖原文件还是拼接原文件
            OutputStream stream = new FileOutputStream("1129\\src\\a.txt");
    ) {
        stream.write(65);
        stream.write(49);
        stream.write(52);
        stream.write("abdcfe".getBytes());
        stream.write('\n');
        stream.write("学习使我快乐!".getBytes());//给汉字的时候注意编码格式

    } catch (IOException e) {
        e.printStackTrace();
    }
}

模拟用户上传头像

private static void demo6() {
    File filePath = new File("E:/肖战.jpg");
    File filePath1 = new File("D:/肖战.jpg");
    String targetPath = "1129\\src\\image\\" + LocalDate.now().toString();
    try (
            InputStream inputStream = new FileInputStream(filePath1);
            OutputStream outputStream =
        new FileOutputStream(targetPath + UUID.randomUUID());
        //由于图片名称可能会相同,下载路径一致的时候可能会被覆盖,这里我们用UUID的随机数字符来拼接
    ) {
        int len;
        while ((len = inputStream.read()) != -1) {
            outputStream.write(len);
        }
        System.out.println(targetPath);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//读取大文件的时候,这种读取速度是很慢的:
private static void demo7() {
        String filePath="E:\\第一阶段课堂笔记(JavaSE).nyf";
        String targetPath = "1129\\src" + LocalDate.now().toString();
        try(
                InputStream inputStream = new FileInputStream(filePath);
                OutputStream outputStream = new FileOutputStream(targetPath + UUID.randomUUID());
        ) {
            int len;

            while ((len=inputStream.read())!=-1){
                outputStream.write(len);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
//读取速度很慢,我等了一分钟也没读完

但是上面的读写速度是比较慢的,如果需要传大文件的时候,一个读一个写,这样的速度是很慢的,因此我们可以用带参的write(byte[] bytes)来加快写入文件的速度:

private static void upLoadFile(String sourceFilePath) {
        Objects.requireNonNull(sourceFilePath);
        File target = new File(TARGET_PATH, LocalDate.now().toString());
        if (!target.exists()) {
            target.mkdirs();//判断文件目录是否存在,不存在去创建
        }
        String filename=UUID.randomUUID().toString()+
            sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator)+1);
       File targetPath=new File(target,filename);//创建目标文件路径和目标文件名
        try (
                InputStream inputStream = new FileInputStream(sourceFilePath);
                OutputStream outputStream = new FileOutputStream(targetPath);
        ) {
            int len;
            byte[] bytes = new byte[1024 * 100];//一次写入这样多的字节
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);//如果不加这一行最后会多读取1024个字节
            }
            System.out.println("文件上传成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

上面,file来操作文件夹,而IO来操作文件数据

高效字节流

BufferedInputStream:高效字节输入流 read

BufferedOutputStream:高效字节输出流 write

底层自动提供了字节数组来缓冲,默认长度为8192

private static void demo1() {
    try{
        BufferedOutputStream stream=new BufferedOutputStream(new FileOutputStream("day1202\\src\\a.txt"));
        stream.write(78);
        stream.write("hello".getBytes());
        //写入的数据都放在缓存区,因为此时的文件不满8192的长度,需要释放资源,或者刷新
        //stream.flush();
        stream.close();//底层自动调用flush()
    }catch (IOException e){
        e.printStackTrace();
    }
}

若用该方法进行io,并且在代码里面又加了一个临时缓冲区,效率会更快,两个缓存区一起使 ,因此推荐使用自己写一个缓冲区,然后再与BufferedOutputStream来一起使用 ,效率会很快。

2.字符流

reader:字符输入流

writer:字符输入流

字符流不能操作其他的二进制文件,主要用于操作纯文本文件(txt、java、html.etc) ,对于有样式的文本文件,后期会用POI来进行操作。底层:字节流+字符集,它可以写入一串

public void write(String str, int off, int len) throws IOException {
    se.write(str, off, len);
}

reader常用子类:

BufferedReader
FileReader
InputStreamReader

writer常用子类:

BufferedWriter
FileWriter
OutputStreamWriter

用法跟字节流差不多,直接拿来用:

上传文件:

private static void demo2() {
    String targetPath="day1202\\src";
    File filePath=new File(targetPath,LocalDate.now().toString());
    if (!filePath.exists()) {
        System.out.println("目标路径目录不存在,已为您创建目录");
        filePath.mkdirs();
    }
    String path= "day1202\\src\\a.txt";
    File sourcePath=new File(path);
    String name=path.substring(path.lastIndexOf('\\')+1);
    File targetFile=new File(filePath,name);//得到文件(文件名+文件类型)
    try (
            Reader reader = new FileReader(sourcePath);
            Writer writer=new FileWriter(targetFile)//参数只能是文件,不能是文件夹
    ) {
        int read;
        while ((read = reader.read())!=-1){
            writer.write(read);
            System.out.println("上传成功");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

但是它用来操作其他文件的话得到的是一个破损文件,是打不开的,只能操作文本文件

高效字符流

装饰了基本字符流的读写功能,底层自带缓冲(带一个长度为8192的字符数组) ,他里面有一个方法:

String readLine() //一次读取一行

标签:IO,字节,stream,read,write,File,new
From: https://www.cnblogs.com/Liku-java/p/16945944.html

相关文章