标签:
IO流:
包括字节流和字符流。
在这里解释一下我对于流的理解,其实流就相当于一个用来运输字节或者字符的管道,一开始会把所有的数据存放到流中,然后我们再从流中取出数据(进行读取或者写出操作),每读或者写一次就会从管道中把读或者写的数据取出来,管道中就没有了你刚才读到或者写出的数据了。比如:
FileInputStream fis = new FileInputStream(String filename);
就会把文件名为filename的文件内容全部存放到管道中去,然后我们进行fis.read(),就会从管道中读取出内容,读到的内容就会从管道中消失。
(1)InputStream:抽象了应用程序读取数据的方式
OutputStream : 抽象了应用程序写出数据的方式
(2)输入流的基本方法:
InputStream in = new InputStream();
int b = in.read();
读取一个字节无符号填充到int的最后8位,当读到-1时,标识读取到最后结束了。
in.read(byte[] buf):读取的数据填充到字节数组buf中
in.read(byte[] buf,int start ,int size):读取数据到字节数组buf,并且是从buf的start位置开始,存放size长度的数据
(3)输出流的基本方法:
OutputStream out = new OutputStream();
out.write(int b):写出一个字节到流,写的是int的最后的8位
out.write(byte[] buf):将buf字节数组都写入到流
out.write(byte[] buf,int start,int size):字节数组buf从start位置开始写size长度的字节到流
下面介绍字节流基本的读取方法的使用(注意:FileInputStream继承了InputStream)
package com.test.FileInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamTest {
public static void main(String[] args) {
try {
System.out.println("方式一:字节数组的长度足够存储读取的内容");
ReadFile1("C:\\Users\\Administrator\\Desktop\\javaIO\\读取的测试文件.txt");
System.out.println();
System.out.println("方式二:字节数组的长度不足以存储读取的内容");
ReadFile2("C:\\Users\\Administrator\\Desktop\\javaIO\\读取的测试文件.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 当字节数组的大小足够存储读取的内容的时候
* 只读取一次,然后打印出来就可以了
*/
public static void ReadFile1(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
byte[] buf = new byte[1024];
//从fis中批量读取字节,放入到buf这个字节数组中,
//从第0个位置开始放,最多放buf.length个
//返回的是读到的字节的个数
int bytes = fis.read(buf, 0, buf.length);
int j = 1;
for(int i=0;i<bytes;i++){
//byte类型8位,int类型32位,为了避免数据转换错误,通过&0xff将高24位清零
System.out.print(Integer.toHexString(buf[i]&0xff)+" ");
if(j++%10==0){//每读取10个字节就换行
System.out.println();
}
}
fis.close();
}
/**
* 当数组的大小没法存储读取的全部的字节的时候,
* 就要对该字节数组进行重复利用,
* 每读取字节数组的长度的内容的时候就打印出来,
* 然后再次读取该字节数组长度的内容,
* 直到把所有的内容读取出来
*/
public static void ReadFile2(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
byte[] buf = new byte[1024];
int bytes = 0;
int j = 1;
while((bytes = fis.read(buf, 0, buf.length))!=-1){//如果数组不是足够大,要进行多次的读取操作
for(int i = 0;i<bytes;i++){
System.out.print(Integer.toHexString(buf[i]&0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
}
fis.close();
}
}
读取的文件内容:
读取结果截图:
下面对比下单字节读取与批量读取文件的效率:
package com.test.FileInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 对比单字节读取与批量读取同样的文件的所用的时间
* 2015年8月8日 下午9:24:31
*
*/
public class FileInputStreamTest1 {
public static void main(String[] args) {
try {
ReadFile1("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
ReadFile2("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 单字节读取文件的方式
* @param filename
* @throws IOException
*/
public static void ReadFile1(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
int b;
int i = 1;
long start = System.currentTimeMillis();
while((b = fis.read())!=-1){
// System.out.print(Integer.toHexString(b&0xff)+" ");
if(i++%10==0){
// System.out.println();
}
}
long end = System.currentTimeMillis();
System.out.println("单字节读取所用的时间:"+(end-start));
fis.close();
}
/**
* 批量字节读取的方式
* @param filename
* @throws IOException
*/
public static void ReadFile2(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
byte[] buf = new byte[1024];
int b;
int j = 1;
long start = System.currentTimeMillis();
while((b = fis.read(buf, 0, buf.length))!=-1){
for(int i = 0;i<b;i++){
// System.out.print(Integer.toHexString(buf[i]&0xff)+" ");
if(j++%10==0){
// System.out.println();
}
}
}
long end = System.currentTimeMillis();
System.out.println("批量读取所用的时间:"+(end-start));
fis.close();
}
}
所以,批量读取,对于大文件而言效率高,也是我们最常见的读文件的方式。单字节读取不适合大文件,大文件读取的效率很低。
下面介绍字节流基本的写出方法的使用(注意:FileOutputStream继承了OutputStream,实现了向文件中写出byte数据的方法)
package com.test.FileOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
public static void main(String[] args) {
try {
WriteFile("C:\\Users\\Administrator\\Desktop\\javaIO\\写入测试文件.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void WriteFile(String filename) throws IOException{
//如果该文件不存在,则直接创建,如果存在,删除后创建
FileOutputStream fos = new FileOutputStream(filename);
// //如果该文件不存在,则直接创建,如果存在,直接在文件中追加内容
// FileOutputStream fos = new FileOutputStream(filename,true);
/*
* 写一个字符的方法(可以写一个字符)
*/
fos.write(‘A‘);//写出了‘A’的字节所占位的最后八位
fos.write(‘B‘);
/*
* 写一个整数的方法
*/
int i = 10;//write()方法只能写八位,那么写一个int需要写4次,每次8位
fos.write(i>>>24);
fos.write(i>>>16);
fos.write(i>>>8);
fos.write(i);
/*
*写一个字节数组的方法 (可以直接写一个字节数组)
*/
byte[] gbk = "小灰灰".getBytes("gbk");
fos.write(gbk);
fos.close();
}
}
基本的字节输入流和字节输出流的整合运用:(以Copy文件为例)
package com.test.FileOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) {
File srcFile = new File("C:\\Users\\Administrator\\Desktop\\javaIO\\被copy的文件.txt");
File destFile = new File("C:\\Users\\Administrator\\Desktop\\javaIO\\copy的文件.txt");
try {
copyFile(srcFile, destFile);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void copyFile(File srcFile,File destFile) throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] buf = new byte[3*1024];
int i;
while((i = fis.read(buf,0,buf.length))!=-1){
fos.write(buf, 0, i);
fos.flush();
}
fis.close();
fos.close();
}
}
DataOutputStream/DataInputStream的使用:
作用:
对“流”功能的扩展,可以更加方便的读取int,long,字符等基本类型的数据。
构造方法:
DataOutputStream dos = new DataOutputStream(OutputStream out);
DataInputStream dis = new DataInputStream(InputStream in);
从构造方法中可以看到这两种流就是对普通流进行了包装,方便读取基本类型的数据。
DataOutputStream多出来的写出的方法:
writeInt()
writeDouble()
writeLong()
writeChars()//采用UTF-16BE编码写出
writeUTF()//采用UTF-8编码写出
……
writeInt():
write()方法一次只可以写出最后的8位,但是int类型的数据是32位(4个字节),所以要write()四次才能写出一个int类型的数据。
int i = 10;//write()方法只能写八位,那么写一个int需要写4次,每次8位
fos.write(i>>>24);
fos.write(i>>>16);
fos.write(i>>>8);
fos.write(i);
这是我们写一个int类型数据的方法。
writeInt()方法可以只写一次就可以写出一个int类型的数据,其实查看源码可以知道其实也是write()了四次。
writeInt()方法的源码:
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
writeLong(),writeDouble()……也是这样的原理。
所以可以看出DataOutputStream就是对基本类型的数据的写出方法进行了包装,方便我们写出基本类型的数据。
BufferedInputStream/BufferedOutputStream的使用:
这两个流为IO提供了带缓冲区的操作,一般打开文件进行写入或者读取操作时,都会加上缓冲,这种流模式提高了IO的性能。
解释:
从应用程序中把数据放入文件,相当于将一缸水倒入另一个缸中。
FileOutputStream—–>write()方法相当于一滴水一滴水的把水转过去
DataOutputStream—>writeXxx()方法会方便一些,相当于一瓢一瓢的转移过去
BufferedOutputStream—>write()方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入到另个缸中,性能提高了。
注意:当使用BufferedOutputStream的时候,当写完一次后要进行冲刷缓冲区(flush()),否则下次进行写入的时候就没法向缓冲区中存放了。
下面比较一下这些流读取和写入操作的效率:
package com.test.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 对比单字节读取与批量读取同样的文件的所用的时间
* 2015年8月8日 下午9:24:31
*
*/
public class FileInputStreamTest1 {
public static void main(String[] args) {
try {
ReadFile1("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
ReadFile2("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
ReadFile3("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
ReadFile4("C:\\Users\\Administrator\\Desktop\\javaIO\\问尘 - 洛天依.mp3");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 单字节读取文件的方式
* @param filename
* @throws IOException
*/
public static void ReadFile1(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
int b;
int i = 1;
long start = System.currentTimeMillis();
while((b = fis.read())!=-1){
// System.out.print(Integer.toHexString(b&0xff)+" ");
if(i++%10==0){
// System.out.println();
}
}
long end = System.currentTimeMillis();
System.out.println("单字节读取所用的时间:"+(end-start));
fis.close();
}
/**
* 批量字节读取的方式
* @param filename
* @throws IOException
*/
public static void ReadFile2(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
byte[] buf = new byte[1024];
int b;
int j = 1;
long start = System.currentTimeMillis();
while((b = fis.read(buf, 0, buf.length))!=-1){
for(int i = 0;i<b;i++){
// System.out.print(Integer.toHexString(buf[i]&0xff)+" ");
if(j++%10==0){
// System.out.println();
}
}
}
long end = System.currentTimeMillis();
System.out.println("批量读取所用的时间:"+(end-start));
fis.close();
}
/**
* 字节缓冲流读取文件
* @param filename
* @throws IOException
*/
public static void ReadFile3(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);
long start = System.currentTimeMillis();
int b;
int j = 1;
while((b=bis.read())!=-1){
for(int i=0;i<b;i++){
// System.out.println(Integer.toHexString(b&0xff)+" ");
if(j++%10==0){
// System.out.println();
}
}
}
long end = System.currentTimeMillis();
System.out.println("字节缓冲流读取所用的时间:"+(end-start));
bis.close();
}
/**
* 字节缓冲流批量读取文件
* @param filename
* @throws IOException
*/
public static void ReadFile4(String filename) throws IOException{
FileInputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buf = new byte[1024*3];
long start = System.currentTimeMillis();
int b;
int j = 1;
while((b= bis.read(buf, 0, buf.length))!=-1){
for(int i = 1;i<b;i++){
// System.out.println(Integer.toHexString(buf[i]&0xff)+" ");
if(j++%10==0){
// System.out.println();
}
}
}
long end = System.currentTimeMillis();
System.out.println("字节缓冲流批量读取所用的时间"+(end-start));
bis.close();
}
}
所用时间结果截图:
由此可以看出:
批量读取文件的效率>字符缓冲流读取文件的效率>单字节读取文件的效率
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u013991521/article/details/47320043