三、字节输入流:(InputStream)(重点)
InputStream可以实现数据的读取操作,在java中InputStream类的定义如下:
public abstract class InputStream implements Closeable
InputStream类中定义有三个数据的读取操作方法:
- 读取单个字节:
public abstract int read() throws IOException;
每次执行此方法将读取当个字节数据,如果已经读取完成了,那么最后返回-1。
读取数据到字节数组中:public int read(byte b[]) throws IOException.最常用方法
每次讲数据读取到数组之中,那么会返回一个读取长度的数据,如果没有数据则返回的长度为-1,可是要考虑两种情况:
要读取的内容大于开辟的数组内容:长度就是整个数组的长度。
要读取的内容小于开辟数组的内容,
长度就是全部最后的内容长度,数组装不满。
读取部分内容到字节数组中:public int read(byte b[], int off,int len) throws IOException;
每次读取内容到部分字节数组,只允许读取满限制的数组的字节个数。此方法依然会返回读取的长度。
整个操作跟输出的形式几乎是相同的,参数的类型及作用也几乎是相同的。
InputStream是一个抽象类,所以要进行文件的读取使用FileInputStream子类,子类定义的构造方法如下:
构造方法:public FileInputStream(File file) throws FileNotFoundException.
范例:实现数据的读取
package lisy; import java.awt.print.Printable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Date; import java.text.SimpleDateFormat; @SuppressWarnings("unused") public class Demo { public static void main(String[] args) throws IOException { //第一步:定义要输出的文件的File类对象 File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt"); //第二步:实例化InputStream InputStream input = new FileInputStream(file); //实现数据的读取操作 byte data[] = new byte[1024]; int len = input.read(data);//将数据读取到数组之中 System.out.println("读取的内容【" +new String(data,0,len)+"】"); //第四步关闭输入流 input.close(); } }
使用InputStream类中提供的一个read()方法,这个方法可以实现单个字节数据的读取操作。
范例:读取单个字节
package lisy; import java.awt.print.Printable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Date; import java.text.SimpleDateFormat; import javax.swing.table.TableModel; @SuppressWarnings("unused") public class Demo { public static void main(String[] args) throws IOException { //第一步:定义要输出的文件的File类对象 File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");//你的路径 //第二步:实例化InputStream InputStream input = new FileInputStream(file); //实现数据的读取操作 byte data[] = new byte[1024]; int foot = 0;//控制保存的脚标索引 int temp = 0;//接收每次保存的字节数据 //while循环实际上按照由里向外的原则执行,它的执行分为两步: //第一步:“temp = input.read()”,表示读取一个字节保存到temp变量之中。 //第二步:“(temp = input.read()) != -1”判断读取出来的temp内容是否为-1, //如果不是-1则表示还有数据,则进行保存。 while((temp = input.read()) != -1);{ data[foot ++] = (byte) temp; } System.out.println("读取的内容【" +new String(data,0,foot)+"】"); //第四步关闭输入流 input.close(); } }
四、字符输出流:(Writer)
Writer是进行字符输出操作使用的类,这个类属于抽象类,观察定义:
public abstract class Writer implements Appendable, Closeable, Flushable
这个Writer类可以直接输出字符串:public void write(String str) throws IOException
Writer是一个抽象类,要进行文件字符流操作,其构造方法为:
public FileWriter(File file)。
范例:使用Writer输出数据
package lisy; import java.awt.print.Printable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Date; import java.text.SimpleDateFormat; import javax.swing.table.TableModel; @SuppressWarnings("unused") public class Demo { public static void main(String[] args) throws IOException { //第一步:定义要输出的文件的File类对象 File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");//你的路径 if(!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } Writer out = new FileWriter(file); String str = "一定要好好学习,天天向上。。。"; out.write(str); out.close(); } }
虽然Writer类提供有字符数组的输出操作能力,但是从本质上来讲使用Writer类就意味着要执行字符串的直接输出。
字符流最适合操作中文,但并不意味着字节流就无法操作中文。
五、字符输入流:(Reader)
Reader一定是一个抽象类,其定义为:
public abstract class Reader extends Object implements Readable,Closeable
在Reader类中也提供有一系列的read()方法。
- 数据的读取:
public int read(char[] cbuf) throws IOException。
范例:数据的读取
package lisy; import java.awt.print.Printable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Date; import java.text.SimpleDateFormat; import javax.sql.rowset.CachedRowSet; import javax.swing.table.TableModel; @SuppressWarnings("unused") public class Demo { public static void main(String[] args) throws IOException { //第一步:定义要输出的文件的File类对象 File file = new File("e:"+File.separator+"hello"+File.separator+"my.txt");//你的路径 if(file.exists()) { Reader in = new FileReader(file); char data[] = new char[1024]; int len = in.read(data);//向字符数组保存数据,返回长度。 System.out.println(new String(data,0,len)); in.close(); } } }
六、字节流与字符流的区别
首先必须要明确一点,通过任何终端(网络、文件)读取或者输出的数据都一定是字节,但是字符是经过内存处理后的数据。
字符输入:字节(磁盘)–> 自动转换为 –>字符(内存);
字符输出:字符(内存)–> 自动转换为–>字节(磁盘);
在利用字符流输出的时候,所有的内容实际上都只是输出到了缓冲区中(内存)。在使用close()方法关闭的时候会将我们缓冲区的数据进行输出,如果没有关闭,那么就将无法进行输出,此时可以利用flush()方法进行强制的输出。
字符使用到了缓冲区,而字节流没有使用到缓冲区。
如果处理中文使用字符流,其他的任何数据都使用字节流。