java之IO字符流

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java之IO字符流相关的知识,希望对你有一定的参考价值。

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();
	}

}















本文出自 “11831428” 博客,请务必保留此出处http://11841428.blog.51cto.com/11831428/1865697

以上是关于java之IO字符流的主要内容,如果未能解决你的问题,请参考以下文章

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

IO流之字符输入流,字符输出流

重新java系列之IO流

io系列之字符流

Java基础IO类之字符串流(查字符串中的单词数量)与管道流

Java IO流 之 InputStreamReader 字节流转字符流