IO流

  • 输入流指向源,程序通过read()方法从输入流中读取源中的数据
  • 输出流指向数据要去的目的地,程序通过write()方法向输出流写入数据,传送到目的地

1. File类

File对象用来获取文件的信息,不涉及读写操作。

  • 创建File对象的构造方法:
File(String filename)
File(String directoryPath, String filename)
File(File f,String filename)

其中,filename:文件名字;directoryPath:文件的路径;f:指定成一个目录的文件

1.1 文件的属性

自行查阅相关方法(书本p329)

1.2 目录

  1. 创建目录
    调用方法public boolean mkdir()创建一个目录,创建成功返回true,否则返回false(如果该目录已存在就返回false)
  2. 列出目录中的文件
    (1)public String [ ] list():以字符串形式返回目录下所有文件。
    (2)public File [ ] listFiles():以File对象形式返回目录下所有文件。
    有时需要列出指定类型的文件,如.java、.txt等扩展名的文件,用以下方法:
    (3)public String [ ] list(FilenameFilter obj):以字符串形式返回目录下指定类型的所有文件。
    (4)public File [ ] listFiles(FilenameFilter obj):以File对象形式返回目录下指定类型的所有文件。
    上述FilenameFilter是个接口,用一个方法:
    public boolean accept(File dir,String name)

1.3 文件的创建与删除

1.4 运行可执行文件

用Runtime类。首先声明一个对象:
Runtime ec;
然后用该类的getRuntime()静态方法创建这个对象
ec=Runtime.getRuntime();
ec可以调用exec(String command)方法打开本地机上的可执行文件或执行一个操作。

2. 文件字节流

2.1 文件字节输入流

  1. 创建文件字节输入流
    FileInputSteam类创建的对象被称为文件字节输入流,该类是InputStream的子类。
    创建对象的构造方法:
FileInputStream(String name)
FileInputStream(File file)

name和file指定的文件成为输入流的源
注意:程序必须在try......catch语句中的try块部分创建输入流对象catch块部分检测并处理异常

  1. 以字节为单位读文件
     输入流调用read( )方法顺序地读取源中的单个字节数据,返回字节值,如果到源的末尾,返回-1.
     read方法还有其他形式,可以把多个字节读到一个字节数组中:
int read(byte b[ ])  //从文件读取b.length个字节,存放在数组b中
int read(byte b[ ],int off, int len)   //从文件读取len个字节,存放在数组b中,首字节的位置是off

这两个方法都返回实际读取的字节个数,如果到达文件的末尾,返回-1.

2.2 文件字节输出流

  1. 创建文件字节输出流
    FileOutputSteam类创建的对象被称为文件字节输入流,该类是OutputStream的子类。
    创建对象的构造方法:
FileOutputStream(String name)
FileOutputStream(File file)

参数name和file指定的文件称为输出流的目的地
注意:如果输出流指向的文件不存在,Java会创建该文件;如果指向的文件是已存在的文件,输出流将刷新该文件(使得文件的长度为0)
下列构造方法在创建输出流时,可以选择是否刷新文件

FileOutputStream(String name ,boolean append)
FileOutputStream(File file, boolean append)

如果append 值取true,不刷新文件(若文件已存在),输出流的write方法从文件的末尾开始写入数据;否则刷新文件(若文件已存在)

  1. 以字节为单位写文件
    继承了OutputStream的write(byte b[ ])方法,该方法特点是以字节为单位向文件写入数据。
    public void write(byte b[ ]):写b.length个字节到文件
    public void write(byte b[ ], int off, int len):从数组b的off处开始写len个字节到文件中

2.3 关闭流

通过调用close()方法

3. 文件字符流

与字节流相对应的是的FileReader、FileWriter字符流,分别是Reader和Writer的子类,其构造方法分别如下:

FileReader(String filename)
FileReader(File filename)
FileWriter(String filename)
FileWriter(File filename)

字符流以字符为基本单位处理数据,二者常用方法如下:

  • int read():从源中读取一个字符,返回一个整数,未读出字符返回-1
  • int read(char b [ ] ):从源中读取b.length个字符数组b中,返回实际读取的字符数目。若到达源的末尾,返回-1
  • int read(char b [ ], int off, int len):从源中读取len个字符放到数组b中,off存放的首位置返回实际读取的字符数目。若到达源的末尾,返回-1
  • void write():向文件写入一个字符
  • void write(char b [ ] ):向文件写入一个字符数组
  • void write(char b [ ], int off, int len):从数组b的off处开始取出len个字符写到文件

4. 缓冲流

BufferedReader类和BufferedWriter类创建的对象称为缓冲输入流、缓冲输出流。二者的源和目的地必须是字符输入流和字符输出流。因此具有更强的读写能力

4.1构造方法分别如下:

BufferedReader(Reader in)
BufferedWriter(Writer out)

BufferedReader流可以读取文本,方法是readLine()。

4.2 创建对象

  通过向BufferedReader传递一个Reader子类的对象(例如FileReader的实例)来创建一个BufferedReader对象,例如:

FileReader in1=new FileReader("1.txt");
BufferedReader in2=BufferedReader(in1);

然后in2流调用readLine()方法读取1.txt,例如:

String str=in2.readLine():

BufferedWriter流和FileWriter流的连接与上面类似。

另外,BufferedWriter流有自己独特的向文件写入一个回行符的方法:
newLine()
可以把缓冲流称为上层流,把它们指向的字符流称为底层流。底层字符输入流先将数据读入缓存,缓冲输入流在从缓存读取数据;缓冲输出流将数据写入缓存,底层字符输出流再将缓存中的数据写入目的地。

5. 随机流

功能更完善的RandomAccessFile类。不是InputStream和OutputStream的子类。

5.1 构造方法:

  • RandomAccessFile(Srting name, String mode):参数name是文件名字,给出流的源,也是流的目的地。参数mode取r(只读)或者rw(可读/写),决定流对文件的访问权利。
  • RandomAccessFile(File file, String mode):参数file是File对象,给出流的源,也是流的目的地。参数mode取r(只读)或者rw(可读/写),决定流对文件的访问权利。

5.2 其他方法:

  • seek(long a):用来定位流的读/写位置,参数a确定读写为止距离文件开头的字节个数
  • getFilePointer():获取流的当前读写位置

RandomAccessFile流的readLine()方法在读取含有非ASCII字符的文件(例如汉字)会出现乱码,需要把读取的字符串用ISO8859-1重新编码存放到byte数组中,然后用当前计算机的默认编码将该数组转化为字符串:
(1)读取字符串:String str=in.readLine();
(2)用ISO 8859—1重新编码:byte b[ ]=str.getBytes("ISO 8859-1");
(3)使用当前计算机的默认编码将字节数组转化为字符串:String content=new String(b);
注:如果计算机的默认编码是GB2312,那么String content=new String(b);等同于String content =new String(b,"GB2312");

6. 数组流

6.1 字节数组流

6.1.1 字节数组输入流

构造方法:

  • ByteArrayInputStream(byte[ ] buf):该方法构造的字节数组流的源是参数buf指定的数组的全部字节单元
  • ByteArrayInputStream(byte[ ] buf, int off, int len):该方法构造的字节数组流的源是参数buf指定的数组从off处按顺序取len个字节单元

其他方法:

  • public int read():调用该方法顺序地从源中读出一个字节,返回读出的字节值
  • public int read(byte [ ] b,int off, int len):调用该方法读出len个字节,存放到数组b中,从数组b的off处开始存放,返回读出的字节个数,若未读出则返回-1
6.1.2字节数组输出流

构造方法:

  • ByteArrayOutputStream():该方法构造的流指向一个默认大小为32字节的缓冲区,容量会随情况自动增加
  • ByteArrayOutputStream(int size):缓冲区大小由参数size决定,容量会随情况自动增加

其他方法:
public void write(int b):调用该方法顺序地向缓冲区写入一字节
public void write(byte[ ] b,int off, int len):将数组b中从off处len个字节写入缓冲区

6.2字符数组流

字节数组流相对应,CharArrayReader类和CharArrayWriter类,分别使用字符数组作为流的源和目的地。

7. 数据流

DataInputStream和DataOutputStream类创建的对象叫数据输入流和数据输出流。这两个流读取数值时,不必关心数值应当是多少字节。
构造方法:

  • DataInputStream( InputStream in):创建的数据输入流指向参数in指定的底层输入流
  • DataOutputStream( OutputStream out):创建的数据输出流指向一个参数out指定的底层输出流

相关方法自行查阅

8. 对象流

ObjectInputStream类和ObjectOutputStream类分别是InputStream类和OutputStream类的子类
对象输出流用writeObject(Object obj)方法将对象obj写入文件;对象输入流使用readObject()方法读取对象
构造方法:

  • ObjectInputStream(InputStream in)
  • ObjectOutputStream(OutputStream out)

ObjectOutputStream指向一个输出流对象,当准备将对象写入文件时,先用OutputStream的子类创建一个输出流,例如:

FileOutputStream fileOut=new FileOutputStream("tom.txt");
ObjectOutputStream objOut=newObjectOutputStream(fileOut);

ObjectInputStream指向一个输入流对象,准备从文件中读取数据时,先用InputStream的子类创建一个输入流,例如:

FileInputStream fileIn=new FileInputStream("tom.txt");
ObjectInputStream objIn=new ObjectInputStream(fileIn);

使用对象流读写对象时候,要保证对象时序列化的。Java提供的绝大多数对象都是序列化的。

9. 序列化与对象克隆

一个类如果实现了Serializable接口,该类创建的对象就是序列化对象

使用对象流获取一个序列化对象的克隆

当把一个序列化对象(对象A)写入对象输出流时,JVM会实现Serializable接口中的方法,将对象的序列化信息写入目的地。当ObjectInputStream的流从文件读取对象时,会从文件中读取对象的序列化信息,并根据对象的序列化信息创建一个对象B,B就是A的克隆,例如

class Example implements Serializable{  //实现Serializable接口,使Example类序列化
类体
}
public class Main{
  public static void main(String[] args) {
    Example exp1=new Example;
    File file=new Fiel("EXP.txt");
    try{
            FileOutputStream fileOut=new FileOutputStream(file);
            ObjectOutputStream objectOut=new ObjectOutputStream(fileOut);
            objectOut.writeObject(exp1);   // 将对象序列化信息写入源中
            objectOut.close();
            FileInputStream fileIn=new FileInputStream(file);
            ObjectInputStream objectIn=new ObjectInputStream(fileIn);
            Example exp2=(Example)objectIn.readObject();    // 将源中的序列化信息读出,并创建对象exp2,exp2即exp1的克隆
            objectIn.close();
        }
        catch (IOException | ClassNotFoundException e){
            System.out.println(e);
        }
    }
}

上述代码中Example exp2=(Example)objectIn.readObject();即创建克隆对象的语句,注意格式

10. 文件锁

FileLock类和FileChannel类。
例如用随机流读写文件时使用文件锁:
(1)先试用RandomAccessFile流建立指向稳健的留的对象,读写属性必须是ew
RandomAccessFile input=new RandomAccessFile("Example.java","rw");
(2)input流调用FileChannel类的方法getChannel()获得一个连接到底层文件的对象(信道):
FileChannel channel=input.getChannel();
(3)信道调用FileLock类的方法tryLock()或lock()获得一个FileLock(文件锁)对象,这一过程称为对文件加锁
FileLock lock= channel.tryLock();
文件锁对象产生后,文件不能再被操作或进行加锁。除非让FileLock对象调用release()释放文件锁:
lock.release();

11. 使用Scanner类解析文件

1. 使用默认分隔标记解析文件

创建Scanner对象,指向要解析的文件,例如:

File file=new File("hello.java");
Scanner sc=new Scanner(file);

sc将空白作为分隔标记,调用next()方法返回file中的单词。如果file中最后一个单词已经被返回,sc调用hasNext()方法将返回false,否则返回true
sc可以调用nextInt()、nextDouble()等方法将数字型单词转化为int、double等数据返回。注意:如果单词不是数字型单词,调用nextInt()等方法将发生InputMismatchException异常,在处理异常时用next()方法返回非数字型单词。

2.使用正则表达式作为分隔标记解析文件

创建Scanner对象,指向要解析的文件,并使用useDelimiter方法指定正则表达式作为分隔标记,例如:

File file=new File("hello.java");
Scanner sc=new Scanner(file);
sc.useDelimiter(正则表达式);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容