输入输出

来源:互联网 发布:内存条js 编辑:程序博客网 时间:2024/05/16 03:16

java的IO:包括输入输出两种IO,每种输入输出流又可以分为字节流和字符流。其中字节流以字节为单位,字符流以字符为单位处理输入输出。javaIO流又分为底层节点流和上层处理流,节点流用于和底层物理存储节点直接关联,程序可以把不同物理节点流包装成统一的处理流。使用java的序列化机制可以把内存的java对象转换成二进制字节流,这样就可以把java对象存储到磁盘里或者在网上传输对象。

一.File类

不管是文件还是目录都是使用File来操作,File类能新建,删除,重命名文件和目录,不能访问文件本身内容,如果需要访问文件本身内容需要使用输入输出流。

1).访问文件目录

1.File可以使用文件字符串创建File实例。File有访问文件名的相关方法,文件检测的相关方法,获取文件常规信息,文件操作相关方法,目录操作相关方法。

2).文件过滤器

1.File的list()方法可以接收一个FilenameFilter参数,通过参数可以列出符合条件的文件。FilenameFilter接口包含一个accept方法,该方法将对指定的File所有子目录或者文件进行迭代,如果该方法返回true,list方法会该子目录或者文件。

file.list(Lambda表达式)

二.理解java的IO流

1).流的分类

1.输入流:只能读取数据,主要由InputStream和Reader作为基类,输出流:只能写数据,主要由OutputStream和Writer作为基类(划分输入输出是从程序运行所在的内存的角度来考虑的)

2.字节流和字符流:字节流主要由Inputstream和OutputStream作为基类,而字符流则主要由Reader和Writer作为基类

public class FileInputStreamTest {    public static void main(String[] args) throws IOException{        FileInputStream fis = new FileInputStream("C:\\Users\\asus\\eclipse-workspace\\abc\\src\\abc\\FileInputStreamTest.java");        byte[] buff = new byte[1024];        int hasRead = 0;        while((hasRead = fis.read(buff)) > 0) {            System.out.println(new String (buff, 0 , hasRead));        }        fis.close();    }}
public class FileOutputStreamTest {    public static void main(String[] args) {        //自动关闭资源的try语句        try (FileInputStream fis = new FileInputStream("C:\\Users\\asus\\eclipse-workspace\\abc\\src\\abc\\"                + "FileInputStreamTest.java");        FileOutputStream fos = new FileOutputStream("newFile.txt"))        {            byte[] bbuf = new byte[32];            int hasRead = 0;            while((hasRead = fis.read(bbuf)) > 0) {                fos.write(bbuf,0,hasRead);            }        }catch (IOException e) {            e.printStackTrace();        }    }}

3.节点流和处理流:可以向一个特定的IO设备读写数据的流成为节点流,节点流也被称为低级流,对一个已存在的流进行连接或者封装,通过封装后的流来实现数据读写功能,处理流也被称为高级流。处理流的功能:主要以增加缓冲的方式来提高输入输出的效率,处理流提供一系列便捷的方法输入输出大批量的内容。

(程序里打开的文件IO资源不属于内存,垃圾回收机制无法回收该资源,所以应该显式关闭文件IO资源,可以使用自动关闭的try)

注意:使用java的IO流执行输出时不要忘记关闭输出流,关闭输出流可以保证流的物理资源被回收之外,可能还可以将输出流缓冲区的数据flush到物理节点。

三.输入输出流体系

1).使用处理流的典型思路是使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的IO设备文件交互。关闭输入输出资源时只要关闭最上层的处理流即可,系统会自动关闭被该处理流包装的节点流。

2).输入输出流体系

3).转换流

1.输入输出流体系提供了两个转换流,InputStreamReader,OutputstreamWriter将字节输入流转换字符流.

2.可以将普通的Readr再次包装成BufferedReader,利用Buffered的readLine()方法可以一致读取一行。

4).推回输入流

PushbackInputStream和PushbackReader

五.重定向标准输入输出

java的标准输入输出分别通过System.in和System.out来代表,在默认的情况下代表键盘和屏幕。

六.java虚拟机读写其他进程的数据。

Runtime对象的exec()可以运行平台的其他程序,该方法产生一个Process对象,Process对象代表由java程序启动的子进程。(子进程读取程序中的数据应该是输出流)

七.RandomAccessFile

由于RandomAccessFile可以自由访问文件的任意位置,允许自由定位文件的记录指针,因此可以向已存在的文件追加内容。RandomAccessFile只能读写文件。

注意:RandomAccessFile不能向指定文件插入内容,会覆盖 文件中原有的内容,如果需要向指定位置插入内容,程序先把插入点后面的内容读入缓存区,等把需要插入的数据写入文件后,再将缓冲区的内容追加到文件后面。

八.对象的序列化

对象序列化的目标是将对象保存到磁盘中或者允许在网络直接传输对象,对象序列化机制允许把内存中的对象转化为二进制流,,也可以将这种二进制流恢复为原来的对象

1).序列化的含义和意义

对象的序列化(Serialize)指将java对象写入IO流,对应的是对象的反序列化(Deserialize)

让某个对象支持序列化机制就必须实现Serializable接口或者Externalizable接口。Serializable接口是一个标记接口实现该接口无须实现任何方法,只是表明该类的实例是可序列化的。

反序列化读取的仅仅是java对象的数据而不是java类,因此采用反序列化恢复java对象时必须提供java对象所属类的class文件。反序列化无需通过构造器来初始化对象

如果使用序列化机制向文件写入多个java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。当一个序列化的类有多个父类时,要么有无参数的构造器,要么也是可序列化的否则抛出异常

public class WriteObject {    public static void main(String[] args) {        try(ObjectOutputStream oos = new ObjectOutputStream(                new FileOutputStream("object.txt"))                )        {            Person per = new Person("St", 45);            oos.writeObject(per);        }        catch(IOException e) {            e.printStackTrace();        }        try(ObjectInputStream ois = new ObjectInputStream(                new FileInputStream("object.txt"))){            Person p = (Person)ois.readObject();        System.out.println(p.getAge()+p.getName());        }catch (Exception e) {            e.printStackTrace();        }    }    static class Person implements java.io.Serializable{        /**         *          */        private static final long serialVersionUID = 1L;        private String name;        private int age;        public Person(String name, int age) {            System.out.println("有参数的构造器");            this.name = name;            this.age = age;        }        public void setName(String name) {            this.name = name;        }        public String getName() {            return this.name;        }        public void setAge(int age) {            this.age  = age;        }        public int getAge() {            return this.age ;        }    }}

2).对象引用的可序列化

 如果某个类的成员变量的类型是一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型成员变量的类也是不可序列化的。

java采用一种特殊的序列化算法保证对象只被序列化一次

1.所有保存到磁盘的对象都有一个序列化编号

2.当程序试图序列化一个对象时先检查该对象是否已经被序列化一次。如果已经序列化过,程序将输出序列化编号

3).自定义序列化

1.通过在实例变量前使用transient关键字修饰,可以指定java序列化时无需理会该实例变量。transient只能修饰实例变量。

2.其他种实现自定义序列化对象的机制。

九.NIO

新IO采用映射文件的方式处理输入输出。新IO将文件或文件的一段区域映射到内存中,这样就可以访问内存一样访问文件了。

Channel(通道)和Buffer(缓冲)是新IO中的两个核心对象,Channel是对传统的输入输出系统的模拟,在新IO系统中所有数据都需要通过通道传输,Channel与IntputStream等的最大区别是map方法,通过map方法将一块数据映射到内存中。

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

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

还有文件锁,path,paths,Files,使用FileVistor遍历文件和目录,使用WatchService监听文件变化,访问文件属性等内容就不说了。

原创粉丝点击