一、引言

IO(输入/输出),输入是指允许程序读取外部数据(包括来自磁盘、光盘等存储设备的数据)、用户输入数据。输出是指允许程序记录运行状态,将程序数据输出到磁盘、光盘等存储设备中。

IO的主要内容包括输入、输出两种IO流,这两种流中又分为字节流和字符流,字节流是以字节为单位来处理输入、输出流,而字符流是以字符为单位来处理输入、输出流。


二、File 类

File 类是用来操作文件和目录的,File能创建、删除、重命名文件和目录,File不能访问文件内容本身,File 类可以通过文件路径字符串来创建对象,创建完对象之后有很多方法来操作文件和目录:

2.1 构造方法

  • File(String pathname):根据一个路径得到File对象
  • File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
  • File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对

2.2 创建方法

//在当前路径来创建一个File对象File file = new File("1.txt");//创建文件System.out.println(file.createNewFile());File file2 = new File("temp"); //创建对象对应的目录System.out.println(file2.mkdir());

2.3 重命名和删除功能

//把文件重命名为指定的文件路径file2.renameTo(new File("temp2"));//删除文件或者文件夹file2.delete();

注:重命名中如果路径名相同,就是改名,如果路径名不同,就是改名并剪切。删除不走回收站,要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹。

2.4 判断功能

//判断文件或目录是否存在System.out.println(file.exists());//判断是否是文件System.out.println(file.isFile());//判断是否是目录System.out.println(file.isDirectory());//是否为绝对路径System.out.println(file.isAbsolute());//文件或目录是否可读System.out.println(file.canRead());//文件或目录是否可写System.out.println(file.canWrite());

2.5 获取功能

//返回文件内容长度System.out.println(file.length());//获取文件或目录名System.out.println(file.getName());//获取文件或目录相对路径System.out.println(file.getPath());//获取文件或目录绝对路径System.out.println(file.getAbsolutePath());//获取上一级路径System.out.println(file.getAbsoluteFile().getParent());//返回当前目录的子目录或文件的名称String[] list = file1.list();for (String fileName : list) { System.out.println(fileName);}//返回当前目录的子目录或文件,返回的是File数组File[] files = file1.listFiles();//返回系统的所有根路径File[] listRoots = File.listRoots();for (File root : listRoots) { System.out.println(root);}

回到顶部

三、IO 流

实现输入/输出的基础是IO流,Java把不同的源之间的数据交互抽象表达为流,通过流的方式允许Java程序使用相同的方式来访问不同的数据源。用于操作流的类都在IO包中。

3.1 流的分类

按照不同的分类方式,流也可以分为不同类型

  1. 输入流和输出流:根据流向来分,可以分为输入流与输出流
  • 输入流:从中读取数据,而不能向其写入数据
  • 输出流:向其写入数据,而不能读取数据
  1. 字节流和字符流:这两种流用法几乎完全一样,区别在于所操作的数据单元不一样,字节流操作的数据单元是8位的字节,而字符流是16位的字符。

3.2 InputStream与Reader

InputStream和Reader是所有输入流的抽象基类,这是输入流的模板,InputStream中有三个方法

  • int read() :从输入流读取单个字节,返回所读取的字节数据。
  • int read(byte b[]):从输入流中最多读取b.length个字节的数据,并将其存储在数组b中。
  • int read(byte b[], int off, int len):从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入的位置是从off中开始。

Reader中也有三个方法

  • int read() :从输入流读取单个字符,返回所读取的字符数据。
  • int read(char cbuf[]):从输入流中最多读取cbuf.length个字符的数据,并将其存储在数组cbuf中。
  • int read(char cbuf[], int off, int len):从输入流中最多读取len个字符的数据,并将其存储在数组cbuf中,放入的位置是从off中开始。
  • 两个类的方法基本相同,用法相同,只是操作单位不一样
InputStream inputStream = new FileInputStream("StreamTest.java");byte[] bytes = new byte[1024];int hasRead = 0;while ((hasRead = inputStream.read(bytes)) > 0) {System.out.println(new String(bytes, 0, hasRead));}inputStream.close();

3.3 OutputStream与Writer

OutputStream与Writer是所有输出流的抽象基类,是输出流模板,OutputStream有三个方法:

  • void write(int b):指定字节输出到流中
  • void write(byte b[]):将指定字节数组输出到流中
  • void write(byte b[], int off, int len):将指定字节数组从off位置到len长度输出到流中

Writer中也有三个方法:

  • void write(int b):指定字符输出到流中
  • void write(char buf[]):将指定字符数组输出到流中
  • void write(char cubf[], int off, int len):将指定字符数组从off位置到len长度输出到流中

由于Writer是以字符为单位进行操作,那可以使用String 来代替,于是有另外的方法

  • void write(String str):将str字符串输出到流中
  • void write(String str, int off, int len):将str从off位置开始长度为len输出到流中
FileWriter fileWriter = new FileWriter("test.txt");fileWriter.write("日照香炉生紫烟");fileWriter.write("遥看瀑布挂前川");fileWriter.write("飞流直下三千尺");fileWriter.write("遥看瀑布挂前川");fileWriter.close();

注:操作流时一定要记得关闭流,因为打开的IO资源不属于内存资源,垃圾回收无法回收。

四、输入/输出流体系

Java的输入输出流提供了40多个类,要全部都记住很困难也没有必要,我们可以按照功能进行下分类,其实是非常有规律的




java 通过路径 获取MultipartFile 对象 java根据路径获取文件流_java读取src路径下的txt文件


一般如果输入/输出的内容是文本内容,应该考虑使用字符流,如果输入/输出内容是二进制内容,则应该考虑使用字节流。

4.1 转换流

体系中提供了两个转换流,实现将字节流转换成字符流,InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流,System.in代表标准输入,这个标准输入是字节输入流,但是键盘输入的都是文本内容,这个时候我们可以InputStreamReader转换成字符输入流,普通的Reader读取内容不方便,我们可以使用BufferedReader一次读取一行数据,如:

//先将System.in转换成Reader 对象InputStreamReader inputStreamReader = new InputStreamReader(System.in);//再将Reader包装成BufferedReaderBufferedReader bufferedReader = new BufferedReader(inputStreamReader);String line = null;while ((line = bufferedReader.readLine()) != null) { if (line.equals("exit")) { System.exit(1); } System.out.println("输入的内容是:" + line);}

BufferedReader具有缓冲功能,在没有读到换行符则阻塞,读到换行符再继续。

4.2 推回输入流

推回输入流PushbackInputStream和PushbackReader中都提供了如下方法:

  • void unread(int b) :将一个字节/字符推回到推回缓冲区,从而允许重复读取刚刚读取的内容。
  • void unread(byte[] b/char[] b, int off, int len) :将一个字节/字符数组里从off开始,长度为len字节/字符的内容推回到推回缓冲区,从而允许重复读取刚刚读取的内容。
  • void unread(byte[] b/char[]):将一个字节/字符数组内容推回到推回缓冲区,从而允许重复读取刚刚读取的内容。

这两个推回流都带有一个推回缓冲区,当调用unread()方法时,系统将会把指定的内容推回到该缓冲区,而当每次调用read方法时会优先从推回缓冲区读取,只有完全读取了推回缓冲区的内容后,但还没有read()所需的数组时才会从原输入流中读取。

//创建PushbackReader对象,指定推回缓冲区的长度为64PushbackReader pushbackReader = new PushbackReader(new FileReader("StreamTest.java"), 64);char[] buf = new char[32];//用以保存上次读取的字符串内容String lastContent = "";int hasRead = 0;//循环读取文件内容while ((hasRead = pushbackReader.read(buf)) > 0) { //将读取的内容转换成字符串 String content = new String(buf, 0, hasRead); int targetIndex = 0; if ((targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0) { //将本次内容和上次的内容一起推回缓冲区 pushbackReader.unread((lastContent + content).toCharArray()); //重新定义一个长度为targetIndex的char数组 if (targetIndex > 32) { buf = new char[targetIndex]; } //再次读取指定长度的内容 pushbackReader.read(buf, 0, targetIndex); //打印读取的内容 System.out.print(new String(buf, 0, targetIndex)); System.exit(0); } else { //打印上次读取的内容 System.out.print(lastContent); //将本次内容设为上次读取的内容 lastContent = content; }}

五、RandomAccessFile

RandomAccessFile是Java输入/输出流体系中最丰富的文件内容访问类,提供了众多的方法来访问文件内容,既可读取文件内容,也可以向文件输出数据,RandomAccessFile可以自由访问文件的任意位置。

RandomAccessFile包含一个记录指针,用以标识当前读和写的位置,当创建新对象时,指针位置在0处,而当读/写了N个字节后,指针就会向后移动N个字节,并且RandomAccessFile可以自动的移动该指针位置,当然我们也可以直接的获取指针的位置。

  • getFilePointer():获取文件记录指针的当前位置。
  • seek(long pos):将文件记录指针定位到pos位置。

RandomAccessFile有两个构造函数:

  • RandomAccessFile(File file, String mode):使用File文件,指定文件本身 RandomAccessFile(String name, String mode):使用文件名称,指定文件

其中还有一个参数mode(访问模式),访问模式有4个值:

  • r:以只读方式打开文件
  • rw:以读、写方式打开文件,如果文件不存在,则创建
  • rws:以读、写方式打开文件,并要求对文件的内容或者元数据的每个更新都同步写入到底层存储设备
  • rwd:以读、写方式打开文件,并要求对文件的内容的每个更新都同步写入到底层存储设备
RandomAccessFile raf = new RandomAccessFile("StreamTest.java