什么是IO
一般Android
中,认为的io
是java IO
,Java IO
也称为IO流
,IO = 流,它的核心就是对文件的操作,对于 字节 、字符类型的输入和输出流。
IO是指对数据流的输入和输出,也称为IO流,IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。
IO流的本质是数据传输,并且流是单向的。
常用的字节流FileInputStream
、FileOutputStream
、ObjectInputStream
、ObjectOutputStream
IO分阻塞型IO和非阻塞型IO(NIO)
阻塞型IO在读取数据时,如果数据未到达,会一直阻塞到读取到数据为止,所以称为阻塞型IO,在高并发的环境下性能不佳。
NIO
不是使用 “流” 来作为数据的传输方式,而是使用通道,通道的数据传输是双向的,且NIO
的数据写入和读取都是异步的,不会阻塞线程,所以称为非阻塞型IO,在高并发的环境下性能很好。但是,NIO
只是支持非阻塞式,默认还是阻塞式,只有在网络交互时支持非阻塞式,文件交互不支持。基于这些特性,基本上,在日常的Android开发中,很少见到NIO
的身影
什么是流?
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在设备间传输称之为流。
本质是数据传输,根据数据传输的特性将流区分为各种类,方便更直观的进行数据操作。
- 数据处理的不同类型分为:字节流和字符流
- 数据流向不同分为:输入流和输出流
什么是字节流?
程序中的输入输出都是以流
的形式保存的(输入流or输出流),流中保存的实际上全都是字节
(一个字节等于一个Byte
占8个bit
)文件。Java提供了OutputStream
、InputStream
两个专门操作字节流的类。
知识补充1:
计算机能存储的唯一东西就是bytes
,为了在计算机中存储东西,我们首先得将其编码(encode),例如将其转化为bytes
。
比如:要想保存音乐(以字节形式保存),我们首先得用 MP3, WAV 等将其编码;要想保存图片,我们首先得用 PNG, JPEG 等将其编码;要想保存文本,我们首先得用 ASCII, UTF-8 等将其编码.
知识补充2:
Unicode 是字符集,不是字符编码。Unicode 把全世界的字符都搜集并且编号了,但是没有规定具体的编码规则。编码规则有 UTF-8、GBK等。
字节流适合
所有类型文件
的数据传输,因为字节(Byte)是电脑中表示信息含义的最小单位(通常情况下一个ACSII码就是一个字节的空间来存放)。
什么是字符流?
字符流按字符(一个字符占两个字节)读数据:一次读两个字节,返回了这两个字节所对应的字符的int型数值(编码)。写入文件时把这两个字节的内容解码
成这个字符在Unicode
码下对应的二进制数据写入。即把原始文件中的二进制数据以字符形式读出,再将字符以二进制形式写入,所以得到的文件以字符方式存储。字符流只能处理字符或者字符串。Java提供了Writer
、Reader
两个专门操作字节流的类。
字符流只能够处理纯文本(中文)数据,其他类型数据不行,但是字符流处理文本要比字节流处理文本要方便。
字节流跟字符流的区别
1.字节流没有使用到缓冲区(内存),是与文件本身直接操作的。字符流使用到了缓冲区,在缓冲区的数据需要使用close()
或者flush()
方法强制刷新缓冲区将其输出(程序没有关闭数据是不会从缓冲区输出出来的)。
2.字节流在操作文件时,即使不关闭资源(close
方法),文件也能输出,但是如果字符流不使用close
方法的话,则不会输出任何内容。
3.在所有的硬盘
上保存文件或进行传输的时候都是以字节
的方法进行的,包括图片也是按字节完成,而字符
是只有在内存
中才会形成的,所以使用字节
的操作是最多
的。
4.字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以处理。
5.流按字节读数据,而字节不需要编码、解码,只有字节与字符之间转换时才需要编码、解码!
字节流与字符流的转换
在jdk中,提供了两个类用于实现将字节流转化为字符流,分别为InputStreamReader和OutputStreamWriter。InputStreamReade是Reader的子类,它可以将一个字节输入流转化为字符输入流,方便直接读入字符。OutputStreamWriter是Writer的子类,它将字节输出流转化为字符输出流,方便直接写入字符。
转换流的原理是:字符流 = 字节流 + 编码表。 在转换流中选择正确的编码非常的重要,因为指定了编码,它所对应的字符集自然就指定了,否则很容易出现乱码,所以编码才是我们最终要关心的。
转换流的特点:其是字符流和字节流之间的桥梁。
-
可对读取到的字节数据经过指定编码转换成字符
-
可对读取到的字符数据经过指定编码转换成字节
那么何时使用转换流?
-
当字节和字符之间有转换动作时
-
流操作的数据需要编码或解码时
fun ioWrite() {
try {
FileOutputStream(filePath).use { fileOutputStream ->
OutputStreamWriter(fileOutputStream,"GBK").use {
it.write("java hello")
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
fun ioRead() {
try {
FileInputStream(filePath).use { fileInputStream ->
InputStreamReader(fileInputStream).use {
val charArray = CharArray(1024)
val len = it.read(charArray)
println(String(charArray, 0, len))
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
常用的IO实例
1、字节流写文件
fun ioWrite() {
try {
//use会自动调用close
FileOutputStream(filePath).use { fileOutputStream ->
fileOutputStream.write('h.toInt())
fileOutputStream.write('a'.toInt())
}
} catch (e: IOException) {
e.printStackTrace()
}
}
2、字节流读文件
fun ioRead() {
try {
FileInputStream(filePath).use { fileInputStream ->
println(fileInputStream.read().toChar())
println(fileInputStream.read().toChar())
}
} catch (e: IOException) {
e.printStackTrace()
}
}
3、字节流加入buffer写文件
fun ioBufferWrite() {
try {
FileOutputStream(filePath).use { fileOutputStream ->
BufferedOutputStream(fileOutputStream).use {
it.write('c'.code)
it.write('b'.code)
it.flush()
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
4、字节流加入buffer读文件
fun ioBufferRead() {
try {
FileInputStream(filePath).use { fileInputStream ->
BufferedInputStream(fileInputStream).use {
println(it.read().toChar())
println(it.read().toChar())
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
5、字符流写文件
fun ioWriter() {
try {
FileWriter(filePath).use {
val str = "hello haha"
it.write(str)
}
} catch (e: IOException) {
}
}
6、字符流读文件
fun ioReader() {
try {
FileReader(filePath).use {
val charArray = CharArray(1024)
val len = it.read(charArray)
println(String(charArray, 0, len))
}
} catch (e: IOException) {
}
}
7、复制文件
fun ioCopyFile() {
try {
BufferedInputStream(FileInputStream(filePath)).use { inputStream ->
BufferedOutputStream(FileOutputStream(copyFilePath))
.use { outputStream ->
val data = ByteArray(1024)
var read: Int
while (inputStream.read(data).also { read = it } != -1) {
outputStream.write(data, 0, read)
}
}
}
} catch (e: FileNotFoundException) {
} catch (e: IOException) {
}
}