常见字符集
标准ASCII码字符集
- ASCII(American Standard Code for Information Interchange):美国信息交换标准代码,包括英文、符号等
- 标准ASCII码使用1个字节存储一个字符,首位是0,总共可表示128个字符
而对于国内而言,汉字和字符多达几万个,很明显ASCII码是不够用的,所以便推出了我们的汉字编码字符集——GBK
GBK(汉字内码扩展规范,国标)
- 汉字编码字符集,包含了两万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储
- GBK规定,汉字的第一个字节的首位必须是1
- GBK兼容了ASCII字符集,事实上,绝大多数字符集都兼容了ASCII
Unicode字符集(万国码,也叫统一码) - Unicode是国际组织制定的,可以容纳世界上所有文字及符号的字符集,如UTF - 32、UTF - 16及UTF - 8,其中最常用的是UTF - 8
- UTF - 8:Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节、2个字节、3个字节和4个字节。英文字符、数字等只占1个字节(兼容ASCII码),汉字字符占3个字节
字符集的编码、解码操作
- Java对字符编码
String提供的方法 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
- Java对字符解码
String提供的方法 | 说明 |
---|---|
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的String |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的String |
演示
public class charsetTest {
public static void main(String[] args) throws UnsupportedEncodingException {
/* 编码*/
String data = "abc一蓑烟雨任平生bcd";
// 默认按平台字符集进行编码,这里使用的是UTF-8,中文3个字节
byte[] bytes = data.getBytes();
System.out.println(Arrays.toString(bytes));
// 27
System.out.println(bytes.length);
// 按照指定字符集进行编码,GBK中文2个字节
byte[] bytesGBK = data.getBytes("GBK");
// 20
System.out.println(bytesGBK.length);
/* 解码 */
String s1 = new String(bytes);
// 平台配置的是UTF-8,所以,在对UTF-8编码的bytes解码时不需要指定字符集
System.out.println(s1);
// bytesGBK指定的编码是GBK,在使用默认编码UTF-8对其解码时会出现乱码
String s2 = new String(bytesGBK);
// abcһ��������ƽ��bcd
System.out.println(s2);
// 指定GBK对bytesGBK解码即可正常显示
String s3 = new String(bytesGBK,"GBK");
System.out.println(s3);
}
}
IO流
IO流概述
- I:指Input,称为输入流,负责把数据读到内存中区
- O:指Output,称为输出流,负责写数据出去
IO流分类
- 按流的方向分为输入流和输出流
- 按流中数据的最小单位分为字节流和字符流,其中字节流适合操作所有类型的文件,如音频、视频、图片等,而字符流知识和操作纯文本文件,如:读写txt、doc、java文件等
总结流的四大类(抽象类)
- 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流——> InputStream
- 字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流——> OutputStream
- 字符输入流:以内存为基准,来自碰盘文件/网络中的数据以字符的形式读入到内存中去的流——> Reader
- 字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流——> Writer
FileInputStream(文件字节输入流)
- 作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
构造器 | 说明 |
---|---|
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通 |
方法名 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1 |
public int read(byte[] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1 |
public byte[] readAllBytes() throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
案例1
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
// 创建文件字节输入流管道,与源文件接通
// InputStream is = new FileInputStream(new File("oop3\\src\\com\\ligemanyin\\_IO\\EnTest.txt"));
InputStream is2 = new FileInputStream("oop3\\src\\com\\ligemanyin\\_IO\\EnTest.txt");
int b;
// read()一次只能读取一个字节,导致其无法读取中文字符,因为中文字符是3个字节
while ((b = is2.read()) != -1) {
System.out.print((char) b);
}
// 关闭流,释放资源
is2.close();
}
}
案例2
public class FileInputStreamTest2 {
public static void main(String[] args) throws Exception{
// 创建一个字节输入流对象代表字节输入流管道与源文件接通
File file = new File("oop3\\src\\com\\ligemanyin\\_IO\\ChTest.txt");
InputStream is = new FileInputStream(file);
// 开始读取文件中的字节数据:每次读取多个字节
// byte[] buffer = new byte[(int) file.length()];
// int len = is.read(buffer);
// String rs = new String(buffer);
// System.out.println(rs);
// System.out.println(len);
// 或
byte[] buffer2 = is.readAllBytes();
System.out.println(new String(buffer2));
// 关闭流,释放资源
is.close();
}
}
其中EnTest.txt中只写入了一句英文短句,而ChTest.txt中则写入张若虚的《春江花月夜》
FileOutputStream(文件字节输出流)
- 作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
构造器 | 说明 |
---|---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(String filePath) | 创建字节输出管道与源文件路径接通 |
public FileOutputStream(File file, boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filePath, boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer, int pos, int len) | 写一个字节数组的一部分出去 |
public void close() throws IOException | 关闭流 |
演示1
public class FileOutputStreamTest1{
public static void main(String[] args) throws Exception {
// 创建一个字节输出流管道与目标文件接通
OutputStream op = new FileOutputStream("oop3\\src\\com\\ligemanyin\\_IO\\_FileOutPutStream\\outTest1.txt");
// 写字节数据出去
// 97一个字节-->a
// abc
op.write(97);
op.write('b');
op.write(99);
// abc万里悲秋常作客,百年多病独登台
byte[] bytes = "万里悲秋常作客,百年多病独登台".getBytes();
op.write(bytes);
// UTF-8中七个字21个字节
// // abc万里悲秋常作客,百年多病独登台万里悲秋常作客
op.write(bytes, 0, 21);
// 以上构造器是将txt文本清空后进行写出
// 以下构造器可不用清空文本,在文本后添加数据
// 首先进行换行,方便区分,ASCII码中,10表示LF(Line Feed),即换行
// 亦或是"\r\n"进行换行,通过getBytes()方法转换
op.write(10);
// OR op.write("\r\n".getBytes())
OutputStream op2 = new FileOutputStream("oop3\\src\\com\\ligemanyin\\_IO\\_FileOutPutStream\\outTest1.txt", true);
byte[] bytes2 = "艰难苦恨繁霜鬓,潦倒新停浊酒杯".getBytes();
/*abc万里悲秋常作客,百年多病独登台万里悲秋常作客
艰难苦恨繁霜鬓,潦倒新停浊酒杯*/
op2.write(bytes2);
op2.close();
op.close();
}
}
演示2
public class FileInputStreamTest2 {
public static void main(String[] args) throws Exception{
// 创建一个字节输入流对象代表字节输入流管道与源文件接通
File file = new File("oop3\\src\\com\\ligemanyin\\_IO\\ChTest.txt");
InputStream is = new FileInputStream(file);
// 开始读取文件中的字节数据:每次读取多个字节
// byte[] buffer = new byte[(int) file.length()];
// int len = is.read(buffer);
// String rs = new String(buffer);
// System.out.println(rs);
// System.out.println(len);
// 或
byte[] buffer2 = is.readAllBytes();
System.out.println(new String(buffer2));
// 关闭流,释放资源
is.close();
}
}
案例
public class CopyPictureTest {
public static void main(String[] args) throws Exception{
// 复制图片
// 源文件
InputStream is = new FileInputStream("F:\\Data\\picture\\图片1.jpg");
// 目标文件
OutputStream os = new FileOutputStream("F:\\Data\\picture\\picture.jpg");
byte[] bytes = is.readAllBytes();
os.write(bytes);
// 先关后流,先流后关
os.close();
is.close();
System.out.println("复制完成");
}
}