流的学习2
流的概念
java中有输出流和输入流的概念,其实两者都是给数据传输提供了一个管道,输入流的两端分别是程序和数据,输入流指向的数据集我们称为源,数据方向是源通过输入流这个管道流向我们的用户程序。而输出流两端是程序和目的地,数据方向是从用户程序通过管道流向目的地。源和目的地可以是任何形式的数据容器,例如文件、内存数据、网络数据、键盘、磁盘、显示器等。
流中还有一些流是对输入流和输出流管道中的数据进行加工处理的流,处理流。
File对象
流的很多读写都跟文件有关。使用File创建文件对象,可以获取文件的许多信息,文件的目录,绝对路径,读写权限等。当需要执行一个可执行的文件时,可以使用java.lang包中的Runtime类,通过Runtime类的静态方法getRuntime创建对象,对象调用exec方法执行开执行文件,该方法接收文件的路径为参数。
InputStream和OutputStream
这两个流为字节的输入输出流,都提供了最基本的读写的方法read和write,read和write。其它的流都是建立在这两个流的基础之上的。
FileInputStream和FileOutputStream(字节)
文件输入输出流,可以根据文件名或File对象创建对应的输入输出流。read()方法按顺序读取文件的内容,读到末尾返回-1,read(byte[] b)读取数据到字节数组中 ,read(byte[] b,off,len)读取字节到数组b中,off指定存放的位置,len知道存放的长度。相应的write也是一样,只不过文件输出流构造方法具有一个属性append,设置为true代表不刷新文件。
FileReader和FileWriter(字符)
为什么需要字符流?在java中char类型是两个字节的,如果用字节流读取,那相当于读取字符的一半,肯定会出现一些错误,而字符流就是根据字符来读取的而不是字节。
其使用与文件字节流一致,只不过字节数组换为字符数组而已,也可以字节将字符串写入。
BufferedReader和BufferedWriter(处理流)
缓冲字符流,不管是读取数据还是写入数据,都是从缓冲区读取和写入数据,而对于输入流的缓冲区数据,是缓冲区向原始流读取的。具有了缓冲区,那么就相应的会有flush方法用来手动将缓冲区数据写入硬件设备,不手动调用的话,需要等缓冲区的数据满了才会相应将数据写入硬件设备。缓冲输入流具有读取一行数据的方法readLine(),缓冲输出流调用newLine()方法写入一个换行。
ByteArrayInputStream和ByteArrayOutputStream
输入输出流的源和目的地也可以是内存,创建一个输入流时,可以传入一个字节数组或带上参数off和len,创建输出流时可以传入参数size,指定内存目的地的大小。通过调用toByteArray方法可以返回一个包含目的地数据的字节数组。相应的就会有字符数组输入输出流,只不过字符流可能会输出IOException。调用toCharArray返回一个包含目的地字符的字符数组。还有相应的字符串流,以字符串作为流的源,同样调用toString方法可已返回一个包含目的地字符串内容的字符串。
DataInputStream和DataOutputStream(处理流)
数据流可以读取和写入java的基本数据类型,而不用去管数据的大小问题。相应的有readInt,writeInt等方法。
ObjectInputStream和ObjectOutputStream(处理流)
对象输入输出流,可以将对象进行读取和写入,相应的方法是readObject和writeObject。在写入对象时要求对象时可序列化的即实现了Serializable接口的对象。使用这个流可以很方便的对对象进行克隆。
RandomAccessFile
随机读写流专门用来处理文件的读写问题,不是inputStream和Reader的子类。构造方法文件流差不多,只不过后面多加一个参数mode,指定对该文件的权限。
seek(long a) 用来移动读写的位置。
getFilePointer()获取文件的指针的位置。
readLine读取文件一行内容。
文件锁FileLock
在使用随机读写流时,对于多个线程操作一个文件肯定是不安全的,可以采用线程同步的问题解决,但是太过复杂,所以可以通过filelock对象的getChannel方法获取一个连接到底层FileChannel对象,在通过这个对象调用tryLock或lock方法获取锁,获取锁后任何线程都不能对这个文件进行操作,只有通过该对象的release方法释放锁后才能对文件进行操作。在fileinputstream和fileoutputstream对文件进行读写时也可以获取锁。
Scanner来解析文件
在创建一个scanner对象时传入File对象为参数,默认的分割符是空格。可以调用scanner对象的useDelimiter方法指定分割符,可以是字符也可以是正则表达式。