------- java学习型技术博客、期待与您交流 ----------
Java基础,IO流总结之字节流
什么是字节流?
字节流是指基本单位是一个字节的信息系列。
字节流的好处
因为各种信息在计算机中是以8位二进制(字节)来处理的,所以可以将各种信息用字节流来统一处理,也就是说用字节流可以处理各种信息,包括文件。
字节流按照数据的方向划分有两个基类InputStream类和OutputStream类。
InputStream类
抽象类InputStream是所有字节输入流的根类,该类及其子类对象表示一个字节输入流利用该类的方法可以从流中一次读取一个或多个字节。
InputStream类常用方法:
InputStream的常用直接已知子类:
|InputStream
OutputStream类
抽象类OutputStream是所有字节输出流的根类,该类及其子类的对象表示一个字节输出流。利用类中的方法,可以向流中写入一个或多个字节。
OutputStream类常用方法:
OutputStream的常用直接已知子类:
|OutputStream
|FileOutputStream,
|ByteArrayOutputStream
|FilterOutputStream
|ObjectOutputStream
|PipedOutputStream
文件字节流:
我们经常要用字节流来处理文件,在字节输入和输出流中有两个类专门用来处理文件的类FileInputStream和 FileOutputStream。
FileInputStream和 FileOutputStream示例,通过字节输出流向一个文件中输入数据,然后通过字节输入流读取文件中的数据并打印。代码如下:
import java.io.*;
class FileStream
{
public static void main(String[] args) throws IOException
{
readFile_2();
}
//读取方式一:通过字节数组进行读取
public static void readFile_2()throws IOException
{
//定义一个字节输入流并关联一个文件
FileInputStream fis = new FileInputStream("fos.txt");
//定义一个字节数组用于存储读取到的数据
byte[] buf = new byte[1024];
int len = 0;
//将流中的字节数据读取到数组中并通过数据输出
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
//关闭流
fis.close();
}
//读取方式二:一次读取单个字节
public static void readFile_1()throws IOException
{
//定义一个字节输入流并关联一个文件
FileInputStream fis = new FileInputStream("fos.txt");
int ch = 0;
//一次读取一个字节,将读取到的字节数据转成字符后输出
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
fis.close();
}
//向一个文本文件中输入字节数据
public static void writeFile()throws IOException
{
//定义一个字节输出流并关联文件对象
FileOutputStream fos = new FileOutputStream("fos.txt");
//将一个字符串转成字符数组后写入字节输出流
fos.write("abcde".getBytes());
//关闭流对象
fos.close();
}
}
示例2:复制一个图片文件。
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
//用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
fos = new FileOutputStream("c:\\2.bmp");
//用字节读取流对象和图片关联。
fis = new FileInputStream("c:\\1.bmp");
//定义一个数组用于存储读取到的字节数据
byte[] buf = new byte[1024];
int len = 0;
//通过字节输入流将图片的字节数据读取至字节数组后将其写入字节输出流中
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
//关闭流
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
字节流缓冲区:
和字符流一样,字节流内部也有自己的缓冲技术以提高数据的读写效率,字节流的缓冲流对应两个类,BufferedInputStream和BufferedOutputStream。
字节流缓冲区示例,通过缓冲区技术复制一个Mp3文件。
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
copy();
}
//通过字节流的缓冲区完成复制
public static void copy()throws IOException
{
//定义一个字节输入缓冲流,并传入需要缓冲的字节输入流对象
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
//定义一个字节输出缓冲流,并传入需要缓冲的字节输出流对象
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
//字节输入流中的数据读出后,写入字节输出流
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
//关闭流
bufos.close();
bufis.close();
}
}
转换流
转换流引入示例:需求,读取键盘录入,当读取到回车符时将读取到的数据转换成大写后在控制台输出,如果输入了”over”则结束程序,需要用到PrintStream类的一个实例System.in 。
import java.io.*;
class ReadIn
{
public static void main(String[] args) throws IOException
{
//将键盘输入作为字节输入流
InputStream in = System.in;
//因为最终要输出字符串,定义一个StringBuilder
StringBuilder sb = new StringBuilder();
while(true)
{
//通过字节输入流读取键盘输入数据
int ch = in.read();
//如果读取到的字符是windows换行标志中的第一个字符'\r'时继续往后读取
if(ch=='\r')
continue;
//当读取到连续的'\r''\n'时,表示到了行的末尾
if(ch=='\n')
{
//将读取到的一行数据转换成字符串
String s = sb.toString();
//如果该行数据为over则停止录入
if("over".equals(s))
break;
//将读取到的一行数据转换成大写后输出
System.out.println(s.toUpperCase());
//清空StringBuilder
sb.delete(0,sb.length());
}
//如果没读到行结尾就将读取到的数据存入sb中
else
sb.append((char)ch);
}
}
}
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?答案是可以的,需要用到转换流,也称作桥梁流:
InputStreamReader:字节流通向字符流的桥梁
OutputStreamWriter:字符流通向字节流的桥梁(一般在处理编码问题的时候用到)
有了转换流,可以将上面程序中的字节流对象转换成字符流对象,进而使用字符流缓冲类的readLine()方法。
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
/*
1,定义一个字节读取流对象获取键盘录入
2,使用InputStreamReader转换流将字节流对象转换成字符流对象
3,为了提高效率,使用字符流缓冲区BufferedReader对转换后的字符流进行缓冲
*/
//键盘的最常见写法。
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//使用OutputStreamWriter将标准输出转换成字节流对象并引入缓冲
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
//使用字符流缓冲区的方法对键盘输入的数据进行操作
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
bufr.close();
}
}
IO流体系的作用使用其实很简单,就是读取和写入。但是因为功能的不同,流的体系中提供N多的对象。那么到底该用哪个对象更为合适呢?这就需要明确流的操作规律。
流的操作规律:
1,明确源和目的。
数据源:就是需要读取,可以使用两个体系:InputStream、Reader;
数据汇:就是需要写入,可以使用两个体系:OutputStream、Writer;
2,操作的数据是否是纯文本数据?
如果是:数据源:Reader
数据汇:Writer
如果不是:数据源:InputStream
数据汇:OutputStream
3,虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?
明确操作的数据设备。
数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。
4,需要在基本操作上附加其他功能吗?比如缓冲。
如果需要就进行装饰。
------- java学习型技术博客、期待与您交流 ----------