Java I/O流基础
1、 JAVA的IO类库的基本构架
JAVA的IO操作类在包java.io下,基本可以分为
基于字节操作的I/O接口:InputStream和OutputStream
基于字符操作的I/O接口:Writer和Reader
基于硬盘操作的I/O接口:File
基于网络的操作I/O接口:Soctet

1.1、 字节流和字符流的区别
实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,但是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。
实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,但是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。
实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,但是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。
因为很重要,所以说三遍。。
使用字节流好还是字符流好呢?
答案是字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。
2、 字节流的IO操作。
向文件中写入string
package iostream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String filename = "d:" + File.separator + "iotest.txt";
File f = new File(filename);
OutputStream outputStream = new FileOutputStream(f);
String str = "Helloworld";
byte[] b = str.getBytes();
outputStream.write(b);
outputStream.close();
}
}
从文件中读取数据
package iostream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String filename = "d:" + File.separator + "iotest.txt";
File f = new File(filename);
InputStream inputStream = new FileInputStream(f);
StringBuffer sb = new StringBuffer();
byte[] b = new byte[1024];
int len = -1;
while ((len = inputStream.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
inputStream.close();
}
}
3、 字符流操作
写入文件操作
package iostream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String filename = "d:" + File.separator + "iotest.txt";
File f = new File(filename);
// 第二个参数为追加字符
Writer w = new FileWriter(f, true);
w.write("3w.avfun.tv");
w.close();
}
}
读取文件操作
package iostream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String filename = "d:" + File.separator + "iotest.txt";
File f = new File(filename);
// 第二个参数为追加字符
Reader r = new FileReader(f);
char[] c = new char[100];
int index =-1;
while ((index = r.read(c)) != -1) {
System.out.println(c);
}
}
}
4、 文件类
package iostream;
import java.io.File;
import java.io.IOException;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//File.separator 表示分隔符
File file1 = new File("D:"+File.separator+"yyd"+File.separator+"cdut.txt");
//路径分隔符
// String s = File.pathSeparator;
//文件是否存在
if(!file1.exists()){
try {
//创建一个新文件
boolean b = file1.createNewFile();
System.out.println("创建文件:"+b);
} catch (IOException e) {
e.printStackTrace();
}
}
//删除文件
//System.out.println(file1.delete());
//得到文件的上一级路径
System.out.println(file1.getParent());
//判断一个路径是否是文件夹
System.out.println("是否是目录:"+file1.isDirectory());
////判断一个路径是否是文件
System.out.println("是否是文件:"+file1.isFile());
File file2 = new File("d:\\yydt");
//列出文件夹中的所有文件名
String[] fileName = file2.list();
for (String s : fileName) {
System.out.println(s);
}
//列出文件夹中的所有文件,以File数组返回
File[] files = file2.listFiles();
for (File file : files) {
System.out.println(file.getPath()+"---"+file.length());
}
//创建文件夹
File file3 = new File("d:\\zhangsan\\lisi");
file3.mkdirs();
//重命名
File file4 = new File("d:\\zhangsan\\wangwu");
file3.renameTo(file4);
}
}
5、 流转换
读入流操作。
package iostream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class iotest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File file = new File("D:" + File.separator + "iotest.txt");
InputStream inputStream = new FileInputStream(file);
Reader reader = new InputStreamReader(inputStream);
char[] c = new char[100];
int index = -1;
while ((index = reader.read(c)) != -1) {
System.out.println(c);
}
inputStream.close();
reader.close();
}
}
流的基本操作算是写完了。那么该深入分析。
2.1、几种访问文件的方式
1)标准访问文件的方式
标准访问文件的方式就是当应用程序调用read()接口时,操作系统检查内核的高速缓存中有没有需要的数据,如果已经缓存了。那么直接从缓存中返回,如果没有则从磁盘中读取,然后缓存在操作系统的缓存中。
写入的方式是,用户的应用程序调用write()接口将数据从用户地址空间复制到内核的地址空间缓存中。
2)直接的I/O方式
所谓的直接IO方式就是应用程序直接访问磁盘数据,而不经过操作系统内核缓冲区,这样做的目的就是减少一次从内核缓冲区到用户程序缓存的数据复制
卧槽!我已经不想吐槽两个的效率问题了!源码如下
E:/qq文件/Visio_2010_Premium_W32_Std_Pro_Prem.iso
使用缓冲区读取耗时:24948ms
直接读取耗时:1045385ms
package iostream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class iotest {
public static void main(String args[]) throws IOException {
String from = "E:/qq文件/Visio_2010_Premium_W32_Std_Pro_Prem.iso";
System.out.println(from);
long startTime1 = System.currentTimeMillis();
iotest.readWriteWithBuffer(from,
"f:/Visio_2010_Premium_W32_Std_Pro_Prem1.iso");
long endTime1 = System.currentTimeMillis();
System.out.println("使用缓冲区读取耗时:" + (endTime1 - startTime1) + "ms");
long startTime = System.currentTimeMillis();
iotest.readWrite(from, "f:/Visio_2010_Premium_W32_Std_Pro_Prem2.iso");
long endTime = System.currentTimeMillis();
System.out.println("直接读取耗时:" + (endTime - startTime) + "ms");
}
public static void readWrite(String from, String to) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
while (true) {
int data = in.read();
if (data == -1) {
break;
}
out.write(data);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
/************************************************************************
* *** 使用缓存区读写文件
*
* @param from
* @param to
* @throws IOException
*/
public static void readWriteWithBuffer(String from, String to)
throws IOException {
InputStream inBuffer = null;
OutputStream outBuffer = null;
try {
inBuffer = new BufferedInputStream(new FileInputStream(from));
outBuffer = new BufferedOutputStream(new FileOutputStream(to));
while (true) {
int data = inBuffer.read();
if (data == -1) {
break;
}
outBuffer.write(data);
}
} finally {
if (inBuffer != null) {
inBuffer.close();
}
if (outBuffer != null) {
outBuffer.close();
}
}
}
}
3)同步文件访问方式
就是单线程直接写- -,性能不咋地,只有一些对数据安全性要求比较高的地方才会使用。
4)异步文件访问方式
用多线程去写。这种访问文件的方式可以明显的提高应用程序的效率,但不会减少访问文件的效率。
5)内存映射的方式
这个就比较屌了。指的是操作系统将内存中的某一块区域与磁盘中的文件关联起来,当要访问内存中的一段数据时,转换为访问文件的某一段数据。这种方式的目的是减少数据从内核空间缓存到用户空间缓存的数据复制操作,因为两个空间的数据是共享的。
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 测试利用多线程进行文件的写操作
*/
public class Test {
public static void main(String[] args) throws Exception {
// 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件
RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");
raf.setLength(1024*1024); // 预分配 1M 的文件空间
raf.close();
// 所要写入的文件内容
String s1 = "第一个字符串";
String s2 = "第二个字符串";
String s3 = "第三个字符串";
String s4 = "第四个字符串";
String s5 = "第五个字符串";
// 利用多线程同时写入一个文件
new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据
new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据
new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据
new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据
new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据
}
// 利用线程在文件的指定位置写入指定数据
static class FileWriteThread extends Thread{
private int skip;
private byte[] content;
public FileWriteThread(int skip,byte[] content){
this.skip = skip;
this.content = content;
}
public void run(){
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("D://abc.txt", "rw");
raf.seek(skip);
raf.write(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
raf.close();
} catch (Exception e) {
}
}
}
}
}
浙公网安备 33010602011771号