java day16 IO流(字节流、字符流)

1、流

1.1 流的概念

  • 内存与内存设备之间的数据传输通道
  • 水借助管道传输;数据借助流传输

1.2 流的分类

1.2.1 按方向(重点)
  • 输入流:将存储设备中的数据读入到内存中
  • 输出流:将内存中的内容写入到存储设备中
1.2.2 按单位
  • 字节流:以字节为单位,可以读取任何文件的数据
  • 字符流:以字符为单位,可以读取文本文件的数据
1.2.3 按功能
  • 节点流:具有具体传输数据的能力
  • 过滤流:在节点流的基础上加强功能

2、File、FileFilter

2.1 Filel类

概念:代表物理盘符中的一个文件或者文件夹

常见方法:

方法名描述
createNewFile()创建一个新文件。
mkdir()创建一个新目录。
delete()删除文件或空目录。
exists()判断File对象所对象所代表的对象是否存在。
getAbsolutePath()获取文件的绝对路径。
getName()取得名字。
getParent()获取文件/目录所在的目录。
isDirectory()是否是目录。
isFile()是否是文件。
length()获得文件的长度。
listFiles()列出目录中的所有内容。
public class Demo01 {
    public static void main(String[] args) {
        //路径都是从盘符开始
        //File file = new File("E:\\File\\IO1.txt");
        //File file = new File("E:\\File", "IO1.txt");
        //File file = new File(new File("E:\\File"), "IO1.txt");

        //路径从项目开始
        File file = new File("file\\IO1.txt");
        System.out.println("文件是否可读:"+file.canRead());
        System.out.println("文件是否可写:"+file.canWrite());
        System.out.println("文件是否隐藏:"+file.isHidden());
        //相对于项目
        System.out.println("相对路径:"+file.getPath());
        //从盘符开始
        System.out.println("绝对路径:"+file.getAbsolutePath());
        System.out.println("文件名:"+file.getName());
        System.out.println("文件的长度:"+file.length());
        //返回的是从1970年1月1日到文件最后修改时间的毫秒数
        System.out.println("文件的最后修改时间1:"+file.lastModified());
        System.out.println("文件的最后修改时间2:"+getTime(file.lastModified()));
        System.out.println("是否为文件:"+file.isFile());
        System.out.println("是否为目录:"+file.isDirectory());
    }

    public static String getTime(long time){
        //Date date = new Date(time);
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //String str = sdf.format(date);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = sdf.format(time);
        return str;
    }
}

2.2 FileFilter接口

FileFilter:文件过滤器接口

  • boolean accept(File pathanme)
  • 当调用File类中的listFile()方法时,支持传入FileFilter接口的接口实现类,当获取文件进行过滤,只有满足条件的文件才会出现在listFile()的返回值中
    private static void test04(File file){
        //数组中包含txt文件和目录
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //过滤非txt文件的内容
                if(pathname.isFile()){
                    //是否为txt文件
                    if(!pathname.getName().endsWith(".txt")){
                        return false;
                    }
                }
                return true;
            }
        });

        for (File f:files) {
            //判断是文件还是目录
            if(f.isFile()){
                System.out.println(f.getAbsolutePath());

            }else{
                test03(f);
            }
        }
    }

3、字节流(重点)

3.1 字节抽象类

InputStream:字节输入流

  • public int read(){}。
  • public int read(byte[] b){}。
  • public int read(byte[] b,int off,int len){}。

OutputStream:字节输出流

  • public void write(int n){}。
  • public void write(byte[] b){}。
  • public void write(byte[] b,int off,int len){}。

3.2 字节节点流

FileOutputStream:

  • public void write(byte[] b)。
  • 一次写多个字节,将b数组中所有字节,写入输出流。

FileInputStream:

  • public int read(byte[] b)。
  • 从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数。
  • 如果达到文件的尾部,则返回-1。

案例演示:FileInputStream读取文件。

package com.qf.ran.stream;

import com.qf.ran.utils.IOUtils;
import org.junit.Test;

import java.io.*;

/**
 * @author Ran
 * @since JDK 1.8
 *          IO流
 *              1.根据数据的传输方向:
 *                      输入流/输出流
 *              2.根据读写的单位:
 *                      字节流,字符流
 *              3.根据功能划分:
 *                      基础流,包装类
 *
 *
 *          FileInputStream --  文件字节输入流,基类为InputStream
 */
public class Demo01 {

    //读取单个字节
    @Test
    public void test01(){
        //文件字节输入流
        FileInputStream fis = null;
        try {
            //fis = new FileInputStream(new File("IO1.txt"));
            fis = new FileInputStream("IO3.txt");
            //读取单个字节
            int read = fis.read();
            System.out.println((char)read);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    //读取单个字节    --  循环读取完毕
    @Test
    public void test02(){
        //文件字节输入流
        FileInputStream fis = null;
        try {
            //fis = new FileInputStream(new File("IO1.txt"));
            fis = new FileInputStream("IO1.txt");
            //读取到的数据字节
            int read;
            while((read = fis.read())!= -1){
                System.out.println((char)read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void test03(){
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("IO1.txt");
            //1024代表数组的长度,也代表一次读取1024个数据字节到数组中
            byte[] b = new byte[1024];
            //读取到数组中的数据长度
            int len;
            while((len = fis.read(b)) != -1){
                //第一个参数为存放数据的数组(缓冲区)
                //第二个参数是偏移量
                //第三个参数是存放在数组中的数据长度
                System.out.println(new String(b,0,len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtils.closeAll(fis);
        }
    }
}

3.3 字节缓冲流

字节缓冲流:BufferedOutputStream、BufferedInputStream

  • 提高IO效率,减少访问磁盘的次数
  • 数据存储在缓冲区中,fush是将缓存区的内容写入文件中,也可以自己close,但是内存无法手动关闭

代码示例:

public class Demo01 {
    //带缓冲区的字节输出流
    @Test
    public void test01() throws IOException {
        //默认缓冲区大小为8192
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO1.txt"));
        bos.write("good good study!".getBytes());
        bos.close();
    }

    @Test
    public void test02() throws IOException {
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO1.txt",true));
        bos.write("day day up!".getBytes());
        bos.close();
        //刷新,会把缓冲区的数据写入文件中
        //bos.flush();
    }

    //带缓冲区的字节输入流
    @Test
    public void test03() throws Exception {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("IO1.txt"));
        byte[] b = new byte[1024];
        int len;
        while((len = bis.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
        bis.close();
    }

    //带缓冲区的字节流拷贝
}

3.4 对象流

对象流

  • ObjectInputStream
  • ObjectOutputStream
  • 使用对象流进行读写操作是,本质上是在进行序列化与反序列化操作
  • 写入对象的操作为序列化操作
  • 读取对象的操作为反序列化操作
  • 序列化和反序列化的序列号保持一致
  • 私有的静态属性不会被序列 私有的transient属性不会被序列化

案例演示:使用对象流实现序列化和反序列化。

public class User implements Serializable {
    //默认存在的序列号
    //private static final long serialVersionUID = 1L;

    //2个属性拥有对应的序列号  --  序列化时的序列号
    //private static final long serialVersionUID = -3904710604062277395L;
    //3个属性拥有对应的序列号  --  反序列化时的序列号
    //private static final long serialVersionUID = 4353974749186785642L;

    private String name;
    private int age;

    //会被序列化
    //private int id;
    //会被序列化
    //static int id;
    //不会被序列化
    //private static int id;
    //会被序列化
    //public static int id;
    //会被序列化
    //protected static int id;
    //会被序列化
    //private final int ID = 1;
    //会被序列化
    //public final int ID = 1;
    //不会被序列化
    //private static final int ID = 1;
    //会被序列化
    //transient int id;
    //不会被序列化
    private transient int id;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Demo01 {
    public static void main(String[] args) throws IOException {
        //把对象存储到集合中,把集合通过对象流写入文件中
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("霞姐",18));
        list.add(new User("泽哥",28));
        list.add(new User("昌老师",28));
        list.add(new User("波老师",28));
        oos.writeObject(list);
        oos.close();


        /*
        写入对象完毕后添加null对象
        null对象添加有可能遗漏或者null对象后续再添加对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
        oos.writeObject(new User("霞姐", 18));
        oos.writeObject(new User("四青", 19));
        oos.writeObject(new User("银珍", 20));
        oos.writeObject(new User("玲苑", 20));
        oos.writeObject(new User("玲苑", 16));
        oos.writeObject(null);
        oos.close();*/


        //在写入对象之前写入int类型的数据,数据值为对象个数
        //数据值与对象个数可以存在不匹配的情况
       /* ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO4.txt"));
        oos.writeInt(4);
        oos.writeObject(new User("霞姐", 18));
        oos.writeObject(new User("四青", 19));
        oos.writeObject(new User("银珍", 20));
        oos.close();*/

        /*BufferedWriter bw = new BufferedWriter(new FileWriter("IO3.txt"));
        String str = user.getName()+user.getAge();
        bw.write(str);
        bw.close();*/
    }
}

4、字符流(重点)

4.1 字节抽象类

Reader:字节输入流

  • public int read(){}.
  • public int read(char[] c){}.
  • public int read(char[] int off, int len){}

Write:字符输出流

  • public void write(int n){}.
  • public void write(String str){}.
  • public void write(char[] c){}.

4.2 字节节点流

FileWriter:

  • public void write(String str).
  • 一次写多个字符,将b数组中所有的字符,写成输出流

FileReader:

  • public int read(char[] c)
  • 从流中读取多个字符,将读到的内容存入c数组中,返回实际读取到的字符数,若是到达文件末尾,则返回-1.
public class TestFileReader {
	public static void main(String[] args) throws Exception{
		//1创建FileReader 文件字符输入流
		FileReader fr=new FileReader("d:\\hello.txt");
		//2读取
		//2.1单个字符读取
		//int data=0;
		//while((data=fr.read())!=-1) {//读取一个字符
		//	System.out.print((char)data);
		//}
		char[] buf=new char[1024];
		int count=0;
		while((count=fr.read(buf))!=-1) {
			System.out.println(new String(buf, 0, count));
		}
		
		//3关闭
		fr.close();
	}
}

public class TestFileWriter {
	public static void main(String[] args) throws Exception {
		//1创建FileWriter对象
		FileWriter fw=new FileWriter("d:\\write.txt");
		//2写入
		for(int i=0;i<10;i++) {
			fw.write("java是世界上最好的语言\r\n");
			fw.flush();
		}
		//3关闭
		fw.close();
		System.out.println("执行完毕");
	}
}

4.3 字节缓冲流

缓冲流:BufferedWriter、BufferedReader

  • readLine()是BufferedReader独有的方法,作用是读取一行数据
  • newLine()是BufferedWriter独有的方法,作用是写入换行符
public class Demo02 {
    @Test
    public void test01() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("IO1.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("IO2.txt"));
        /*char[] c = new char[1024];
        int len;
        while((len = br.read(c)) != -1){
            bw.write(c,0,len);
        }*/

        String str;
        //br.readLine()读取一行数据
        while((str = br.readLine()) != null){
            //写入一行数据
            bw.write(str);
            //写入换行符
            bw.newLine();
        }
        br.close();
        bw.close();
    }
}

4.4 打印流

  • PrintStream:打印字节流
  • PrintWriter:打印字符流
  • 支持数据原样打印
public class Demo01 {
    @Test
    public void test01() throws FileNotFoundException {
        PrintStream ps = new PrintStream(new FileOutputStream("IO1.txt"));
        //ps.write(97);
        //打印流独有的方法,直接打印数据
        ps.print(98);
        ps.close();
    }

    @Test
    public void test02() throws IOException {
        PrintWriter pw = new PrintWriter(new FileWriter("IO2.txt"));
        pw.write(97);
        pw.print(97);
        pw.close();
    }
}

4.5 转换流

转换流: InputStreamReader、OutputStreamWriter

  • 可以将字节流转换成字符流
  • 可以设置字符的编码方式
public class Demo01 {
    //转换流输出流
    @Test
    public void test01() throws Exception {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("IO5.txt"));
        osw.write("净化广告");
        osw.close();
    }

    //转换流输入流
    @Test
    public void test02() throws Exception {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("IO5.txt"));
        char[] c = new char[1024];
        int len;
        while((len = isr.read(c)) != -1){
            System.out.println(new String(c,0,len));
        }
        isr.close();
    }

    //使用场景
    @Test
    public void test03() throws Exception {
        //方法返回字节流
        FileInputStream fis = new FileInputStream("IO5.txt");
        //需要使用BufferedReader的readLine()
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));
        //使用对应的方法..
    }


    //使用文件字节输入流读取不同编码格式的文件
    @Test
    public void test04() throws Exception {
        FileInputStream fis = new FileInputStream("E:\\File\\File.txt");
        byte[] b = new byte[1024];
        int len;
        while((len = fis.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
        fis.close();
    }

    //使用文件字符输入流读取不同编码格式的文件
    @Test
    public void test05() throws Exception {
        FileReader isr = new FileReader("E:\\File\\File.txt");
        char[] c = new char[1024];
        int len;
        while((len = isr.read(c)) != -1){
            System.out.println(new String(c,0,len));
        }
        isr.close();
    }

    //使用转换输入流读取不同编码格式的文件
    @Test
    public void test06() throws Exception {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\File\\File.txt"),"GBK");
        char[] c = new char[1024];
        int len;
        while((len = isr.read(c)) != -1){
            System.out.println(new String(c,0,len));
        }
        isr.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 SpringMVC 中,我们可以通过 ResponseBody 注解返回音频流,具体步骤如下: 1. 在 Controller 中定义一个返回类型为 ResponseEntity<byte[]> 的方法,该方法需要使用 @ResponseBody 注解标注。 2. 在方法中获取音频文件的字节数组,并将其放入 ResponseEntity 对象中返回。 3. 在 ResponseEntity 对象中设置 Content-Type、Content-Disposition 等响应头,以便浏览器正确解析音频流并进行播放。 示例代码如下: ```java @RequestMapping("/audio") @ResponseBody public ResponseEntity<byte[]> getAudio() throws IOException { // 读取音频文件字节数组 InputStream in = getClass().getResourceAsStream("/static/audio/sample.mp3"); byte[] audioBytes = IOUtils.toByteArray(in); // 设置响应头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("audio/mpeg")); headers.setContentDispositionFormData("attachment", "sample.mp3"); // 返回音频流 return new ResponseEntity<>(audioBytes, headers, HttpStatus.OK); } ``` 上述代码中,我们将音频文件 sample.mp3 放在了项目的 /static/audio 目录下。在方法中,我们使用 IOUtils.toByteArray() 方法将音频文件转换为字节数组,并将其放入 ResponseEntity 对象中返回。在设置响应头时,我们使用 MediaType.parseMediaType() 方法设置 Content-Type,使用 setContentDispositionFormData() 方法设置 Content-Disposition。最后,我们通过 new ResponseEntity<>(audioBytes, headers, HttpStatus.OK) 创建 ResponseEntity 对象并返回。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值