字符流处理的数据都是文字,需要将指定的数据,查指定的编码表。而字节流处理的数据不一定都是文字数据,所以是不需要指定查表的。直接在操作文件数据的时候,就将具体的字节数据写入到目的。
字节流常用的对象:
抽象基类:InputStream 和 OutputStream
InputStream
|-------FileInputStream
|-------BufferedInputStream
OutputStream
|--------FileOutputStream
|--------BufferedOutputStream
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
/*
* 需求:读取一个文件。用字节流。
*/
FileInputStream fis = new FileInputStream("tempfile\\fos.txt");
//读取并存储到数组,将数组打印。以该种方式。
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
System.out.println(fis.available()); //获取流关联的文件的剩余字节数。
fis.close();
}
}
在上述例子中,
1. 我们自定义了缓冲区 来达到高效的目的,当然也可以用 BufferedInputStream 自带的缓冲区。
2. 用到的read()方法 返回值为:读入缓冲区的字节总数,如果因为已经到达流末尾而没有更多的数据,则返回 -1。
3. available() 方法 :获取流关联的文件的剩余字节数。
下面要完成的示例是:
将一串文本数据,写到本地硬盘上去。用FileOutputStream。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("tempfile\\fos3434.txt");
fos.write("abcdef".getBytes());//字节流的直接操作文件写入时,直接将数据写入到目的地。 FileOutputStream不支持对字符串的直接操作,因此需要转为 字节数组。
// fos.flush();使用的是父类OutputStream的flush。该方法什么都没有做,只有OutputStram某一些子类定义了该方法的具体内容。
fos.close();//必须有,因为要关闭资源。
}
}
在这个示例中,我们应当注意:
1. 不需要 flush()。这是为什么呢,而操作字符就的FileWriter 为啥需要刷呢?
那是因为FileWriter底层使用了字节流在操作字符数据时,会先将这些数据进行临时存储,并查指定的编码表。按照指定的编码表中的内容写入到目的地。
比如:
对于字符——"你好",用FileWriter操作时,需要先将读到的字符临时存储然后,查找编码表,然后转成对应的数字字节,再写到目的地中去。
而字节流处理的数据不一定都是文字数据,所以是不需要指定查表的。直接在操作文件数据时,就将具体的字节数据写入到目的地。
2. 但必须有 close() 方法,用来关闭调用的系统资源。
接下里,我们将完成的示例是,CopyMp3!这个示例,我们将综合前面学的所以知识来完成,
我们将会见到在复制的过程中,不用缓冲区,用默认缓冲区,用刚好合适的缓冲区,用自定义的缓冲区等等情况下的,复制状态,以及效率。
对于效率的监控,我们用复制完成后的当前系统时间和 复制前的当前系统时间 差值来表示。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyMp3Test {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
copy_1();
long end = System.currentTimeMillis();
System.out.println("毫秒值:"+(end-start));
}
//不用缓冲区。
public static void copy_4() throws IOException {
FileInputStream fis = new FileInputStream("C:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\4.mp3");
int by = 0;
while((by=fis.read())!=-1){
fos.write(by);
}
fos.close();
fis.close();
}
//不建议。使用刚刚好的缓冲区。因为文件过大会溢出。
public static void copy_3() throws IOException {
FileInputStream fis = new FileInputStream("C:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\3.mp3");
byte[] buf = new byte[fis.available()];
fis.read(buf);
fos.write(buf);
fos.close();
fis.close();
}
//使用字节流已有的缓冲区。
public static void copy_2() throws IOException {
FileInputStream fis = new FileInputStream("C:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\2.mp3");
BufferedInputStream bufis = new BufferedInputStream(fis);
BufferedOutputStream bufos = new BufferedOutputStream(fos);
// //3,定义一个字节缓冲区。
// byte[] buf = new byte[1024];
int by = 0;
while((by=bufis.read())!=-1){
bufos.write(by);
}
bufos.close();
bufis.close();
}
//自定义数组缓冲区的方式。
public static void copy_1() throws IOException {
//1,读取流对象,和mp3关联。
FileInputStream fis = new FileInputStream("C:\\0.mp3");
//2,写入流对象,明确存储mp3数据的目的。
FileOutputStream fos = new FileOutputStream("c:\\1.mp3");
//3,定义一个字节缓冲区。
byte[] buf = new byte[1024*8];
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
fis.close();
}
}
至此,我们已经介绍完了字符流和字节流。但是,我们会注意到这样一个问题,程序中所需要的数据,都是事先已经定义好的,那么程序能否处理,由我们输入的数据呢?即读取键盘的数据。答案是肯定的,那么又该如何读取呢,是否有相应的对象?