From c3ee062a20e19a49c02dc51a949433b8154cf781 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 9 Jun 2018 23:03:31 +0800 Subject: [PATCH] auto commit --- notes/Java IO.md | 83 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index 885ecbe1..cf87cbfb 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -26,12 +26,12 @@ Java 的 I/O 大概可以分成以下几类: -1. 磁盘操作:File -2. 字节操作:InputStream 和 OutputStream -3. 字符操作:Reader 和 Writer -4. 对象操作:Serializable -5. 网络操作:Socket -6. 新的输入/输出:NIO +- 磁盘操作:File +- 字节操作:InputStream 和 OutputStream +- 字符操作:Reader 和 Writer +- 对象操作:Serializable +- 网络操作:Socket +- 新的输入/输出:NIO # 二、磁盘操作 @@ -51,39 +51,67 @@ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); DataInputStream 装饰者提供了对更多数据类型进行输入的操作,比如 int、double 等基本类型。 -批量读入文件内容到字节数组: +使用字节流操作进行文件复制: ```java -byte[] buf = new byte[20*1024]; -int bytes = 0; -// 最多读取 buf.length 个字节,返回的是实际读取的个数,返回 -1 的时候表示读到 eof,即文件尾 -while((bytes = in.read(buf, 0 , buf.length)) != -1) { - // ... +FileInputStream in = new FileInputStream("file/1.txt"); +FileOutputStream out = new FileOutputStream("file/2.txt"); +byte[] buffer = new byte[20 * 1024]; +// read() 最多读取 buffer.length 个字节,返回的是实际读取的个数 +// 返回 -1 的时候表示读到 eof,即文件尾 +while (in.read(buffer, 0, buffer.length) != -1) { + out.write(buffer); } +in.close(); +out.close; ``` # 四、字符操作 -不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,所以 I/O 操作的都是字节而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。 +不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。 -InputStreamReader 实现从文本文件的字节流解码成字符流;OutputStreamWriter 实现字符流编码成为文本文件的字节流。它们继承自 Reader 和 Writer。 +InputStreamReader 实现从文本文件的字节流解码成字符流;OutputStreamWriter 实现字符流编码成为文本文件的字节流。它们分别继承自 Reader 和 Writer。 + +逐行输出文本文件的内容: + +```java +FileReader fileReader = new FileReader("file/1.txt"); +BufferedReader bufferedReader = new BufferedReader(fileReader); +String line; +while ((line = bufferedReader.readLine()) != null) { + System.out.println(line); +} +// 装饰者模式使得 BufferedReader 组合了一个 Reader 对象 +// 在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法,因此只要一个 close() 调用即可 +bufferedReader.close(); +``` 编码就是把字符转换为字节,而解码是把字节重新组合成字符。 -```java -byte[] bytes = str.getBytes(encoding); // 编码 -String str = new String(bytes, encoding); // 解码 -``` - 如果编码和解码过程使用不同的编码方式那么就出现了乱码。 -- GBK 编码中,中文占 2 个字节,英文占 1 个字节; -- UTF-8 编码中,中文占 3 个字节,英文占 1 个字节; -- UTF-16be 编码中,中文和英文都占 2 个字节。 +- GBK 编码中,中文字符占 2 个字节,英文字符占 1 个字节; +- UTF-8 编码中,中文字符占 3 个字节,英文字符占 1 个字节; +- UTF-16be 编码中,中文字符和英文字符都占 2 个字节。 UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-16le,le 指的是 Little Endian,也就是小端。 -Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码正是为了让一个中文或者一个英文都能使用一个 char 来存储。 +Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。 + +String 可以看成一个字符序列,可以指定一个编码方式将它转换为字节序列,也可以指定一个编码方式将一个字节序列转换为 String。 + +```java +String str1 = "中文"; +byte[] bytes = str1.getBytes("UTF-8"); +String str2 = new String(bytes, "UTF-8"); +System.out.println(str2); +``` + +在调用无参数 getBytes() 方法时,默认的编码方式不是 UTF-16be。双字节编码的好处是可以使用一个 char 存储中文和英文,而将 String 转为 bytes[] 字节数组就不再需要这个好处,因此也就不再需要双字节编码。getBytes() 的默认编码方式与平台有关,一般为 UTF-8。 + +```java +byte[] bytes = str1.getBytes(); +``` # 五、对象操作 @@ -107,10 +135,10 @@ private transient Object[] elementData; Java 中的网络支持: -1. InetAddress:用于表示网络上的硬件资源,即 IP 地址; -2. URL:统一资源定位符,通过 URL 可以直接读取或者写入网络上的数据; -3. Sockets:使用 TCP 协议实现网络通信; -4. Datagram:使用 UDP 协议实现网络通信。 +- InetAddress:用于表示网络上的硬件资源,即 IP 地址; +- URL:统一资源定位符,通过 URL 可以直接读取或者写入网络上的数据; +- Sockets:使用 TCP 协议实现网络通信; +- Datagram:使用 UDP 协议实现网络通信。 ## InetAddress @@ -466,3 +494,4 @@ NIO 与普通 I/O 的区别主要有以下两点: - [NIO 与传统 IO 的区别](http://blog.csdn.net/shimiso/article/details/24990499) - [Decorator Design Pattern](http://stg-tud.github.io/sedc/Lecture/ws13-14/5.3-Decorator.html#mode=document) - [Socket Multicast](http://labojava.blogspot.com/2012/12/socket-multicast.html) +- [深入分析 Java 中的中文编码问题](https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/index.htm)