第17 章 : IO操作深入

80 字符编码

常用的编码

1、GBK/GB2312 国标编码, GB2312简体中文,GBK包含简体和繁体

2、ISO8859-1 国际通用编码,描述所有字母

3、UNICODE 16进制存储,描述所有问题

4、UTF 象形文字部分使用16进制,普通字母采用ISO8859-1,主要使用UTF-8

列出本机属性

System.getProperties().list(System.out);

项目中出现乱码问题就是编码和解码标准不统一

81 内存操作流

文件操作流 以文件为操作终端,InputStream、OutputStream

内存操作流

1、字节内存操作流 ByteArrayOutputStream ByteArrayInputStream

2、字符内存操作流 CharArrayWriter CharArrayReader

继承关系

OutputStream
-FileOutputStream
-ByteArrayOutputStream

InputStream
-FileInputStream
-ByteArrayInputStream

Writer
-OutputStreamWriter
-FileWriter
-CharArrayWriter

Reader
-InputStreamReader
-FileReader
-CharArrayReader

示例:利用内存流小写转大写操作

import java.io.*;

class Demo{
public static void main(String[] args) throws IOException {
String message = "hello java";

// 将数据保存到内存流中
InputStream input = new ByteArrayInputStream(message.getBytes());
OutputStream output = new ByteArrayOutputStream();

int data = 0;

// 每次读取一个数据
while ((data = input.read())!=-1){
output.write(Character.toUpperCase(data));
}

System.out.println(output);
// HELLO JAVA

output.close();
input.close();
}
}

82 管道流

发送信息 <- 管道 -> 接收信息

字节管道流 PipedInputStream, PipedOutputStream

字符管道流 PipedReader, PipedWriter

继承关系

InputStream
-PipedInputStream

OutputStream
-PipedOutputStream

Reader
-PipedReader

Writer
-PipedWriter

管道发送接收数据

import java.io.*;

class Sender implements Runnable {
private PipedOutputStream output;

public Sender() {
this.output = new PipedOutputStream();
}

@Override
public void run() {
try {
this.output.write("你好".getBytes());
} catch (IOException e) {
e.printStackTrace();
}

try {
this.output.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public PipedOutputStream getOutput() {
return this.output;
}
}

class Receiver implements Runnable {
private PipedInputStream input;

public Receiver() {
this.input = new PipedInputStream();
}

@Override
public void run() {

try {
byte[] data = new byte[1024];
int len = this.input.read(data);
System.out.println(new String(data, 0, len));
// 你好

} catch (IOException e) {
e.printStackTrace();
}

try {
this.input.close();
} catch (IOException e) {
e.printStackTrace();
}

}

public PipedInputStream getInput() {
return this.input;
}
}

class Demo {
public static void main(String[] args) throws IOException {
Sender sender = new Sender();
Receiver receiver = new Receiver();

// 管道连接
sender.getOutput().connect(receiver.getInput());

new Thread(sender).start();
new Thread(receiver).start();
}
}

83 RandomAccessFile

随机读取类,可以移动文件指针

public RandomAccessFile(String name, String mode)
import java.io.*;

class Demo {
public static void main(String[] args) throws IOException {
// 写入
RandomAccessFile writer = new RandomAccessFile("demo.txt", "rw");
writer.write("你好世界".getBytes());
writer.close();

// 读取
RandomAccessFile reader = new RandomAccessFile("demo.txt", "rw");
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}

writer.close();
}
}

第18 章 : 输入与输出支持

84 打印流

设计思想:装饰设计模式

为OutputStream 类实现一层包装

PrintStream

PrintWriter

继承关系

OutputStream
-FilterOutputStream
-PrintStream
Writer
-PrintWriter
import java.io.*;

class Demo {
public static void main(String[] args) throws IOException {

PrintWriter writer = new PrintWriter(new FileWriter("demo.txt"));

// 换行输出
writer.println("你好");

// 格式化输出
writer.printf("姓名 %s, 年龄: %s", "小强", 23);

writer.close();
}
}

只要是文件内容输出时都使用打印流

85 System类对IO的支持

System是系统类

1、标准输出(显示器)

2、错误输出

3、标准输入(键盘)

public final class System {
public final static InputStream in = null;
public final static PrintStream out = null; // 黑色字体
public final static PrintStream err = null; // 红色字体
}

修改输出位置

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

class Demo {
public static void main(String[] args) throws IOException {
System.setErr(new PrintStream(new FileOutputStream(new File("demo.txt"))));
System.err.println("你好");
}
}

接收键盘输入(一般不用此方法)

import java.io.IOException;
import java.io.InputStream;

class Demo {
public static void main(String[] args) throws IOException {
InputStream input = System.in;
System.out.println("请输入姓名:");
byte[] data = new byte[1024];
int len = input.read(data);

System.err.println(new String(data, 0, len));
}
}

86 BufferedReader缓冲输入流

JDK < 1.5

缓冲字符输入流

继承关系

Reader
-BufferedReader

代码示例

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Demo {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入:");
String msg = reader.readLine();
System.out.println(msg);
}
}

87 Scanner扫描流

JDK > 1.5

替代BufferedReader

构造函数

判断是否有数据 public boolean hasNext()

读取数据 public String next()

设置分隔符

import java.io.IOException;
import java.util.Scanner;

class Demo {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入年龄:");
if(scanner.hasNextInt()){
int age = scanner.nextInt();
System.out.println("您输入的年龄是:" + age);
} else{
System.out.println("输入不正确");
}
scanner.close();
}
}

可以结合正则进行判断验证

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

class Demo {
public static void main(String[] args) throws ParseException {
Scanner scanner = new Scanner(System.in);

System.out.println("请输入生日:");
if (scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
String msg = scanner.next("\\d{4}-\\d{2}-\\d{2}");
System.out.println("您输入的年龄是:" + new SimpleDateFormat("yyyy-MM-dd").parse(msg));
} else {
System.out.println("输入不正确");
}

scanner.close();
}
}

读取文件

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

class Demo {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("demo.txt"));

// 设置换行分隔符
// scanner.useDelimiter("\n");

while (scanner.hasNext()) {
System.out.println(scanner.next());
}

scanner.close();
}
}

开发中:

输出使用PrintWriter打印流

输入使用Scanner扫描流

第19 章 : 对象序列化

88 对象序列化基本概念

对象序列化:

将内存中保存的对象以二进制数据的形式处理,

实现对象的保存或者网络传输

保存到文件
堆内存 - 二进制转换 -> 保存到数据库
发送到服务器

要序列化的对象必须实现java.io.Serializable 接口

没有任何方法,只是描述一种能力

示例

import java.io.Serializable;


class Person implements Serializable {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}
}

89 序列化与反序列化处理

继承关系

InputStream(ObjectInput, ObjectStreamConstants)
-ObjectInputStream

OutputStream(ObjectOutput, ObjectStreamConstants)
-ObjectOutputStream

代码示例

import java.io.*;

class Person implements Serializable {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}
}

class Demo {
private static final File SAVE_FILE = new File("demo.person");

public static void main(String[] args) throws IOException, ClassNotFoundException {
Person person = new Person("Tom", 23);
// saveObject(person);

System.out.println(loadObject());
// Person@15aeb7ab
}

// 序列化
public static void saveObject(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oos.writeObject(obj);
oos.close();
}

// 反序列化
public static Object loadObject() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj = ois.readObject();
ois.close();
return obj;
}
}

实际开发中不直接操作ObjectInputStream、ObjectOutputStream

90 transient关键字

表示进行序列化处理时,不处理被transient关键字修饰的字段

不常用,知道即可

IO继承体系整合

// 字节流:
OutputStream(Closeable, Flushable)
-FileOutputStream
-ByteArrayOutputStream
-PipedOutputStream
-FilterOutputStream
-PrintStream
-ObjectOutputStream


InputStream(Closeable)
-FileInputStream
-ByteArrayInputStream
-PipedInputStream
-ObjectInputStream

// 字符流:
Writer(Appendable, Closeable, Flushable)
-OutputStreamWriter
-FileWriter
-CharArrayWriter
-PipedReader
-PrintWriter
-BufferedWriter

Reader(Readable, Closeable)
-InputStreamReader
-FileReader
-CharArrayReader
-PipedWriter
-BufferedReader