1.字符的编码解码
windows 默认使用码表为 GBK,一个字符两个字节。
IDEA 和以后工作默认使用 Unicode 的 UTF-8 编解码格式,一个中文三个字节。
package com.qdu;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class CharStreamDemo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
// byte[] getBytes() 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
// byte[] getBytes(String charsetName) 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
String s = "黑马程序员";
// 利用idea默认的UTF-8将中文编码为一系列的字节
byte[] bytes1 = s.getBytes();
System.out.println(Arrays.toString(bytes1));
// 利用gbk将中文编码为一系列的字节
byte[] bytes2 = s.getBytes("GBK");
System.out.println(Arrays.toString(bytes2));
// String(byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组来构造新的String
// String(byte[] bytes, String charsetName) 通过指定的字符集解码指定的字节数组来构造新的String
// 利用默认的UTF-8进行解码
String s1 = new String(bytes1);
System.out.println(s1);
// 利用GBK进行解码
String s2 = new String(bytes2, "gbk");
System.out.println(s2);
}
}
因为字节流一次读一个字节,而不管GBK还是UTF-8一个中文都是多个字节,用字书流每次只能读其中的一部分,所以就会出现乱码问题。
2.字符流
字符流 = 字节流 + 编码表
不管是在哪张码表中,中文的第一个字节一定是负数。
想要进行拷贝,一律使用字节流或者字节缓冲流。
想要把文本文件中的数据读到内存中,请使用字符输入流。
想要把内存中的数据写到文本文件中,请使用字符输出流。
2.1 字符输出流:写数据
package com.qdu;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo3 {
public static void main(String[] args) throws IOException {
// 1.创建字符输出流的对象
// FileWriter fw = new FileWriter(new File("charstream\\a.txt"));
FileWriter fw = new FileWriter("a.txt");
// 2.写数据
// void write(int c) 写一个字符
// fw.write(97);
// fw.write(98);
// fw.write(99);
// void write(char[] cbuf) 写一个字符数组
// char[] chars = {97, 98, 99, 100, 101};
// fw.write(chars);
// void write(char[] cbuf, int off, int len) 写字符数组的一部分
// char[] chars = {97, 98, 99, 100, 101};
// fw.write(chars, 0, 3);
// void write(String str) 写一个字符串
// String line = "加油abc";
// fw.write(line);
// void write(String str, int off, int len) 写一个字符串的一部分
String line = "加油abc";
fw.write(line, 0, 2);
// 3.释放资源
fw.close();
}
}
package com.qdu;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo5 {
public static void main(String[] args) throws IOException {
// flush() 刷新流,刷新完毕之后,还可以继续写数据
// close() 关闭流,释放资源,关闭之前会刷新流,一旦关闭,就不能写数据
FileWriter fw = new FileWriter("a.txt");
fw.write("虎年大吉");
fw.flush();
fw.write("666");
fw.flush();
fw.close();
// fw.write("aaa"); // 报错:Stream closed
}
}
2.2 字符输入流:读数据
示例1:一次读取一个字符
package com.qdu;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo6 {
public static void main(String[] args) throws IOException {
// 创建字符输入流的对象
// FileReader fr = new FileReader(new File("a.txt"));
FileReader fr = new FileReader("a.txt");
// 读取数据
int ch;
while ((ch = fr.read()) != -1) {
System.out.println((char) ch);
}
// 释放资源
fr.close();
}
}
示例2:一次读取多个字符
package com.qdu;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo7 {
public static void main(String[] args) throws IOException {
// 创建对象
FileReader fr = new FileReader("a.txt");
// 创建一个数组
char[] chars = new char[1024];
int len;
// 一次读取多个字符,把读到的字符都存入到chars数组中
// 返回值:表示本次读到了多少个字符
while ((len = fr.read(chars)) != -1) {
System.out.println(new String(chars, 0, len));
}
fr.close();
}
}
2.3 案例
练习:将用户键盘录入的用户名和密码保存到本地实现永久化存储。要求用户名独占一行,密码独占一行。
package com.qdu;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class CharStreamDemo8 {
public static void main(String[] args) throws IOException {
// 1.实现键盘录入,把用户名和密码录入进来
Scanner sc = new Scanner(System.in);
System.out.println("请录入用户名");
String username = sc.next();
System.out.println("请录入密码");
String password = sc.next();
// 2.分别把用户名和密码写到本地文件
FileWriter fw = new FileWriter("a.txt");
fw.write(username);
fw.write("\r\n");
fw.write(password);
fw.flush();
// 3.释放资源
fw.close();
}
}
3.字符缓冲流
3.1 字符缓冲输入流:读数据
BufferedReader:可以将数据高效地读取到内存
构造方法:BufferedReader(Reader in)
package com.qdu;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo9 {
public static void main(String[] args) throws IOException {
// 字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 读取数据
char[] chars = new char[1024];
int len;
while ((len = br.read(chars)) != -1) {
System.out.println(new String(chars, 0, len));
}
br.close();
}
}
特有功能 public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为 null。
package com.qdu;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo12 {
public static void main(String[] args) throws IOException {
// 创建对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 读取数据
String line1 = br.readLine();
String line2 = br.readLine();
String line3 = br.readLine();
// readLine如果读不到数据返回null
String line4 = br.readLine();
String line5 = br.readLine();
System.out.println(line1);
System.out.println(line2);
System.out.println(line3);
System.out.println(line4);
System.out.println(line5);
// 释放资源
br.close();
}
}
package com.qdu;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo13 {
public static void main(String[] args) throws IOException {
// 创建对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
// 释放资源
br.close();
}
}
3.2 字符缓冲输出流:写数据
BufferedWriter:可以将数据高效地写出
构造方法:BufferedWriter(Writer out)
package com.qdu;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo10 {
public static void main(String[] args) throws IOException {
// 字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
// 写出数据
bw.write(97);
bw.write("\r\n");
char[] chars = {97, 98, 99, 100, 101};
bw.write(chars);
bw.write("\r\n");
bw.write(chars, 0, 3);
bw.write("\r\n");
bw.write("虎年大吉");
bw.write("\r\n");
String line = "abcdefg";
bw.write(line, 0, 5);
bw.flush();
bw.close();
}
}
特有功能 void newLine():写一行行分隔符,行分隔符字符串由系统属性定义。
package com.qdu;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamDemo11 {
public static void main(String[] args) throws IOException {
// 创建对象
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
// 写出数据
bw.write("虎年大吉666");
bw.newLine();
bw.write("abcdef");
bw.newLine();
bw.write("-------------");
// 刷新流
bw.flush();
// 释放资源
bw.close();
}
}
3.3 案例
练习:读取文件中的数据,排序后再次写到本地文件。
package com.qdu;
import java.io.*;
import java.util.Arrays;
public class CharStreamDemo14 {
public static void main(String[] args) throws IOException {
// 1.要把文件中的数据读取进来
BufferedReader br = new BufferedReader(new FileReader("sort.txt"));
// 输出流一定不能写在前面,因为会清空文件中的内容
// BufferedWriter bw = new BufferedWriter(new FileWriter("sort.txt"));
String line = br.readLine();
System.out.println("读取到的数据为" + line);
br.close();
// 2.按照空格进行切割
String[] split = line.split(" ");
// 3.把字符串类型的数组变成int类型
int [] arr = new int[split.length];
// 遍历split数组,进行类型转换
for (int i = 0; i < split.length; i++) {
String smallStr = split[i];
int number = Integer.parseInt(smallStr); // 类型转换
arr[i] = number; // 把转换后的结果存入到arr中
}
// 4.排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// 5.把排序之后的结果写回到本地
BufferedWriter bw = new BufferedWriter(new FileWriter("sort.txt"));
for (int i = 0; i < arr.length; i++) {
bw.write(arr[i] + " ");
bw.flush();
}
// 释放资源
bw.close();
}
}
4.小结