Java I/O流——面向字符输入/输出流(超详细)
前言上篇文章中,我们学习了Java I/O流——面向字节的输入/输出流(超级详细),字节流中数据的最小单元为字节,而Java采用Unicode字符编码,对每个字符,JVM会为其分配2字节的内存,而用字节流类读/写字符文本会很不方便,因此,java.io包中提供了Reader/Writer类,用表示字符的输入/输出流。字符编码在读/写文本文件时,最主要的问题是进行字符编码的转换。文本文件中字符有可能
目录
前言
上篇文章中,我们学习了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的后代,如下图所示:
- 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)类实例
使用字符输入流读取文件内容:
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(); //强制刷新流
}
}
运行结果为:
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类型并输出文件中的内容
}
}
}
运行结果为:
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(); //关闭文本文件
}
}
运行结果为:
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();
}
}
运行结果为:
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(); //关闭文本文件
}
}
运行结果为:
最后
好了,关于Java I/O流——面向字符输入/输出流的知识学到这里,谢谢观看!!!
我们下篇文章再见!!!
成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)