您的位置:首页 > 编程语言 > Java开发

java 输入/输出

2016-05-07 21:28 330 查看

1. 简介

java的IO流使用了一种装饰器模式,它将IO流分为底层节点流和上层处理流,其中节点流用于和底层的物理存储节点直接关联,不同的物理存储节点获取节点流的方式可能存在一些差异,但程序可以把不同的物理节点流包装成统一的处理流,从而允许使用统一的方式来读取不同的物理存储节点的资源。

2. File类

File类是java.io包下代表与平台无关的文件和目录。

1)访问文件和目录

public static void main(String[] args) throws IOException{

File file = new File("D:/Code/Java/LeetCode/src/com/blue");
/*如果是路径,返回最后一级子目录名*/
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getParent());

File tmpFile = File.createTempFile("abc", ".txt", file);
tmpFile.deleteOnExit();//退出后删除

File newFile = new File(System.currentTimeMillis() + "");
System.out.println("文件是否存在:" + newFile.exists());

newFile.createNewFile();

String[] fileList = file.list();
for(String fileName : fileList) {
System.out.println(fileName);
}

File[] roots = File.listRoots();
for(File root : roots) {
System.out.println(root);
}
}

/**
blue
D:\Code\Java\LeetCode\src\com\blue
D:\Code\Java\LeetCode\src\com\blue
D:\Code\Java\LeetCode\src\com
文件是否存在:false
abc3889250970410031061.txt
sky
sourcecode
sql
C:\
D:\
E:\
F:\
H:\
*/


2) 文件过滤器

FileNameFilter接口里包含一个accpet(File dir, String name)方法,如果返回true,表示会列出

File file = new File("D:/Code/Java/LeetCode/src/com/blue/sky");
String[] nameList = file.list((dir, name) -> {
return name.endsWith(".java") || new File(name).isDirectory();
});

System.out.println("--------------");
for(String name : nameList) {
System.out.println(name);
}


3. 输入/输出流

java把所有设备里的有序数据抽象成流模型

1)流的概念

InputSream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流

OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流

2)输入流

FileInputStream fis = new FileInputStream("D:\\Code\\Java\\LeetCode\\src\\com\\com\\blue\\classloader\\Test6.java");
byte[] buf = new byte[1024];
int hasRead = 0;
while((hasRead = fis.read(buf)) > 0) {
System.out.println(new String(buf, 0, hasRead));
}
fis.close();


3) 输出流

try(FileInputStream fis = new FileInputStream("D:\\Code\\Java\\LeetCode\\src\\com\\com\\blue\\classloader\\Test6.java");
FileOutputStream fos = new FileOutputStream("./1.txt")) {

byte[] buf = new byte[1024];
int hasRead = 0;
while((hasRead = fis.read(buf)) > 0) {
fos.write(buf, 0, hasRead);
}
}catch (IOException e) {
e.printStackTrace();
}


4)输入/输出流体系



4. 对象的序列化

对象的序列化:指将一个java对象写入到IO流中

对象的反序列化:指从IO流中恢复java对象

//实现Serializable
1. 当反序列化读取java对象时,并没有看到程序调用构造器,这表明反序列化机制无须通过构造器来初始化java对象
2. 当一个可序列化类有多个父类(直接父类和间接父类),这些父类要么有无参数的构造器,要么也是可序列化的。如果父类是不可序列化的,只有无参数的构造器,则该父类中定义的成员变量值不会序列化到二进制流中
3. 如果多次序列化同一个对象,只有第一序列化时才会把java对象转换成字节序列输出,所以当程序序列化一个可变对象时,一定要注意。
4. 自定义序列化:在实例变量前加transient,java序列化机制就不会序列化该实例变量
5. 另一种序列化机制:实现Externalizable接口 需要重写writeExternal 和readExternal方法
6. 对象的类名、实例变量(包括基本类型、对其他对象的引用和数组)都会被序列化;方法、类变量、transient实例变量都不会被序列化


5. NIO

新IO采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射到内存中。

Channel和Buffer是新IO中的两个核心对象。在新IO系统中所有的数据都需要通过通道传输。

Buffer可以被理解成一个容器,它的本质是一个数组。发送到Channel中的所有对象都必须首先放到Buffer中,而从Chanel中读取的数据也必须先放到Buffer中。

1)Buffer使用

从内部结构看,Buffer就像一个数组,它可以保存多个类型相同的数据。常用的Buffer有ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer。

通过allocate获取对应的XXXBuffer对象

Buffer有三个重要的概念:容量(capacity),界限(limit),位置(position)

缓冲区的容量表示该Buffer的最大数据容量,创建后不能改变。

limit表示第一不可以被读或写的缓冲区位置索引。也就是说,limit后的数据既不可以被读,也不可以被写

position用于指明下一个可以被读出或者写入的缓存区位置索引

当数据装入完毕后,调用Buffer的flip方法,该方法将limit位置为position所在位置,并将position设为0

当调用clear方法时,它仅仅将position置0,将limit置为capacity,数据不会清空

2)使用Channel

ServerSocketChanel,SocketChannel是用于支持TCP网络通信的Channel

DatagramChannel是用于支持UDP网络通信的Channel

Pipe.SinkChannel 和Pipe.SourceChannel是用于支持线程间通信的Channel

通过相应流的getChannel方法来获取Channel

Channel常用的三类方法:map, read和write,其中map方法用于将Channel对应的部分或全部数据映射成ByteBuffer, read和write方法用于从Buffer中读取或者向Buffer写入数据

Java7的NIO2

提供了全面的文件和文件系统的访问支持(Paths, Files)

基于异步Channel的IO
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: