标签:unicode 复制 buffer 方法 后缀 路径 nbsp 机器 有一个
参考资料:郝斌老师的Java学习视频
一,流和四大基本抽象流
* 流的定义
流:用于输入输出的类
流:程序和设备之间连接起来的一根用于数据传输的管道,这个管道上有很多按钮,不用的按钮可以实行不同的功能
管道 = 口径 + 方向
* 流的分类
数据的流向| 输入流 处理数据的单位| 字节流 功能 | 节点流(原始流)
| 输出流 | 字符流 | 处理流(包裹流)
所有的流类型都位于 包java.io内,且都分别继承以下四种抽象流类型:
字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
* 节点流和处理流
节点流:可以从一个特定的数据源(节点)读写数据。(注意:数据源和数据汇是不同的,数据源有:文件,内存,键盘等)
处理流:是“包裹”在已存在的流(节点流和处理流皆可)之上,通过对数据的处理为程序提供更为强大的读写功能。
* java 中一个字符占两个字节
* 凡是以 sream 结尾的都是字节流
* InputStream流 中常用的方法
public int read() throws IOException
读取一个字节并以整数形式返回
如果读取到输入流的末尾则返回-1
public int read(byte b[]) throws IOException
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中,以整数形式返回实际读取的字节数
如果因为读取到文件末尾而没有可用的字节,则返回 -1
例子:len = fis.read(buf)
len 并不总与 buf 长度一致,如:buf 1000字节,文件 1024字节,第一次 len = 1000,第二次读不完整就 len = -1
public int read(byte b[], int off, int len) throws IOException
从输入流中最多读取 len 字节的数据并存入 byte 数组中,读取的第一个字节存储在 b[off] 中
public void close() throws IOException
关闭此输入流并释放与该流关联的所有系统资源
* OutputStream流 中常用的方法
public void write(int b) throws IOException
向输出流中写入一个字节数据,该字节数据为参数 b 的低八位
public void write(byte b[]) throws IOException
将一个字节类型的数组中数据写入输出流
public void write(byte b[], int off, int len) throws IOException
将一个字节类型的数组中的从指定位置(off)开始的 len 个字节写入到输出流
public void close() throws IOException
关闭流释放的内存资源
public void flush() throws IOException
将输出流中缓冲的数据全部写出到目的地
* Reader流 中常用的方法
public int read() throws IOException
读取一个字符并以整数形式返回
如果读取到输入流的末尾则返回-1
public int read(char cbuf[]) throws IOException
从输入流中读取一定数量的字符,并将其存储在缓冲区数组 cbuf 中,以整数形式返回实际读取的字符数
如果因为读取到文件末尾而没有可用的字符,则返回 -1
public int read(char cbuf[], int off, int len) throws IOException
从输入流中最多读取 len 字符的数据并存入 cbuf 数组中,读取的第一个字符存储在 cbuf[off] 中
public void close() throws IOException
关闭此输入流并释放与该流关联的所有系统资源
* Writer流 中常用的方法
public void write(int c) throws IOException
向输出流中写入一个字符数据,该字节数据为参数 b 的低16位
public void write(char cbuf[]) throws IOException
将一个字符类型的数组中数据写入输出流
public void write(char b[], int off, int len) throws IOException
将一个字符类型的数组中的从指定位置(off)开始的 len 个字符写入到输出流
public void close() throws IOException
关闭流释放的内存资源
public void flush() throws IOException
将输出流中缓冲的数据全部写出到目的地
二,字节流和字符流
* 用字节流读取文本的话,会出现中文乱码,因为中文占两个字节,用字节流读取,就会被从中间截断。
而用字符流的话,一个字符刚好等于一个中文的大小,刚好一一对应。
* 用字符流读写 MP3等不是文本的文件时,会因为编码的原因导致错误
如:文件中有 字符"ab" (这部分我大概率理解错了)
字符流读取 int ch = fr.read(),然后再用 fw.write(ch);这个 ch 是由‘b‘组成 ch 的0~7位,‘a‘组成接下来的8~15位
字节流读取 int c1 = fis.read(),c2 = fis.read(),然后再用 fos.write(c1),fos.write(c2);这个 c1 是由‘a‘组成低八位,c2是由‘b‘组成低八位
因为读取的不同,写入的数据自然不同,其实字符流和字节流的写入都是将 int 对应的 Unicode 编码写入对应数据汇中.
显然,ch 对应的 Unicode编码 和 c1 和 c2 对应的 Unicode 编码是不一样的,所以写入的时候也就不一样了。
所以字符流写入的时候就会发生错误
* 综上:文本文件 用字节流,非文本文件 用字符流
* 文件的后缀名决定文件的编码方式
* 缓冲区:先将读取的字符写入缓冲区,等缓冲区满了再全部读入,这样就不用读一个字符/字节,输入一个字符/字节(可以减少读取硬盘的次数,延长硬盘使用寿命),还可以提高写的速度
如果,你没有先调用 flush() 直接调用 close(),则会造成缓冲区的字符/字节 没有读入直接关闭(然而,close() 好像就会自动调用 flush()
所以输出流要 先 flush(),再 close()
三,文件流
* FileInputStream FileOutputStream
* FileReader FileWriter
* FileInputStream
* InputStream 是用来读取字节的,是个抽象类,我们通常使用的是该类的子类
* FilelnputStream 是 InputStream 的子类,利用 FilelnputStream 可以将一个文件的内容按字节为单位读取出来
* FilelnputStream有一个很常用的构造函数
public FilelnputStream(String fileName) throws FileNotFoundException
利用该构造函数可以实现将输入流连接到某个文件的功能
必须对本构造函数抛出的异常进行捕捉
如果用字符串来表示操作系统的文件路径时,我们可以使用 \\ 和 / 两种方式来作为文件夹的路径分隔符
* FileOutputStream 同理
* FileReader
* Reader 是用来读取字符的,是个抽象类,我们通常使用的是该类的子类
* FileReader 是 Reader 的子类,利用 FileReader 可以将一个文件的内容以字符为单位读取出来
* FileReader有一个很常用的构造函数
public FileReader(String fileName) throws FileNotFoundException
利用该构造函数可以实现将输入流连接到某个文件的功能
必须对本构造函数抛出的异常进行捕捉
如果用字符串来表示操作系统的文件路径时,我们可以使用 \\ 和 / 两种方式来作为文件夹的路径分隔符
* FileWriter 同理
* FileInputStream 和 FileOutputStream 可以完成所有格式文件的赋值
* FileReader 和 FileWriter 只可以完成文本文件的复制,却无法完成视频格式文件的复制
* 因为字节是不需要解码和编码的,将字节转化为字符才存在解码和解码的问题
* 字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据
四,缓冲流概述
缓冲流就是带有缓冲区的输入输出流
缓冲流可以显著的减少我们对IO访问的次数,保护我们的硬盘!
缓冲流本身就是处理流(处理流也叫包裹流),缓冲流必须得依附于节点流(节点流也叫原始流)
处理流是包裹在原始节点流上的流,相当于包括在管道上的管道!
* 缓冲流要"套接"在相应的节点流之上, 对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。
* J2SDK提供了四种缓存流,其常用的构造方法为:
BufferedReader (Reader in)
BufferedReader (Reader in, int sz) //sz 为自定义缓存区的大小
Bufferedwriter (writer out)
Bufferedwriter (Writer out, int sz)
BufferedInputstream (Inputstream in)
BufferedInputStream (Inputstream in, int size)
Buffered0utputstream (0utputStream out)
Buffered0utputstream (0utputstream out, int size)
* 缓冲输入流支持其父类的 mark 和 reset 方法。
* BufferedReader 提供了 readLine方法 用于读取一行字符串(以\r或\n分隔)
* BufferedWriter 提供了 newline方法 用于写入一个行分隔符。
* 对于输出的缓冲流,写出的数据会先在内存中缓存,使用 flush方法 将会使内存中的数据立刻写出。
* 只有
BufferedInputStream
BufferedOutputStream类
BufferedWriter
BufferedReader
* 没有
BufferedStream
BufferedFilelnputStream (但有 FileOutputStream )
BufferredFileOutputStream (但有 FileInputStream )
BufferedFileReader (但有 FileReader )
BufferedFileWriter (但有 FileWriter )
* BufferedOutputStream:带缓冲的输出流,允许一次向硬盘写入多个字节的数据
* BufferedInputStream:带缓冲的输入流,允许一次向程序中读入多个字节的数据
* BufferedReader:带缓冲的输出流,允许一次向硬盘写入多个字符的数据
* BufferedWriter:带缓冲的输入流,允许一次向程序中读入多字符的数据
* BufferedOutputStream 和 BufferedInputStream 都是包裹流,必须的依附于 OutputStream 和 InputStream
* BufferedReader 和 BufferedWriter 都是包裹流,必须的依附于 Reader 和 Writer
*
* BufferedInputStream流 中有
public int read(byte[] b)方法:把从当前流关联到的设备中读取出来的数据存入一个 byte数组 中
BufferedOutputStream流 中有
public int write(byte[] b)方法:把 byte数组 中的数据输出到当前流所关联到的设备中
* 如果我们希望用 BufferedInputStream 和 BufferedOutputStream 完成“将一个 设备中的数据导入另一个设备中”,
我们就应 该定义一个临时的byte类型的数组,用这个临时数组作为输入流与输出流进行交互的中转枢纽!
* Reader,FileReader,InputStream,FilelnputStream
和 BufferedInputStream流 中都没有 readLine方法
DatalnputStream流 中有 readLine方法,但已经被标记为过时
* BufferedReader流 中有 readLine方法, 并且该方法是可以正确被使用的
五,数据流
* 数据流 (凡是以 Data 结尾的都是数据流)
* DataInputStream
* 它能够以一种与机器无关的方式,直接从底层字节输入流读取Java基本类型和Sring类型的数据。
* 常用方法包括:
public DatalnputStream(InputStream in)
public final boolean readBoolean()
public final byte readByte()
public final char readChar()
public final double readDouble()
public final float readFloat()
public final int readlnt()
public final long readLong()
public final short readShort()
public final String readUTF0
DatalnputStream 是包裹流,必须依附于 InputStream
* DataOutputStream
* 它能够以一种与机器无关的方式,直接将Java基本类型和String类型数据写出到其他的字节输出流。
* 常见方法:
public DataOutputStream(OutputStream in)
public final boolean writeBoolean()
public final byte writeByte()
public final char writeChar()
public final double writeDouble()
public final float writeFloat()
public final int writelnt()
public final long writeLong()
public final short writeShort()
public final String writeUTF()
DataOutputStream 是包裹流,必须依附于 OutputStream
* 数据流实例
* 编程实现将 long类型 数据写入byte数组,然后再从byte数组中把该数据读出来
附注:
这是Socket编程中经常要完成的功能,因为网络编程中经常要把数值型数据存入byte数组中,
然后把byte数组打包成数据包(即DatagramPacket),再把数据包经过网络传输到目的机,
目的机再从byte数组中把原数值型数据还原回来
* 本程序要使用到:
ByteArrayInputStream,ByteArrayOutputStream
DatalnputStream,DataOutputStream
因为其它流是没有读取 long类型数据 的方法
六,转换流
* OutputStreamWriter流 是把 OutputStream 转化成 Writer 的流
* InputStreamReader流 是把 InputStream 转化成 Reader 的流
* IutputStreamWriter 和 InputStreamReader 都是包裹流
* 例子:将键盘输入的字符组成字符串直接赋给String对象
* readLine()与回车符的问题
* 如果直接输入回车的话,则.
1. br.readLine() 会丢弃回车符,而不是返回回车符,即
br.readLine()遇到回车符时终止读取,并且会把读取到的回
车符自动丢弃掉
2. br.readLine() 返回的是“”而不是null,“”表示空字符串
null表示空指针,空指针就是空地址,空地址就是不指向任何存储单元的意思
七,Print流
* Print流只有输出,没有输入
* 分类:
PrintWrite 输出字符
PrintStream 输出字节
* 各种输出流的比较:
Writer 的 write 方法可以写入
一个字符
一个字符数组
一个字符数组的一部分
一个字符串
一个字符的一部分
OutputStream 的 write 方法可以写入:
一个字节
一个字节数组
一个字节数组的一部分
DataOutputStream 可以写入
一个字节
一个字节数组(继承自 OutputStream)
一个字节数组的一部分
所有的基本类型数据的二进制代码
如: writeDouble(8.8); 写入的是8.8的二进制代码,共占8个字节
PrintStream 流的 print 可以写入
所有基本类型数据的字符串形式表示
如: print(8.8); 写入的是‘8‘"‘8‘这三个字符,共占3个字节
* PrintStream
* PrintStream 在OutputStream基础之上提供了增强的功能,即可以方便地输出各种类型数据(而不仅限于byte型)的格式化表示形式。
* PrintStream 重载了print和println方法,用于各种不同类型数据的格式化输出
* 格式化输出是指将一个数据用其字符串格式输出
* 不同的输入流的输入方式是不同:
DataOutputStream 中的 writeXXX(data)方法是把data在内存中的二进制数据写入文件
PrintStream 中的 println(data)写出的是该数据的格式化后的字符串
* PrintWriter
* PrintWriter 提供了PrintStream的所有打印方法,其方法也从不抛出IOException
* 与PrintStream的区别:
作为处理流使用时,
PrintStream只能封装OutputStream类型的字节流,
PrintWriter既可封装OutputStream,还能够封装 Writer
* PrintWriter中的println()方法具有更好的跨平台性
* 标准输入输出的重定向
* out 是 PrintStream流
err 是 PrintStream流
in 是 InputStream流
* e.printStackTrace(); // 默认把错误信息输出到 System.err 所关联的设备
八,object
* 对象的序列化
* 所谓序列化是指:把一个Object对象直接转化为字节流,然后把这个字节流直接写入本地硬盘或网络中
* 如果要想把某个对象序列化,则必须的实现Serializable接口
* Serializable接口中并没有任何方法,该接口被称为标记接口。
如果一个类实现了Serializable接口,潜在含义就是告诉编译器这个类是允许被序列化的。
如果程序中存在序列该对象的代码,编译器就会自动进行相应的处理已完成该对象的序列化;
如果该对象没有实现Serializable接口,程序中却存在该对象被序列化的代码,编译器编译时就会报错!
* 在Java中 transient 修饰的成员变量在对象序列化时不被序列化
========= ======== ======= ====== ===== ==== === == =
标签:unicode 复制 buffer 方法 后缀 路径 nbsp 机器 有一个
原文地址:https://www.cnblogs.com/asdfknjhu/p/14608881.html