IO流3之字节流和高效流
一、字节流的一些概况
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,
操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,
所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点
所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。
在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
2. 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以
字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,
它是按字节来处理的 但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,
也就是要进行字符集的转化 这两个之间通过 InputStreamReader,OutputStreamWriter来关联,
实际上是通过byte[]和String来关联 在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的
Reader类的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),
如果已到达流的末尾,则返回 -1
inputStream的read()虽然也返回int,但由于此类是面向字节流的,一个字节占8个位,
所以返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。
因此对于不能用0-255来表示的值就得用字符流来读取!比如说汉字.
操作流程
在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:
1 使用File类打开一个文件
2 通过字节流或字符流的子类,指定输出的位置
3 进行读/写操作
4 关闭输入/输出
IO操作属于资源操作,一定要记得关闭
字节流
字节流主要是操作byte类型数据,以byte数组为准,主要操作类就是OutputStream、InputStream
字节输出流:OutputStream
OutputStream是整个IO包中字节输出流的最大父类,此类的定义如下:
public abstract class OutputStream extends Object implements Closeable,Flushable
从以上的定义可以发现,此类是一个抽象类,如果想要使用此类的话,则首先必须通过子类实例化对象,那么如果现在要操作的是一个文件,则可以使用:FileOutputStream类。通过向上转型之后,可以为OutputStream实例化
Closeable表示可以关闭的操作,因为程序运行到最后肯定要关闭
Flushable:表示刷新,清空内存中的数据
FileOutputStream类的构造方法如下:
public FileOutputStream(File file)throws FileNotFoundException
1.用字节流复制文本文件
其实复制文本文件,我们可以使用字节流和字符流,这里我们主要使用字节流
用字节流复制文本文件。
* 把项目路径下的FileOutputStreamDemo.java复制到d:\\Copy.java中。
*
* 数据源:
* FileOutputStreamDemo.java -- 读取数据 -- FileInputStream
* 目的地:
* FileOutputStreamDemo.java -- 写入数据 -- FileOutputStream
public class CopyFile {
public static void main(String[] args) throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
// 封装目的地
FileOutputStream fos = new FileOutputStream("d:\\Copy.java");
// 基本读写操作
// 方式1
// int by = 0;
// while((by=fis.read())!=-1){
// fos.write(by);
// }
// 方式2
byte[] bys = new byte[1024];
int len = 0;
while((len=fis.read(bys))!=-1){
fos.write(bys,0,len);
}
// 释放资源
fos.close();
fis.close();
}
}
2,字节流复制二进制流数据
然而对于一些文件而言,我们只能使用字节流对其进行复制的,这种文件我们叫做二进制流文件
二进制流数据:图片,视频,音频等。
* 由于二进制的合并为字符,在我们使用的编码表中没有对应的数据,那么,将来在写回去的时候,就会有数据的丢失。
* 所以,二进制流数据只能使用字节流进行操作
例如,下面是字节流复制图片的代码体现
public class CopyImage {
public static void main(String[] args) throws IOException {
// method1();
method2();
}
// 用字节流--一次一个字节数组
private static void method2() throws IOException {
// 封装数据源和目的地
FileInputStream fis = new FileInputStream("mn.jpg");
FileOutputStream fos = new FileOutputStream("d:\\mn.jpg", true);
// 读写
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 释放资源
fos.close();
fis.close();
}
// 用字符流--一次一个字符
private static void method1() throws IOException {
// 封装数据源和目的地
FileReader fr = new FileReader("mn.jpg");
FileWriter fw = new FileWriter("d:\\mn.jpg");
// 基本读写
int ch = 0;
while ((ch = fr.read()) != -1) {
fw.write(ch);
// fw.flush();
}
// 释放资源
fw.close();
fr.close();
}
}
二、字符缓冲流,也称高效流
在编程的过程中,为了能够使得代码运行得更加的流畅和快速高效,我们引进了高效流
我们开始自己定义数组,给出缓冲区大小,是为了提高效率。
* 那么,java在设计类的时候,它也考虑到了这一点,所以,就提供了一种高效的流。带缓冲区的流。
* BufferedWriter:写入数据
* BufferedReader:读取数据
*
* BufferedWriter:
* 构造方法:BufferedWriter(Writer out)
* 为什么传递的是Writer呢?
* 因为BufferedWriter这种流,被称为缓冲流,它只提供数据的缓冲功能。
* 真正的读写还得靠别人。所以,我们这里将使用FileWriter作为参数传递。
*
* 缓冲区只提供缓冲功能,没有真正的读写。
*
* 基本流:能直接进行读写的流对象。
* 高级流:站在基本流的基础上,提供一些特殊的功能。(处理流。)
而其中,有两个重要的方法
* BufferedWriter:
* public void newLine():根据系统平台写入行分隔符
*
* BufferedReader:
* public String readLine():一次读取一行的数据。但是不包含换行符。
读取:
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 创建字符缓冲流对象
BufferedReader br = new BufferedReader(new FileReader("c.txt"));
// 读取数据
// int ch = 0;
// while ((ch = br.read()) != -1) {
// System.out.print((char) ch);
// }
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
br.close();
}
}
写入:
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
// 创建缓冲流对象
// Writer fw = new FileWriter("c.txt");
// FileWriter fw = new FileWriter("c.txt");
// BufferedWriter bw = new BufferedWriter(fw);
BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt"));
// 写入数据
bw.write("hello");
bw.flush();
// 释放资源
// fw.close();// 这个不用关闭
bw.close();
}
}
newLine() 和readLine()
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
// 写数据
// BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
// for (int x = 0; x < 5; x++) {
// bw.write("hello" + x);
// // bw.write("\r\n");
// bw.newLine();
// bw.flush();
// }
//
// bw.close();
// 读取数据
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
/*
String line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
*/
String line = null;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
三、打印流PrintWriter
PrintStream:字节打印流
* PrintWriter:字符打印流
*
* 打印流特点:
* A:可以写入任意类型的数据。
* B:可以自动刷新。必须先启动,并且是使用println,printf及format方法才有效。
* C:可以直接对文件进行写入。
* 哪些流对象是可以直接对文件进行操作的?
* 看构造方法,是否有同时接受File和String类型的参数构造。
*
* 注意:打印流只有写数据的,没有读取数据的。
*
* 构造方法:
* PrintWriter(String fileName)
public class PrintWriterDemo2 {
public static void main(String[] args) throws IOException {
PrintWriter pw = new PrintWriter("b.txt");
//使用print
pw.print(true);
pw.print(123.123);
pw.print("hello");
pw.flush();
pw.close();
}
}