一、缓冲流
缓冲流
* 之前的字节流字符流为了提升效率,我们搞了一个数组
* byte[] arr =new byte[8];
*
* 为了进一步提升我们的程序的读写效率,我们使用缓冲流
* 缓冲流是一个包装类,将我们需要的流包装一下,就可以提升效率
* 缓冲流没有读写能力,只能是装饰我们需要读写的类
* 字节流: FileInputStream FileOutputStream
* 字符流: FileReader FileWriter
常见的缓冲流:
缓冲流内部提供了一个默认大小为8192(8kb)的缓冲区
- BufferedInputStream : 缓冲字节输入流
- BufferedOutputStream : 缓冲字节输出流
- BufferedReader : 缓冲字符输入流
- BufferedWriter : 缓冲字符输出流
代码:
package com.qfedu.day15;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 9:15
* @Version 1.0
*
* 缓冲流
* 之前的字节流字符流为了提升效率,我们搞了一个数组
* byte[] arr =new byte[8];
*
* 为了进一步提升我们的程序的读写效率,我们使用缓冲流
* 缓冲流是一个包装类,将我们需要的流包装一下,就可以提升效率
* 缓冲流没有读写能力,只能是装饰我们需要读写的类
* 字节流: FileInputStream FileOutputStream
* 字符流: FileReader FileWriter
*/
public class Demo01 {
public static void main(String[] args) {
/**
* 在之前的流的基础上套了一层
*/
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\User\\Desktop\\data.txt"))){
/**
* 之前我们每次读取一个数组,就写入到磁盘,这样会产生大量的IO操作,
* 使用缓冲流之后,会将即将写入的内容先放起来,达到一定的时机在写入磁盘,减少了IO操作的频率,提升了效率。
*/
byte[] bytes = new byte[8];
int num;
while((num= bufferedInputStream.read(bytes)) != -1){
System.out.print(new String(bytes,0,num));
}
}catch (Exception e){
}
}
}
BufferWriter 中有一个重要的API newLine()
package com.qfedu.day15;
import java.io.BufferedWriter;
import java.io.FileWriter;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 9:41
* @Version 1.0
*/
public class Demo03 {
public static void main(String[] args) {
try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("C:\\Users\\User\\Desktop\\write.txt"));){
bufferedWriter.write("Hadoop Spark Flink");
// 在windows 中 换行是\r\n \r 是回车 \n 是换行 在linux中,换行是 \n
// 所以我们编写的代码还需要考虑运行的环境,很麻烦,直接封装成一个方法 newLine() 它可以根据运行的环境选择是哪种字符进行换行
bufferedWriter.newLine();// 新的API
bufferedWriter.write("java jvm mysql linux");
}catch (Exception e){
e.printStackTrace();
}
}
}
BufferReader 中有一个重要的额API readLine()
package com.qfedu.day15;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 9:15
* @Version 1.0
*
* readLine()
*/
public class Demo02 {
public static void main(String[] args) {
/**
* 在之前的流的基础上套了一层
*/
try(BufferedReader bufferedReader = new BufferedReader(new FileReader("C:\\Users\\User\\Desktop\\data.txt"))){
//bufferedReader.readLine(); // 每次读取一行,读不到内容就返回null
String str ;
// readLine() 相当的有用 只有在字符缓冲流才有这个API
while((str =bufferedReader.readLine()) != null){
System.out.println(str);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
LineNumberReader 是BufferedReader 的子类,可以设置行号
package com.qfedu.day15;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.LineNumberReader;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 9:52
* @Version 1.0
*/
public class Demo04 {
// BufferedReader 下有一个子类 : LineNumberReader
public static void main(String[] args) {
/**
* 在之前的流的基础上套了一层
*/
try(LineNumberReader lineNumberReader = new LineNumberReader(new FileReader("C:\\Users\\User\\Desktop\\data.txt"))){
String str ;
// lineNumberReader.setLineNumber(5); // 设置行号,起始位置,设置为 5 ,打印的时候从 6 开始打印
// 如果不设置,那么行号从0开始,打印的时候,先打印1
while((str =lineNumberReader.readLine()) != null){
int lineNumber = lineNumberReader.getLineNumber();
System.out.print(lineNumber);
System.out.print(str);
System.out.println();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
二、设计模式—装饰者
java 中有23种设计模式— 大话设计模式
设计模式, 前人总结出来的对一些常见问题的解决方案,后人直接拿来使用
所谓的设计—其实就是java代码中的编程技巧。只要代码足够的优化,都是殊途同归。
今天我们见到了装饰者设计模式的典型应用 — 缓冲流。
举个例子:
自己编写一个类,实现我们的缓冲流中的readLine方法。编写一个自己的MyBufferedReader 类,实现缓冲流中的readLine() 方法。
想对某个类进行增强,就是对某个类中的方法进行增强,所以我们需要将原来的类给引入进来,可以通过传参数。
穿着稻草的小人 —> 传递到了一个增强类中—> 将武器装备和衣服进行升级。
对某个类的功能进行增强:
1、继承
2、装饰者模式
3、代理模式
装饰者模式:
什么是装饰者模式: 对需要进行内容增强的类,进行方法上的增强(原有方法,新的方法)
实现步骤:
1、需要继承原有的类
2、需要有一个有参数的构造方法,将 基本的类传递进来
* 3、实现新的方法或者重写老的方法。
package com.qfedu.day15;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 10:15
* @Version 1.0
*
* 增强的类,使用设计者模式
*
* 装饰者模式:
* 什么是装饰者模式: 对需要进行内容增强的类,进行方法上的增强(原有方法,新的方法)
* 实现步骤:
* 1、需要继承原有的类
* 2、需要有一个有参数的构造方法,将 基本的类传递进来
* 3、实现新的方法或者重写老的方法。
*/
public class MyBufferedReader extends Reader {
/**
* 对 FileReder 进行的增强
*/
private Reader fileReader ;
public MyBufferedReader(Reader fileReader){
this.fileReader = fileReader;
}
/**
* 增强原有的方法
* @return
* @throws IOException
*/
public int read() throws IOException {
/**
* 增强的代码,此处可以随便写
*/
System.out.println("我的增强代码");
return fileReader.read();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return fileReader.read(cbuf,off,len);
}
@Override
public void close() throws IOException {
}
/**
* 是对原来的FileReader 进行的增强方法
* @return
* @throws IOException
*/
public String readLine() throws IOException {
StringBuilder lineStr = new StringBuilder();
/**
* // 回车有两个字符 \r\n
* hadoop version
* flume java
*/
while(true){
int a = fileReader.read();
if(a == '\r'){
continue;
}else if(a == '\n'){
break;
}else{
lineStr.append((char)a);
}
}
return lineStr.toString();
}
}
装饰器模式补充:
4.2.3.1. 介绍
我们对一个已经完成的类,如果需要进行功能的拓展,最容易让我们想到的就是继承!设计一个类的子类,子类继承到父类中所有的功能,同时也可以进行功能的添加。但是有时候我们要拓展的类无法继承,那么怎么办呢?
此时可以使用装饰模式,在不使用继承的情况下,对一个类的功能进行拓展。并且使用装饰模式进行功能拓展,比起使用继承来说要更加的简洁和灵活。
在IO流部分,对装饰模式的使用是比较多的。
例如: InputStream是一个字节输入流,如果我们需要进行效率的提升,可以使用BufferedInputStream。那么,在你实例化一个BufferedInputStream对象的时候,参数部分是不是一个InputStream对象呐?
4.2.3.2. 实现
/**
* @Author 千锋大数据教学团队
* @Company 千锋好程序员大数据
* @Description 修饰装饰
*/
public interface Decorator {
void show();
}
// 所有的装饰者的父类 基类
abstract class AbstractDecorator implements Decorator {
// 表示被装饰的对象
protected Decorator decorator;
//
public AbstractDecorator(Decorator decorator) {
this.decorator = decorator;
}
}
class ShoesDecorator extends AbstractDecorator {
public ShoesDecorator(Decorator decorator) {
super(decorator);
}
@Override
public void show() {
this.decorator.show();
System.out.println("穿了一双鞋");
}
}
class TshirtDecorator extends AbstractDecorator {
public TshirtDecorator(Decorator decorator) {
super(decorator);
}
@Override
public void show() {
this.decorator.show();
System.out.println("穿了一个T恤衫");
}
}
class TrousersDecorator extends AbstractDecorator {
public TrousersDecorator(Decorator decorator) {
super(decorator);
}
@Override
public void show() {
this.decorator.show();
System.out.println("穿了一条裤子");
}
}
public class Demo08 {
public static void main(String[] args) {
// 穿衣服
TshirtDecorator tshirtDecorator = new TshirtDecorator(new Decorator() {
@Override
public void show() {
System.out.println("开始穿衣服");
}
});
//tshirtDecorator.show();
TrousersDecorator trousersDecorator = new TrousersDecorator(tshirtDecorator);
ShoesDecorator shoesDecorator = new ShoesDecorator(trousersDecorator);
shoesDecorator.show();
/**
* 比如: 点咖啡 加糖不加糖 加牛奶不加牛奶 加茶水不加茶水
* 比如: 卖自行车 自行车是一个基类 很多的装饰类 加前灯,加后灯,加音响,加水杯
*/
}
}
三、序列化流(重点)—对象的序列化
1、概念
将jvm内存中的一个类的对象,存储到磁盘上,再从磁盘上加载到jvm内存中,称之为序列化。
序列化与反序列化的操作。
2、将一个对象序列化到磁盘上(文件中)
对象一定要实现序列化接口,否则报错
package com.qfedu.day15;
import java.io.Serializable;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 10:46
* @Version 1.0
*/
public class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.qfedu.day15;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 10:46
* @Version 1.0
*/
public class Demo06 {
public static void main(String[] args) {
// 对象实例化了,jvm中有内容了
Person person = new Person("张三", 19);
// 将该对象放入到一个txt文档里面 --> 对象序列化
// ObjectInputStream、 ObjectOutputStream
try(ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\User\\Desktop\\obj.txt"))){
objectOutputStream.writeObject(person);
objectOutputStream.flush();
}catch (Exception e){
e.printStackTrace();
}
}
}
3、将文件中的序列化的对象,读取到jvm内存中— 反序列化
package com.qfedu.day15;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 10:55
* @Version 1.0
*/
public class Demo07 {
public static void main(String[] args) {
// 将一个文件中的对象读取到内存中,这个过程称之为对象的反序列化
// ObjectInputStream、 ObjectOutputStream
try(ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("C:\\Users\\User\\Desktop\\obj.txt"))){
Object o = objectInputStream.readObject();
if(o instanceof Person){
Person p = (Person)o;
System.out.println(p);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
对象的序列化技术:一般应用于网络间对象数据的传输。一是安全性得到保障另外对象序列化可以压缩空间便于传输。将对象序列化到本地一般不多见,常见于我们使用的一些软件—Redis.
4、序列化中要有序列号
可以通过IDEA帮我生成一个序列化号:
serialVersionUID
不进行上面的操作,是没有办法生成的。
在类上,alt + enter 点击生成 serialVersionUID 就可以了。
首先:
1、我们生成了一个序列化的编号,然后进行了序列化的操作,在磁盘上生成了一个文件
2、我们修改了序列化编号中的一个字,然后再反序列化,就出现了错误:
java.io.InvalidClassException: com.qfedu.day15.Person; local class incompatible: stream classdesc serialVersionUID = 5163574055981245315, local class serialVersionUID = 5163574055981245316
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
at com.qfedu.day15.Demo07.main(Demo07.java:21)
为什么呢?因为你修改了序列化的编号,导致错误。
将序列化编号修改正确即可。
推演:序列化的编号其实是一种安全策略,它可以保证序列化与反序列化是同一个类,没有发生变化。
package com.qfedu.day15;
import java.io.Serializable;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 10:46
* @Version 1.0
*/
public class Person implements Serializable {
// 让系统帮我们生成一个,而不是指定一个 1L
private static final long serialVersionUID = 5163574055981245315L;
//private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
四、Properties(重点)
1、介绍
Properties 不是IO流,是一个集合,是Hashtable的子类,是一个Map实现类。
2、用法
package com.qfedu.day15_02;
import java.util.Properties;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 14:50
* @Version 1.0
当集合用
*/
public class Demo01 {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("first","java");
properties.setProperty("second","python");
properties.setProperty("third","php");
System.out.println(properties);
System.out.println(properties.getProperty("first"));
properties.setProperty("first","scala");
System.out.println(properties);
}
}
package com.qfedu.day15_02;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 14:50
* @Version 1.0
*/
public class Demo02 {
// 获取系统属性
public static void main(String[] args) {
// 获取系统中的Properties 对象
Properties properties = System.getProperties();
// 获取一个Properties 中所有的key值
Set<String> set = properties.stringPropertyNames();
System.out.println(set);
// 通过迭代器循环遍历
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
String key = iterator.next();
System.out.println("key="+key+",value="+properties.getProperty(key));
}
}
}
可以加载配置文件,修改配置文件
package com.qfedu.day15_02;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 15:01
* @Version 1.0
*/
public class Demo03 {
// 此处我们训练的是文件加载到Properties 中
public static void main(String[] args) throws Exception {
// 先搞一个空的集合 Properties
Properties properties = new Properties();
// 通过集合中的load 方法,加载一个流(可以是字符流也可以是字节流)
properties.load(new FileReader("a.txt"));
// 该方法只要执行完,集合中就有数据了。
System.out.println(properties.getProperty("name"));
/**
* 以上内容是读取文件中的内容到Properties 中,以下内容是将properties 中的内容存入文件中
*/
properties.setProperty("name","大家");
// 通过store 可以将内容存储到文件中。
properties.store(new FileWriter("a.txt"),"修改了name");
}
}
五、Scannner类
回顾:常用语法:
package com.qfedu.day15_03;
import java.util.Scanner;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 15:16
* @Version 1.0
*/
public class Demo01 {
// Scanner
/**
* 常用方法
* next() 可以获取一个单词
* nextInt() 可以获取一个数字
* hasNext() 判断是否还有下一个单词
* nextLine() 读取一行数据,遇到换行符就不读取了
* hasNextLine() 判断是否还有下一行
* @param args
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个单词:");
String str = scanner.next();
System.out.println(str);
System.out.println("请输入一句话,使用空格隔开:");
while(scanner.hasNext()){
System.out.println(scanner.next());
}
}
}
流也可以从其他地方过来,比如File
package com.qfedu.day15_03;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 15:16
* @Version 1.0
*/
public class Demo02 {
// Scanner
/**
* 常用方法
* next() 可以获取一个单词
* nextInt() 可以获取一个数字
* hasNext() 判断是否还有下一个单词
* nextLine() 读取一行数据,遇到换行符就不读取了
* hasNextLine() 判断是否还有下一行
* @param args
*/
public static void main(String[] args) {
// Scanner 构造方法中可以传入其他的流,System.in 只是其中一个流而已
try(Scanner scanner = new Scanner(new File("a.txt")))
{
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
}catch (Exception e){
e.printStackTrace();
}
}
}
记录一个坑:
package com.qfedu.day15_03;
import java.util.Scanner;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 15:27
* @Version 1.0
*/
public class Demo03 {
/**
* 补充内容:一个用法上的坑
* @param args
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/*System.out.println("请输入字符串(nextLine):");//曹老板很有钱
String str1 = input.nextLine();
System.out.println(str1);*/
System.out.println("请输入字符串(next):");
String str = input.next(); // 你好(回车)
System.out.println(str);//你好
/**
* 此后代码不让我填写文字,直接运行结束的原因是:
* nihao 然后回车了 \r\n
* next() 只读取了 nihao,并没有读取 \r\n
* 所以后面的readLine 是 遇到 \n 就结束
* 所以 \r\n 被我们的readLine() 读取到了,所以结束了,什么都没有打印
*/
System.out.println("请输入字符串(nextLine):");//曹老板很有钱
String str1 = input.nextLine();// 它读取了一个回车,刚好就结束了
System.out.println(str1);
}
}
六、打印流(了解)
常用类是:
字节打印流(PrintStream)
字符打印流(PrintWriter)
package com.qfedu.day15_03;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 16:05
* @Version 1.0
*/
public class Demo04 {
// 打印流,主要用于打印用的
public static void main(String[] args) throws IOException {
PrintWriter printWriter = new PrintWriter(new FileWriter("b.txt"));
printWriter.write("你好,我是打印流!");
printWriter.close();
}
}
七、标准输入输出流(了解)
System.out 标准输出流 --默认输出到了控制台
System.in 标准输入流 --默认数据来源是键盘
package com.qfedu.day15_03;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 16:10
* @Version 1.0
*/
public class Demo05 {
/**
* 实现从键盘上不断的接收字符的程序
* 要求一行一行的接收
* @param args
*/
public static void main(String[] args) throws IOException {
InputStream in = System.in;// 数据的来源是键盘
myReadLine(in);
}
private static void myReadLine(InputStream in) throws IOException {
StringBuffer stringBuffer = new StringBuffer();
while(true){
int read = in.read();
if(read == '\r'){
continue;
}else if(read == '\n'){
break;
}else{
stringBuffer.append((char)read);
}
}
System.out.println(stringBuffer.toString());
}
}
package com.qfedu.day15_03;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 16:18
* @Version 1.0
*/
public class Demo06 {
public static void main(String[] args) {
PrintStream out = System.out;// 竟然是一个打印流
// 标准的输出流是输出到控制台的,我们也可以改变输出的方向
try(PrintStream printStream = new PrintStream(new FileOutputStream("c.txt"))){
// 可以修改输出流的方向
System.setOut(printStream);
System.out.println("我在哪里,我是谁,发生了什么事儿!!!");
}catch (Exception e){
e.printStackTrace();
}
}
}
面试题:System.out.println() 是线程安全的吗? 自行百度!!!!
八、转换流引出字符集的问题
拥有两个工具类:
转换流 —- 转换字符集的
当文本内容和我们的运行环境不一致的时候,我们需要使用转换流来操作
InputStreamReader
* OutputStreamWriter
1、演示采用某种字符集读取一个文件
package com.qfedu.day15_04;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 16:38
* @Version 1.0
*/
public class Demo01 {
/**
* 转换流 --- 转换字符集的
* 当文本内容和我们的运行环境不一致的时候,我们需要使用转换流来操作
* InputStreamReader
* OutputStreamWriter
* @param args
*/
public static void main(String[] args) {
/**
* 在之前的流的基础上套了一层
*//*
try(BufferedReader bufferedReader = new BufferedReader(new FileReader("C:\\Users\\User\\Desktop\\data.txt"))){
//bufferedReader.readLine(); // 每次读取一行,读不到内容就返回null
String str ;
// readLine() 相当的有用 只有在字符缓冲流才有这个API
while((str =bufferedReader.readLine()) != null){
System.out.println(str);
}
}catch (Exception e){
e.printStackTrace();
}*/
try(InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\User\\Desktop\\data.txt"),"GBK")){
char[] arr =new char[100];
int num;
while((num =inputStreamReader.read(arr)) != -1){
System.out.println(new String(arr,0,num));
}
}catch (Exception e){
e.printStackTrace();
}
}
}
2、采用某个字符集写入一个文件
package com.qfedu.day15_04;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
* @Author laoyan
* @Description TODO
* @Date 2022/3/21 16:38
* @Version 1.0
*/
public class Demo02 {
/**
* 转换流 --- 转换字符集的
* 当文本内容和我们的运行环境不一致的时候,我们需要使用转换流来操作
* InputStreamReader
* OutputStreamWriter
* @param args
*/
public static void main(String[] args) {
try(OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\User\\Desktop\\data2.txt"),"GBK")){
writer.write("Hello World");
writer.write("你好,世界!");
writer.flush();
}catch (Exception e){
e.printStackTrace();
}
}
}
九、字符集
- 常用字符集
- 中国的字符集:GBK/GB2312
- 欧洲的:ISO8859-1
- 通用的:UTF-8
- 美国的:ASCII
- 对中文的处理
- 一个汉字:GBK:2个字节 ISO8859-1:1个字节 utf-8:3个字节 unicode:2个字节(内部编码)
- 说明:GBK,UTF-8是支持中文的,ISO8859-1不支持中文
- 编码:将字符串转化成byte序列的过程
- 解码:是将byte序列转成字符串的过程
- 编码错误:乱码:在执行读与写的时候,由于使用的字符集不同,造成了编码的错误.
GBK 中的中文 --> byte数组 --> utf-8 utf-8 后就乱码
怎么样才能不乱码 文本内容 GBK ,将来读取的时候也需要使用GBK
实战:
编码:
byte[] getBytes() //对于中文 默认的格式
使用平台的默认字符集将此 String 编码为 byte 序列,
并将结果存储到一个新的 byte 数组中。
byte[] getBytes(Charset charset)
使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
解码:
String(byte[] bytes) //对于中文 默认是格式
通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, Charset charset)
通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
// 编码,变为byte数组
byte[] bytes = "你好".getBytes();// 并没有指定字符集,默认采用开发环境中的字符集 utf-8
// 解码
String str = new String(bytes, "UTF-8");
System.out.println(str);
byte[] bytes2 = "你好".getBytes("GBK");
System.out.println(new String(bytes2,"GBK"));