JavaIO流基础以及如何实现文件下载

20 阅读3分钟

详细的都在这里,以下是为了方便我快速复习

javaguide.cn/java/io/io-…

简单介绍:

`InputStream` 常用方法:
  • read():返回输入流中下一个字节的数据。返回的值介于 0 到 255 之间。如果未读取任何字节,则代码返回 -1 ,表示文件结束。
  • read(byte b[ ]) : 从输入流中读取一些字节存储到数组 b 中。如果数组 b 的长度为零,则不读取。如果没有可用字节读取,返回 -1。如果有可用字节读取,则最多读取的字节数最多等于 b.length , 返回读取的字节数。这个方法等价于 read(b, 0, b.length)
  • read(byte b[], int off, int len):在read(byte b[ ]) 方法的基础上增加了 off 参数(偏移量)和 len 参数(要读取的最大字节数)。
  • skip(long n):忽略输入流中的 n 个字节 ,返回实际忽略的字节数。
  • available():返回输入流中可以读取的字节数。
  • close():关闭输入流释放相关的系统资源。

OutputStream用于将数据(字节信息)写入到目的地(通常是文件),java.io.OutputStream抽象类是所有字节输出流的父类。

OutputStream 常用方法:

  • write(int b):将特定字节写入输出流。
  • write(byte b[ ]) : 将数组b 写入到输出流,等价于 write(b, 0, b.length)
  • write(byte[] b, int off, int len) : 在write(byte b[ ]) 方法的基础上增加了 off 参数(偏移量)和 len 参数(要读取的最大字节数)。
  • flush():刷新此输出流并强制写出所有缓冲的输出字节。
  • close():关闭输出流释放相关的系统资源。

除了以上两个父类对象还有字符输出流以及字节输入流,他们直接读取字节单位,这属于父类接口,开发中我们常用的很多都是衍生接口

缓冲字节输出输入流的含义,普通字节输入输出流每次io操作一个字节一个子节的传递,再遇到大文件时会产生产生多次io操作,缓冲的含义就是在这其中增加了一个储存空间,当缓冲空间满了一次传输完整个字节流,减少了Io操作

上面的方法是最基础的父类 项目开发中则使用FileInputStream 和 FileOutputStream 可以方便的读取文件字节流和输出字节流

try (FileOutputStream output = new FileOutputStream("output.txt")) {
    byte[] array = "JavaGuide".getBytes();
    output.write(array);
} catch (IOException e) {
    e.printStackTrace();
}
try (InputStream fis = new FileInputStream("input.txt")) {
    System.out.println("Number of remaining bytes:"
            + fis.available());
    int content;
    long skip = fis.skip(2);
    System.out.println("The actual number of bytes skipped:" + skip);
    System.out.print("The content read from file:");
    while ((content = fis.read()) != -1) {
        System.out.print((char) content);
    }
} catch (IOException e) {
    e.printStackTrace();
}

ObjectInputStream 用于从输入流中读取 Java 对象(ObjectInputStream,反序列化),ObjectOutputStream将对象写入到输出流(ObjectOutputStream,序列化)。

ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("file.txt")
Person person = new Person("Guide哥", "JavaGuide作者");
output.writeObject(person);

tips:深拷贝对象也可以通过这种方式实现。

io实现浏览器文件下载功能:

注意如果是中文的文件称也可能会出现乱码问题,要指定字符据编码

实现流程就是获取服务器端文件路径,用文件输入字节流读取文件 再用 输出流输出字节流给浏览器大致流程代码如下

//获取到资源的路径
String path = this.getServletContext().getRealPath("/download/1.png");

//读取资源
FileInputStream fileInputStream = new FileInputStream(path);

//获取到文件名,路径在电脑上保存是\\形式的。
String fileName = path.substring(path.lastIndexOf("\\") + 1);

告诉浏览器,这个文件需要下载

//设置消息头,告诉浏览器,我要下载1.png这个图片
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
//中文的话指定文件名字符集编码
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
  • 将读取到的内容回送给浏览器
  • 这里手动添加了缓冲空间,自己改成缓存字节流也可以实现
//把读取到的资源写给浏览器
int len = 0;
//缓冲1kb
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();

while ((len = fileInputStream.read(bytes)) > 0) {
    servletOutputStream.write(bytes, 0, len);
}

//关闭资源
servletOutputStream.close();
fileInputStream.close();