JavaIO流详解
JavaIO流详解
I(Input:输入)/O(Output:输出)流,是java中用来传输数据的方式
流(stream)的概念
流是一种抽象概念,它代表了数据的无结构化传递
- 流是一个
无结构化
的数据组成的序列,以字节或字符形式输入或输出 - 流的输入:数据从
外部数据源流入到程序内部
,流的输出:数据从程序内部向外部流出到数据目的地
- 流的本质是进行
数据传输
,java根据数据传输的特性将流抽象成各种类,方便更直观地进行数据操作
流的分类
- 根据处理的数据类型的不同分为:
字节流
和字符流
(字节流以字节(Byte 1Byte=8bit)为单位,可以处理所有类型的数据,字符流以字符为单位,只能处理字符类型的数据。实际开发中主要使用字节流
) - 根据数据的流向的不同分为:
输入流
和输出流
- 根据处理数据功能分为:
节点流
和处理流
- 节点流(又叫实体流):对数据不做任何处理,只完成基本的读写操作。可以从一个特定的地方(节点)读写数据,直接连接数据源
- 处理流(又叫装饰流):在节点流的基础上提供更高级的功能。并不直接连接数据源,是对一个已存在的流的连接和封装,是一种典型的装饰器设计模式。
处理流不直接处理数据,套在节点流或已有的处理流上面
File类
File类(文件操作类):用来表示
计算机磁盘上的文件或目录的对象
- File类用于文件或目录的新建、文件的查找、文件的删除
- File类不能访问文件内容本身,如果需要读取或写入数据,必须使用IO流
- File类的对象常作为参数传递到流的构造器中
- java中表示一个真实存在的文件或目录就需要有一个File对象,但java中一个File对象,不一定对应一个真实存在的文件或目录
常用方法
构造方法:
public File(String pathname)
以pathname为路径创建File对象
方法:
获取方法:
public String getAbsolutePath()
获取绝对路径
public String getPath()
获取路径
public String getName()
获取名称
public String getParent()
获取上层文件目录路径
public Long length()
获取文件长度(字节数)
public Long lastModified()
获取最后一次修改的时间(时间戳)
public String[] list()
获取指定目录下所有文件和文件目录的名称数组
public File[] listFiles()
获取指定目录下所有文件和文件目录的File数组
判断方法:
public boolean isDirectory()
判断是否是文件目录
public boolean isFile()
判断是否是文件
public boolean exists()
判断是否存在
public boolean canRead()
判断是否可读
public boolean canWrite()
判断是否可写
public boolean isHidden()
判断是否隐藏
创建方法:
public boolean createNewFile()
创建文件,若文件存在则不创建,返回false
public boolean mkdir()
创建一级文件目录,若存在则不创建,返回false
public boolean mkdirs()
创建多级文件目录
删除方法:
public boolean delete()
删除文件或文件夹
常用常量
出于跨平台的考虑,使用常量表示不同系统的分隔符
File.separator
用来分隔同一路径字符串的分隔符(根据系统),windows是"\" linux是"/"
File.pathSeparator
用来分隔多个路径字符串的分隔符(根据系统),windows是“;” linux是":"
字节流
InputStream(输入字节流)
抽象类,表示字节输入流所有类的超类
方法
常用:
public abstract int read()
从输入流中读取下一个字节的数据
public int read(byte b[])
从输入流中读取一定数量的字节,并将它们存储到缓冲区数组b中
public int read(byte b[], int off, int len)
从输入流中读取最多len字节的数据到字节数组b中
public void close()
关闭此输入流并释放与该流关联的任何系统资源
不常用:
public int available()
返回可以从此输入流读取(或跳过)的字节数的估计值,而不会被该输入流的方法的下一次调用阻塞
public synchronized void mark(int readlimit)
标记此输入流中的当前位置
public boolean markSupported()
测试此输入流是否支持标记和重置方法
public synchronized void reset()
将此流重新定位到最后一次在此输入流上调用标记方法时的位置
public long skip(long n)
从输入流中跳过并丢弃n个字节的数据。
OutputStream(输出字节流)
抽象类,表示字节输出流所有类的超类
方法
public abstract void write(int b)
将指定的字节写入此输出流
public void write(byte b[])
从指定的字节数组中写入b.length长度个字节到此输出流
public void write(byte b[], int off, int len)
从指定的字节数组(offset off)开始将len字节写入此输出流
public void close()
关闭此输出流并释放与此流关联的任何系统资源
public void flush()
刷新此输出流并强制写入任何缓冲的输出字节
字符流
Reader(输入字符流)
用于读取字符流的抽象类
方法
常用:
public int read()
读取单个字符
public int read(char cbuf[])
将字符读入数组
abstract public int read(char cbuf[], int off, int len)
将字符读入数组的一部分
abstract public void close()
关闭流并释放与之关联的所有系统资源
不常用:
public int read(java.nio.CharBuffer target)
尝试将字符读入指定的字符缓冲区
public void mark(int readAheadLimit)
标记流中的当前位置
public boolean markSupported()
告知此流是否支持标记操作
public void reset()
重置流
public long skip(long n)
跳过n个字符
public boolean ready()
告诉该流是否准备好读取
Writer(输出字符流)
用于写入字符流的抽象类
方法
public void write(int c)
写入单个字符
public void write(char cbuf[])
写入一个字符数组
abstract public void write(char cbuf[], int off, int len)
写入字符数组的一部分
public void write(String str)
写入一个字符串
public void write(String str, int off, int len)
写入字符串的一部分
public Writer append(CharSequence csq)
将指定的字符追加到此写入器
public Writer append(char c)
将指定的字符序列追加到此写入器
public Writer append(CharSequence csq, int start, int end)
将指定字符序列的子序列追加到此写入器
abstract public void flush()
刷新此输出流
abstract public void close()
关闭此输出流并释放与此流关联的任何系统资源
使用流的代码示例
流程
-
创建数据源或目标对象
输入:把文件中的数据流入到程序中,文件是数据源,程序是目标
输出:把程序中的数据流出到文件中,文件是目标,程序是数据源
-
创建IO流对象(输入流或输出流)
-
IO操作(读、写、刷新、重置等操作)
-
关闭流资源(调用close方法)
实现文本数据压缩与解压
package com.test.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* gzip压缩类
*
* @author Administrator
*/
@Slf4j
@Component
public class GzipUtils {
/**
* 压缩
*
* @param text 文本数据
* @return 压缩数据
*/
public String gzipCompress(String text) {
if (StringUtils.hasText(text)) {
return null;
}
//节点流,直连数据源
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = null;
try {
//处理流套在节点流上
gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
//将字节数组写入压缩输出流
gzipOutputStream.write(text.getBytes());
//刷新输出流
gzipOutputStream.flush();
//在不关闭底层流的情况下完成将压缩数据写入字节输出流
gzipOutputStream.finish();
} catch (Exception e) {
log.error("e");
return null;
} finally {
try {
//关闭流资源
byteArrayOutputStream.close();
if (gzipOutputStream != null) {
gzipOutputStream.flush();
gzipOutputStream.close();
}
} catch (Exception e) {
log.error("", e);
}
}
//将输出流进行base64编码成字符串
return Base64Utils.encodeToString(byteArrayOutputStream.toByteArray());
}
/**
* 压缩 jdk1.7之后写法
* 在JDK7优化后的try-with-resource语句,该语句确保了每个资源,在语句结束时关闭。所谓的资源是指在程序完成后,必须关闭的流对象。
* 写在()里面的流对象对应的类都实现了自动关闭接口AutoCloseable
*
* @param text 文本数据
* @return base64
*/
public String gzipNewCompress(String text) {
if (StringUtils.hasText(text)) {
return null;
}
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
gzipOutputStream.write(text.getBytes());
gzipOutputStream.flush();
gzipOutputStream.finish();
return Base64Utils.encodeToString(byteArrayOutputStream.toByteArray());
} catch (Exception e) {
log.error("e");
return null;
}
}
/**
* 解压
*
* @param text 压缩数据
* @return 文本数据
*/
public String gzipDecompress(String text) {
if (StringUtils.hasText(text)) {
return null;
}
//输出流
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//base64解码
byte[] data = Base64Utils.decodeFromString(text);
//节点流,直连数据源
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
GZIPInputStream gzipInputStream = null;
try {
//处理流,套在节点流上
gzipInputStream = new GZIPInputStream(byteArrayInputStream);
//字节数组
byte[] buffer = new byte[256];
int len;
//将数据读入字节数组
while ((len = gzipInputStream.read(buffer)) != -1) {
//将len长度的字节从0偏移量开始写入字节数组输出流中
byteArrayOutputStream.write(buffer, 0, len);
}
} catch (Exception e) {
log.error("", e);
return null;
} finally {
try {
//关闭流资源
byteArrayInputStream.close();
byteArrayOutputStream.close();
if (gzipInputStream != null) {
gzipInputStream.close();
}
} catch (Exception e) {
log.error("", e);
}
}
//将字节数组转换成字符串输出
return byteArrayOutputStream.toString();
}
/**
* 解压 jdk1.7之后写法
* 在JDK7优化后的try-with-resource语句,该语句确保了每个资源,在语句结束时关闭。所谓的资源是指在程序完成后,必须关闭的流对象。
* 写在()里面的流对象对应的类都实现了自动关闭接口AutoCloseable
*
* @param text 压缩数据
* @return 文本数据
*/
public String gzipNewDecompress(String text) {
if (StringUtils.hasText(text)) {
return null;
}
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64Utils.decodeFromString(text));
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream)) {
byte[] buffer = new byte[256];
int len;
while ((len = gzipInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
return byteArrayOutputStream.toString();
} catch (Exception e) {
log.error("", e);
return null;
}
}
}
参考网址
https://www.cnblogs.com/furaywww/p/8849850.html
https://docs.oracle.com/javase/8/docs/api/index.html