1.转换流的引入
在项目中新建了一个a.txt的文件,内容是 hello中国。我现在用字节输入流来读取并输出到控制台。当然复制文件是没有问题的啦。编码是utf-8。
package cn;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileInputStreamDemo1 {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
InputStream is = new FileInputStream("a.txt");
//读取数据
int temp = 0;
while((temp=is.read()) != -1){
System.out.print((char)temp);
}
//释放资源
is.close();
}
}
hello
package cn;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileInputStreamDemo1 {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
InputStream is = new FileInputStream("a.txt");
//读取数据
byte[] b = new byte[1024];
int len = 0;
while((len=is.read(b)) != -1){
System.out.println(new String(b,0,len));
}
//释放资源
is.close();
}
}
hello中国
到这里,各位看官,是否觉得,字节流处理中文也是可以的啦,但是如果第1023是个中文字符,那么就惨了吧,一个中文字符是2个字节的啦。那么截取的时候,可能只截取一半。
所以呢,由于字节流操作中文不是"特别"方便,所以,java就提供了转换流。
字符流=字节流+编码表。
2.编码表
编码表:由字符及其对应的数值组成的一张表。
计算机只能识别二进制数据,早期由来是电信号。
为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。
ASCII:美国标准信息交换码。用一个字节的7位可以表示。
ISO8859-1:拉丁码表,欧洲码表。用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
GB18030:GBK的取代版本。
BIG-5码:通行于台湾、香港地区的一种繁体字编码方案,俗称"大五码"。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,java语言使用的就是unicode。
UTF-8:最多用三个字节来表示一个字符。
UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:
它将Unicode编码为00000000-0000007F的字符,用单个字节来表示
它将Unicode编码为00000080-000007FF的字符用两个字节表示
它将Unicode编码为00000800-0000FFFF的字符用3字节表示
3.编码和解码
首先,我来讲一个故事,情景设在抗战时期。那时候,我们的先辈,为了发送消息,都是通过某种手段,将明文转换为密文来发送。但是,各位看官,可能想明文是什么,密文又是什么鬼?比如:我们的先辈要发送“10月29号 凌晨2点 花果山水帘洞集合”,如果发报的人员,将这个字符串通过电报发送过去,那么就惨了,如果敌人一旦进行电报的拦截,那么我们的先辈就完蛋了,但是,我们的先辈们有这么傻吗?他们准备了一个小本子,里面记载了文字和数值对应的关系,比如我对应1,诸如此类,然后将上面的字符串,即“10月29号 凌晨2点 花果山水帘洞集合”,其实这就是明文了,通过那个小本子,当然专业的说话,这个小本本就是编码表,将“10月29号 凌晨2点 花果山水帘洞集合”转换为编码表对应的数值,然后通过电报发送过去,那么,接收方只要有和发送方一样的编码表就可以了。然后接收方在接收到电报的时候,需要通过编码表,将数值转换为字符串,即将密文转换为明文。那么,即使这中间,敌人截取了电报,也没卵用,因为他们没有编码表。
package com;
import java.util.Arrays;
/**
* public byte[] getBytes(String charsetName):使用指定的字符串集合把字符串编码为字节数组
* public String(byte[] bytes,String charsetName):通过指定的字符集解码字节数组
*
* 编码:把看的懂的变成看不懂的 String-->byte[]
* 解码:把看不懂的变成看的懂的byte[]-->String
*
*/
public class StringDemo {
public static void main(String[] args) throws Exception {
//编码 String-->byte[]
String s = "你好";
byte[] b = s.getBytes("utf-8");
System.out.println("编码:"+Arrays.toString(b));//编码:[-28, -67, -96, -27, -91, -67]
//解码 byte[]-->String
String s1 = new String(b,"utf-8");
System.out.println("解码:"+s1);//解码:你好
}
}
编码:[-28, -67, -96, -27, -91, -67, -17, -68, -116, -28, -72, -106, -25, -107, -116]
解码:你好,世界
4.OutputStreamWriter:编码 是使用制定的字符集将字符编码为字节
package com;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
/**
* public OutputStreamWriter(OutputStream out) 根据默认编码把字节流转换为字符流
* public OutputStreamWriter(OutputStream out,String charsetName) 根据指定编码将字节流转换为字符流
*
* 字符流=字节流+编码表
*/
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
Writer w = new OutputStreamWriter(new FileOutputStream("w.txt"),"utf-8");
//输出
w.write("你好,世界");
//释放资源
w.close();
}
}
5.InputStreamReader:解码 是使用制定的字符集读取字节并解码为字符
package com;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class InputStreamReaderDemo {
public static void main(String[] args) throws Exception{
//创建转换流对象
Reader r = new InputStreamReader(new FileInputStream("w.txt"), "utf-8");
int temp = 0;
while((temp = r.read()) != -1){
System.out.print((char)temp);
}
//释放资源
r.close();
}
}
6.OutputStreamWriter的写数据方法
package cn;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
/**
* OutputStreamWriter的方法
* public void write(int c) 写入一个字符
* public void write(char[] chuf) 写一个字符数组
* public void write(char[] chuf,int off,int len) 写一个字符数组的一部分
* public void write(String str) 写一个字符串
* public void write(String str,int off,int len)写一个字符串的一部分
*/
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
Writer w = new OutputStreamWriter(new FileOutputStream("wr.txt"));
//public void write(int c) 写入一个字符
w.write('a');
w.write(97);
//public void write(char[] chuf) 写一个字符数组
char[] chs = new char[]{'a','b','c','d','e'};
w.write(chs);
//public void write(char[] chuf,int off,int len) 写一个字符数组的一部分
w.write(chs, 0, 2);
//public void write(String str) 写一个字符串
w.write("我爱你");
//public void write(String str,int off,int len)写一个字符串的一部分
w.write("你爱我", 0, 1);
/**
* 如果没有将转换流对象flush()或close()?
* 原因:字符=2字节
* 文件中数据存储的基本单位是字节。
*/
w.flush();
//释放资源
w.close();
}
}
close()和flush()的区别?
close()的作用是关闭流对象,但是先刷新缓冲区。关闭之后,流对象不可以继续使用。
flush()的作用是刷新缓冲区,刷新之后,流对象可以继续使用。
7.InputStreamReader 读取数据
package cn;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
/**
* InputStreamReader 读取数据
*
* int read() 读取单个字符
* int read(char[] chs) 将字符读取入数组
*
*/
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
Reader r = new InputStreamReader(new FileInputStream("wr.txt"));
//读取单个字符
int ch = 0;
while((ch = r.read()) != -1){
System.out.print((char)ch);
}
//关闭流对象
r.close();
}
}
package cn;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
/**
* InputStreamReader 读取数据
*
* int read() 读取单个字符
* int read(char[] chs) 将字符读取入数组
*
*/
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//创建转换流对象
Reader r = new InputStreamReader(new FileInputStream("wr.txt"));
//将字符读取入数组
char[] chs = new char[1024];
int len = 0;
while((len = r.read(chs)) != -1){
System.out.println(new String(chs,0,len));
}
//关闭流对象
r.close();
}
}
8.转换流复制文件
package cn;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/**
* 读取的是a.txt,要保证a.txt存在
*/
public class FileCopy {
public static void main(String[] args) throws IOException {
Reader r = new InputStreamReader(new FileInputStream("a.txt"));
Writer w = new OutputStreamWriter(new FileOutputStream("b.txt"));
//一次读取一个字符
int ch = 0;
while((ch = r.read()) != -1){
w.write(ch);
}
r.close();
w.close();
}
}
package cn;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/**
* 读取的是a.txt,要保证a.txt存在
*/
public class FileCopy {
public static void main(String[] args) throws IOException {
Reader r = new InputStreamReader(new FileInputStream("a.txt"));
Writer w = new OutputStreamWriter(new FileOutputStream("b.txt"));
//读取到字符数组
char[] chs = new char[1024];
int len = 0;
while((len = r.read(chs)) != -1){
w.write(chs,0,len);
}
r.close();
w.close();
}
}
9.FileWriter和FileReader
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对象的子类--FileWriter和FileReader。
package cn;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* 数据源:a.txt 读取数据--字符转换流--InputStreamReader--FileReader
*
* 目的地:b.txt 写入数据--字符转换流--OuputStreamWriter--FileWriter
*
*/
public class FileCopy2 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("a.txt");
Writer w = new FileWriter("b.txt");
int ch = 0;
while((ch = r.read()) != -1){
w.write(ch);
}
r.close();
w.close();
}
}
package cn;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* 数据源:a.txt 读取数据--字符转换流--InputStreamReader--FileReader
*
* 目的地:b.txt 写入数据--字符转换流--OuputStreamWriter--FileWriter
*
*/
public class FileCopy2 {
public static void main(String[] args) throws IOException {
Reader r = new FileReader("a.txt");
Writer w = new FileWriter("b.txt");
char[] chs = new char[1024];
int len = 0;
while((len = r.read(chs)) != -1){
w.write(chs, 0, len);
}
r.close();
w.close();
}
}
10.BufferedWriter和BufferedReader
BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
package cn;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
Writer w = new BufferedWriter(new FileWriter("bw.txt"));
w.write("你好,世界");
w.close();
}
}
package cn;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
Reader r = new BufferedReader(new FileReader("bw.txt"));
char[] chs = new char[1024];
int len = 0;
while((len = r.read(chs)) != -1){
System.out.println(new String(chs,0,len));
}
r.close();
}
}
11.BufferedWriter和BufferedReader的特殊功能
package cn;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 字符缓冲流的特殊方法:
* BufferedWriter:
* public void newLine() 根据系统来决定换行符
* BufferedReader:
* public String readLine() 一次读取一行数据
*
*/
public class BufferedDemo {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
for (int i = 0; i < 10; i++) {
bw.write("hello"+i);
bw.newLine();
bw.flush();
}
bw.close();
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
for(int i = 0;i<10;i++){
String str = br.readLine();
System.out.println(str);
}
br.close();
}
}
改进版代码
package cn;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 字符缓冲流的特殊方法:
* BufferedWriter:
* public void newLine() 根据系统来决定换行符
* BufferedReader:
* public String readLine() 一次读取一行数据
*
*/
public class BufferedDemo {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
for (int i = 0; i < 10; i++) {
bw.write("hello"+i);
bw.newLine();
bw.flush();
}
bw.close();
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
}
BufferedWriter和BufferedReader的特殊功能复制文本
package cn;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileCopy1 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
String line = null;
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
}
转载于:https://blog.51cto.com/11841428/1865697