目录

前言

字符编码

面向字符输入/输出流类

转换流

转换输入流(InputStreamReader)类

转换输入流(InputStreamReader)类实例

转换输出流(OutputStreamWriter)类

转换输出流(OutputStreamWriter)类实例

FileWriter类

FileWriter类实例

FileReader类

FileReader类实例

BufferedWriter类

BufferedWriter类实例

BufferedReader类

BufferedReader类实例

PrintWriter类

PrintWriter类实例

最后


前言

上篇文章中,我们学习了Java I/O流——面向字节的输入/输出流(超级详细),字节流中数据的最小单元为字节,而Java采用Unicode字符编码,对每个字符,JVM会为其分配2字节的内存,而用字节流类读/写字符文本会很不方便,因此,java.io包中提供了Reader/Writer类,用表示字符的输入/输出流。

字符编码

在读/写文本文件时,最主要的问题是进行字符编码的转换。文本文件中字符有可能是采用各种类型的编码。例如:

  • String类getBytes(String encode)方法能返回字符串的特定类型的编码,其中encode参数指定编码类型;
  • String类不带参数的getBytes()方法则使用本地操作系统的默认字符编码。

在Java程序中,以下两种方式都能获得本地平台的字符编码类型:

System.getProperty("file.encoding");            //方式一
Charset cs=Charset.defaultCharset();            //方式二
System.out.println(cs);

注意:Windows操作系统,上面的代码一般会显示“GBK”;而在中文Linux平台上,通常会显示“UTF-8”。

面向字符输入/输出流类

面向字符的输入/输出流类是Reader/Writer的后代,如下图所示:

123131231         34636545

  • Reader类是一个抽象类,提供的方法与InputStream类似只是将基于byte的参数改为基于char;
  • Writer类是一个抽象类,提供的方法与OutputStream类似,只是将基于byte的参数改为基于char。

转换流

字符流建立在字节流的基础上,Java可将字节流和字符流互相转换。

Reader和Writer类默认在本地平台的字符编码和Unicode码之间进行转换:

  • Reader类:能够将输出流中采用其他编码类型的字节流转换为Unicode字符,再为这些字符分配内存;
  • Writer类:将内存中的Unicode字符转换为其他编码类型的字节流,再写到输出流中。

采用特定类型编码的字节流:

  • InputStreamReader类:将一个字节流中若干字节解码成字符;
  • OutputStreamWriter类:将字符编码成若干字节后写入一个字节流。

在实际应用中要根据流数据的特点来决定是否需要进行转换,例如:标准键盘输入提供的数据是字节形式的,实际上,想从键盘输入的数据是字符系列,因此转换成字符流更符合应用的特点。

使用InputStreamReader将字节流转换为字符流,为了能一次性地从键盘输入一行字符串,再用BufferedReader对字符流进行包装处理:

BufferedReader in=new BufferedReader(new InputStreamReader(System.in));    
String  x=in.readLine();                //读取一行字符串

转换输入流(InputStreamReader)类

InputStreamReader是Reader的子类,一个InputStreamReader对象接受一个字节输入流作为源,产生相应的UTF-16字符。常用的构造方法有:

  • InputStreamReader(InputStream in):使用默认的字符集编码,将字节输入流转换为字符输入流并读取数据;
  • InputStreamReader(InputStream in,Charset c):按指定字符集的编码从输入流读取数据;
  • InputStreamReader(InputStream in,String enc)throws UnsupportedEncodingException:使用指定的字符集编码,将字节输入流转换为字符输入流并读取数据。

转换输入流(InputStreamReader)类实例

使用字符输入流读取文件内容:

1231321

import java.io.*;
public class first {
	public static void main(String[] args){
		String filename="D:/welcome.txt";        //创建一个变量filename存放文件路径
		try {
			InputStreamReader isr=new InputStreamReader(new FileInputStream(filename),"UTF-8"); //创建转换输入流,按UTF-8的编码从输入流读取数据
			int c;                               //创建int类型变量c
			while((c=isr.read())!=-1)            //使用while循环读取文件数据
				System.out.print((char)c);       //输出打印字符
		}catch(IOException e) {                  
			e.printStackTrace();                 //查看完整错误信息
		}
	}
}

运行结果为:

欢迎学习Java!!!

注意:支持汉字的编码字符集有GB2312、GBK、UTF-8、UTF-16。其中GBK是GB2312的扩展,它们均是双字节编码,UTF-16采用定长的双字节,而UTF-8采用变长字节表示不同字符;

转换输出流(OutputStreamWriter)类

OutputStreamWriter类是Writer的子类。一个OutputStreamWriter对象将UTF-16字符转换为指定的字符编码的形式写入字节输出流。常用的构造方法有:

  • OutputStreamWriter(OutputStream out):按默认字符集的编码将字节输出流转换为字符输出流并写入数据;
  • OutputStreamWriter(OutputStream out,Charset c):按指定字符集的编码往输出写入数据;
  • OutputStreamWriter(OutputStream out,String enc)throws UnsupportedEncodingException:按名称所指字符集的编码将字节输出流转换为字符输出流写入数据。

转换输出流(OutputStreamWriter)类实例

使用字符输出流往文本文件写入数据

import java.io.*;
public class first {
	public static void main(String[] args){
		String filename="D:/welcome.txt";
		try {
			OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream(filename),"UTF-8");    //创建转换输出流
			osw.write("Hello,我是霖hero博主,一个想当英雄的男人!!!");    //向文本文件写入数据
   			osw.close();                //关闭文件
		}catch(IOException e) {    
			e.printStackTrace();        //查看所有错误信息
		}
	}
}

FileWriter类

FileWriter类用于写字符文件,每次写入一个字符、一个数组或一个字符串,其类对象通常看成一个以字符为基本单位的无格式字符输出流。其构造方法有:

  • FileWriter(File file,boolean append)throws IOException:根据File对象构造一个FileWriter对象,若第二个参数为true,则将字符以添加的方式写入文件尾处,若为false则原有文件内容被清除;
  • FileWriter(String fileName,boolean append)throws IOException:根据字符串文件名构造一个FileWriter对象,若第二个参数为true,则将字符以添加的方式写入文件尾处,若为false则原有文件内容被清除。

FileWriter类实例

将九九乘法表写入文本文件中

import java.io.*;
public class first {
	public static void main(String[] args) throws IOException{
		String filename="D:/table.txt";        
		FileWriter fw=new FileWriter(filename,true);    //创建FileWriter对象
		for(int i=1;i<=9;i++) {                         //利用两个for循环打印九九乘法表
			for(int j=1;j<=i;j++) {
				String s=i+"*"+j+"="+j*i+" ";
				fw.write(s);                            //将乘法表写入文本文件中
			}
			fw.write("\r\n");                           //写入回车换行符
		}
		fw.flush();                                     //强制刷新流
	}
}

运行结果为:

234234234

FileReader类

FileReader类用于读字符文件,每次读取一个字符或一个字符数组,其类对象通常看成一个以字符为基本单位的无格式字符输入流。其构造方法有:

  • FileReader(String fileName)throws FileNotFoundException:在给定中的文件名读取数据的情况下创建一个新的FileReader类;
  • FileReader(File file)throws FileNotFoundException:在给定中的File参数读取数据的情况下创建一个新的FileReader类。

FileReader类实例

读取上面FileReader类实例中的table.txt文件中的九九乘法表

import java.io.*;
public class first {
	public static void main(String[] args) throws IOException{
		FileReader fr=new FileReader("D:/table.txt");   //创建FileReader对象
		int c;
		while((c=fr.read())!=-1) {                //读取文件中的内容
			System.out.print((char)c);            //将c转换为char类型并输出文件中的内容
		}
	}
}

运行结果为:

123131

BufferedWriter类

BufferedWriter是带缓冲的字符流,可用于以文本行为单位处理文本的场合,其常用的方法有:

  • BufferedWriter(Writer out):将输出流out转换成带缓冲的字符流,缓冲区大小为系统默认的;
  • BufferedWriter(Writer out,int sz):将流out转换成带缓冲的字符流,缓冲区大小为sz;
  • void newLine()throws IOException:写入行结束标记,该标记不是简单的换行符('\n'),而是由系统定义的属性line.separator。

BufferedWriter类实例

将100以内所有的质数写入文本文件,要求每10个数一行。

import java.io.*;
public class first {
	static boolean isPrime(int n) {
		for(int i=2;i<=n/2;i++)          //判断是否为质数
			if(n%i==0)
				return false;
		return true;
	}
	public static void main(String[] args) throws IOException{
		BufferedWriter bw=new BufferedWriter(new FileWriter("D:/number.txt"));  //创建BufferedWriter对象
		int j=0;
		for(int i=2;i<=100;i++) {
			if(isPrime(i)) {
				j++;
				String s=String.valueOf(i);
				String s1=s+" ";
				bw.write(s1);            //写入数据到文本文件中
				if(j==10) {                    
					j=0;                 
					bw.newLine();        //当j=10时,写入一个换行符
				}
			}
		}
		bw.flush();                      //强制刷新流
		bw.close();                      //关闭文本文件
	}
}

运行结果为:

12321312

BufferedReader类

BufferedReader是带缓冲的字符流,可用于以文本行为单位处理文本的场合,其常用的方法有:

  • BufferedReader(Reader in):将输入流in转换成带缓冲的字符流,缓冲区大小系统默认的;
  • BufferedReader(Reader in ,int sz):将流in转换成带缓冲的字符流,缓冲区大小为sz;
  • String readLine()throws IOException:从输入流中读取一行字符,行结束标志为回车('\r')/换行('\n')或连续的回车换行符(''r''\n')。

BufferedReader类实例

打印输出BufferedWriter类实例对象中的number.txt文件中的数据。

import java.io.*;
public class second {
	public static void main(String[] args)throws IOException {
		BufferedReader br=new BufferedReader(new FileReader("D:/number.txt"));    //创建BufferedReader对象
		int c;                            //创建int型变量c
		while((c=br.read())!=-1)          //判断是否读完文本中的数据
			System.out.print((char)c);    //将int型转换为char型并输出
		System.out.println();
	}
}

运行结果为:

1231312

PrintWriter类

文本文件的输出流有FileWriter类,该类通常是以字符为单位写入文本文件,但有时需要以Java的基本数据类型为单位写入文本文件,使用FileWriter类写入处理起来不是很方便,因此Java引入PrintWriter类进行此类文本的输出。其构造方法有:

  • PrintWriter(Writer out):将任意一个字符输出流out串接成一个PrintWriter对象,不自动刷空流;
  • PrintWriter(Writer out,boolean autoFlush):将任意一个字符输出流out串接成一个PrintWriter对象,若boolean值为true则自动刷空流;
  • PrintWriter(OutputStream out):将任意一个字符输出流out串接成一个PrintWriter对象,不自动刷空流;
  • PrintWriter(OutputStream out,boolean autoFlush):将任意一个字节输出流out串接成一个PrintWriter对象,若boolean值为true则自动刷空流。

PrintWriter类实例

如果一个四位数是11的倍数且十位数字加上百位数字刚好等于前位数字,则将该四位数写入文本文件中。

import java.io.*;
public class printWriter {
	public static void main(String[] args)throws IOException{
		FileWriter fw=new FileWriter("D:/four.txt");    //创建FileWriter对象
		PrintWriter pw=new PrintWriter(fw);             //创建PrintWriter对象
		int num=0;
		for(int i=1000;i<10000;i++) {                   //利用for循环获得各个位的数字
			int A=i/1000;                               //千位上的数
			int B=i/100%10;                             //百位上的数
			int C=i/10%10;                              //十位上的数
			if(i%11==0&&A==B+C) {                       //如果是11的倍数,且十位数字加百位数字等于千位数字
				pw.print(i+"  ");                       //打印输出该四位数
				if(++num==10) {                         //每十个数换一行
					num=0;
					pw.println();
				}
			}
		}
		fw.close();                                     //关闭文本文件
	}
}

运行结果为:

12313

最后

好了,关于Java  I/O流——面向字符输入/输出流的知识学到这里,谢谢观看!!!

我们下篇文章再见!!!

成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐