Java IO之File类
Java IO中所有的操作类跟接口都放在 java.io 包中,主要的类和接口有 File 、 InputStream 、 OutputStream 、 Reader 、 Writer 、 Serialzable 接口。
1、 File类
File类在整个 IO 中是独立的类,此类的主要功能是与平台无关的文件操作,如创建文件、删除文件等,在 File 类中提供了 public File(String pathname) ,在使用的时候需要指定一个具体的文件路径。
2、创建文件
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.IOException;
- public class CreateFileDemo {
- public static void main(String[] args) {
- File file = new File("D://demo.txt");
- try {
- file.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
上面程序只是创建文件,如果需要使用具体的内容输出,则需要依靠IO 操作流。
3、删除文件
删除文件则使用File 对象的 delete() 方法,如:
- package com.chenzehe.test.io;
- import java.io.File;
- public class DeleteFileDemo {
- public static void main(String[] args) {
- File file = new File("D://demo.txt");
- //删除前先判断下文件是否存在
- if (file.exists()) {
- file.delete();
- }
- }
- }
以上方法虽然完成了文件的操作,可是代码的兼容性有问题,在各个操作系统中文件的分隔符是不一样的,Windows 中的为 \ , Linux 中的为 / ,在 File 类中提供提供了下面几种常量:
路径分隔符:public static final String pathSeparator : ";"
分隔符:public static final separator : "/" 或者 "\"
正常的Java 常量是以大写命名的,这里使用小写是由于历史的原因,以后的程序都采用 File.separator 常量进行分隔。
4、判断路径是文件还是文件夹
在文件中可以使用以下方法判断是否是文件夹:public boolean isDirectory() ;
判断是否是文件:public boolean isFile() ;
5、列出目录中的内容
在File 类中提供了下面两个方法列出目录列表:
public String[] list()
public File[] listFiles()
6、创建目录
使用File 类的 mkdir() 方法,如:
- package com.chenzehe.test.io;
- import java.io.File;
- public class MkdirDemo {
- public static void main(String[] args) {
- File file = new File("D:" + File.separator + "demo.txt");
- file.mkdir();
- }
- }
RandomAccessFile 类的主要功能是完成文件的随机读取操作,可以随机读取文件中指定位置的数据。如果要实现随机读取,则数据在文件中保存的长度必须要一致,否则无法实现该功能。
RandomAccessFile实现了 DataOutput、 DataInput 、 Closeable 接口。
RandomAccessFile的构造方法:
public RandomAccessFile(File file,String mode) throes FileNotFoundException
该构造方法需要接收一个File 的实例,和一个操作模式:
只读模式:r
只写模式:w
读写模式:rw ,此模式如果文件不存在,则自动创建文件
1、 使用RandomAccessFile 进行写入操作
写入操作方法主要为从DataOutput 接口中实现的一系列 writeXxx() 方法,如:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.RandomAccessFile;
- public class RandomAccessFileDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- RandomAccessFile radomAccessFile = new RandomAccessFile(file, "rw");
- // 写入第一条数据
- String name = "first ";
- int age = 30;
- radomAccessFile.writeBytes(name);
- radomAccessFile.writeInt(age);
- // 写入第二条数据
- name = "second ";
- age = 31;
- radomAccessFile.writeBytes(name);
- radomAccessFile.writeInt(age);
- // 写入第三条数据
- name = "third ";
- age = 32;
- radomAccessFile.writeBytes(name);
- radomAccessFile.writeInt(age);
- radomAccessFile.close();//关闭文件
- }
- }
2、 RandomAccessFile读操作
RandomAccessFile读操作是从实现 DataInput 接口方法而来,有一系列的 readXxx() 方法,可以读取各种类型的数据,有下面两种方法控制读取位置:
回到读取点:public void seek(long pos) throws IOException
跳过n 个字节数: public void skipBytes(int n) throws IOException
如:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.RandomAccessFile;
- public class RandomAccessFileDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- RandomAccessFile radomAccessFile = new RandomAccessFile(file, "rw");
- byte[] b = new byte[10];
- String name = null;
- int age = 0;
- radomAccessFile.skipBytes(14);// 跳过第一个人的信息
- System.out.println("第二个人的信息为:");
- for (int i = 0; i < 10; i++) {
- b[i] = radomAccessFile.readByte();
- }
- age = radomAccessFile.readInt();// 读取数字
- System.out.println("姓名:" + new String(b));
- System.out.println("年龄:" + age);
- radomAccessFile.seek(0);// 回到第一个人信息开始处
- System.out.println("第一个人的信息为:");
- for (int i = 0; i < 10; i++) {
- b[i] = radomAccessFile.readByte();
- }
- age = radomAccessFile.readInt();// 读取数字
- System.out.println("姓名:" + new String(b));
- System.out.println("年龄:" + age);
- radomAccessFile.skipBytes(14);// 此时文件读取指针在第一个人信息末,跳过第二个人信息
- System.out.println("第三个人的信息为:");
- for (int i = 0; i < 10; i++) {
- b[i] = radomAccessFile.readByte();
- }
- age = radomAccessFile.readInt();// 读取数字
- System.out.println("姓名:" + new String(b));
- System.out.println("年龄:" + age);
- radomAccessFile.close();// 关闭文件
- }
- }
在整个 Java的 IO 中,流的操作分两种:
字节流:字节输出流OutputStream 和字节输入流 InputStream
字符流:一个字符等于两个字节,分为字符输出流Writer 和字符输入流 Reader
Java IO操作的基本步骤为:
一:使用File 找到一个文件
二:使用字节流或字符流的子类为OutputStream 、 IntputStream 、 Writer 、 Reader 进行实例化操作
三:进行读或写的操作
四:关闭资源:close() ;在所有流操作中,最终必须要关闭。
1、 字节输出流OutputStream
在java.io 包中 OutputStream 是字节输出流最大的父类:
public abstract class OutputStream extends Object implements Closeable,Flushable
此类是一个抽象类,依靠其子类进行文件操作,实现该接口的子类有:
ByteArrayOutputStream、 FileOutputStream 、 FilterOutputStream 、 ObjectOutputStream 、 OutputStream 、 PipedOutputStream 。
OutputStream提供了以下写入数据的方法:
写入全部字节数组:public void write(byte[] b) throws IOException
写入部分字节数组:public void write(byte[] b,int off,int len) throws IOException
写入一个数据:public abstract void write(int b) throws IOException
如果要完成文件的输出操作,则使用FileOutputStream 进行实例化工作:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- public class FileOutputStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- OutputStream outputStream = new FileOutputStream(file);
- String str = "hello world";
- byte[] b = str.getBytes();
- outputStream.write(b);
- outputStream.close();
- }
- }
- 或:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- public class FileOutputStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- OutputStream outputStream = new FileOutputStream(file);
- String str = "hello world";
- byte[] b = str.getBytes();
- for (int i = 0; i < b.length; i++) {
- outputStream.write(b[i]);
- }
- outputStream.close();
- }
- }
以上方式实现发现每次执行后都把上一次的内容替换掉,如果期望追加内容,则使用FileOutputStream 的下面构造方法:
public FileOutputStream(File file,boolean append) throws FileNotFoundException,如果将 append 设置为 true ,则表示追加内容。
2、 字节输入流InputStream
public abstract class InputStream extends Object implements Closeable
此类属于抽象类,需要使用其子类来实现文件的操作,实现它的子类有:
AudioInputStream、 ByteArrayInputStream 、 FileInputStream 、 FilterInputStream 、 InputStream 、 ObjectInputStream 、 PipedInputStream 、 SequenceInputStream 、 StringBufferInputStream ,如果是要实现对文件的操作,则使用 FileInputStream 类,该类有如下方法可读取数据:
将内容读取到字节数组之中:public int read(byte[] b) throws IOException
每次只读一个数据:public abstract int read() throws IOException
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.InputStream;
- import java.io.FileInputStream;
- public class FileInputStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- InputStream inputStream = new FileInputStream(file);
- byte[] b = new byte[1024];
- inputStream.read(b);
- System.out.println(new String(b));
- inputStream.close();
- }
- }
以上是一种比较常见的读取形式,上面给b 开辟了 1024 个字节码的空间,但是实际字符并达不到 1024 长度,所以在输出后面输出很多空格,以上的代码有一个缺点,会受到开辟空间的限制,如果想动态的开辟数组空间,则可以根据文件的大小来决定,采用 read() 方法一个个数据的读取。
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.InputStream;
- public class FileInputStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- InputStream inputStream = new FileInputStream(file);
- byte[] b = new byte[(int) file.length()];
- inputStream.read(b);
- System.out.println(new String(b));
- inputStream.close();
- }
- }
3、 字符输出流Writer
Writer类是在 IO 包中操作字符的最大父类,主要功能是完成字符流的输出, Writer 类的定义如下:
public abstract class Writer extends Object implements Appendable,Closeable,Flushable
与OutputStream 一样, Writer 类也发球抽象类,如果要进行文件操作,则使用 FileWriter,
写入操作为:public void writer(String str) throws IOException ,
可追加的写入操作:public void writer(String str,boolean append) throws IOException
如:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileWriter;
- import java.io.Writer;
- public class FileWriterDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- Writer writer = new FileWriter(file);
- String str = "hello world";
- writer.write(str);
- writer.close();
- }
- }
4、 字符输入流Reader
字符输入流与字节输入流不同的地方是使用的是char 数组, Reader 的定义为:
public abstract class Reader extends Object implements Readable,Closeable, Reader 是一个抽象类,可以使用 FileReader 类进行文件操作,读取方法有:
读取一组字符:public int read(char[] cbuf) throws IOException
读取一个字符:public int read() throws IOException
如:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileReader;
- import java.io.Reader;
- public class FileReaderDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- Reader reader = new FileReader(file);
- char[] c = new char[(int)file.length()];
- reader.read(c);
- System.out.println(new String(c));
- reader.close();
- }
- }
使用字符流也可以一个个的输出:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileReader;
- import java.io.Reader;
- public class FileReaderDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- Reader reader = new FileReader(file);
- char[] c = new char[(int) file.length()];
- for (int i = 0; i < c.length; i++) {
- c[i] = (char) reader.read();
- }
- System.out.println(new String(c));
- reader.close();
- }
- }
5、 字节流和字符流的区别
下面字节流操作文件代码没有关闭操作,内容照常被写到文件中:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- public class FileOutputStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- OutputStream outputStream = new FileOutputStream(file);
- String str = "hello world";
- byte[] b = str.getBytes();
- outputStream.write(b);
- //outputStream.close();
- }
- }
下面字符流操作文件代码没有关闭操作,但是内容并没有写到文件中:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileWriter;
- import java.io.Writer;
- public class FileWriterDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- Writer writer = new FileWriter(file);
- String str = "hello world";
- writer.write(str);
- //writer.close();
- }
- }
但是使用了flush() 方法后,即使没有关闭操作,内容就被写到文件中了:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileWriter;
- import java.io.Writer;
- public class FileWriterDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- Writer writer = new FileWriter(file);
- String str = "hello world";
- writer.write(str);
- // writer.close();
- writer.flush();// 刷新缓冲区
- }
- }
之前代码只有close() 方法而没有 flush() 方法也能写进文件是因为 close() 方法会强制刷新缓冲区,可以得出下面结论:
字节操作流直接操作文件,不使用缓冲区
字符操作流是操作缓冲区,然后再通过缓冲区操作文件
综合来说,在传输或者硬盘上的数据都是以字节的形式保存的,所以字节流的操作比较多,但是在操作中文的时候,字符流用的比较多。
Java IO之内存流
FileInputStream和 FileOutputStream 操作的目标是文件,假设有一些临时的信息需要通过 IO 操作,如果将这些临时信息保存到文件中不太合理,因为操作的最后还需要把文件给删除掉,所以 IO 操作中就提供了内存操作流,它的操作目标是内存。
使用ByteArrayOutputStream 和 ByteArrayInputStream 来完成内存操作流:
ByteArrayOutputStream:用于内存向程序输出,其基本作用就像 OutputStream 一样,一个个的数据读取;
ByteArrayInputStream:用于从程序向内存写入,其构造方法为:
public ByteArrayInputStream(bute[] buf);
以下代码为使用内存操作流完成小写字母到大写字母的转换:
- package com.chenzehe.test.io;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- public class ByteArrayStreamDemo {
- public static void main(String[] args) {
- String helloworld = "helloworld";
- ByteArrayInputStream bis = new ByteArrayInputStream(
- helloworld.getBytes());
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int temp = 0;
- while ((temp = bis.read()) != -1) {
- char c = (char) temp;
- bos.write(Character.toUpperCase(c));
- }
- System.out.println(bos.toString());
- }
- }
Java IO之管道流
管理流是两个线程间通信使用的,由 PipedOutputStream和 PipedInputStream 两个类来完成,这两个类在使用的时候基本上和 OutputStream 和 InputStream 一样,唯一的区别就是在于连接管道的操作上: public void connect(PipedInputStream snk) throws IOException
下面代码进行管道流的操作:
- package com.chenzehe.test.io;
- import java.io.PipedInputStream;
- import java.io.PipedOutputStream;
- // 发送数据的类
- class Send implements Runnable {
- private PipedOutputStream output = null;
- public Send() {
- this.output = new PipedOutputStream();
- }
- public void run() {
- String helloworld = "hello world!";
- try {
- this.output.write(helloworld.getBytes());
- this.output.close();
- } catch (Exception e) {
- }
- }
- public PipedOutputStream getOutput() {
- return output;
- }
- public void setOutput(PipedOutputStream output) {
- this.output = output;
- }
- }
- // 接收数据的类
- class Receive implements Runnable {
- private PipedInputStream input = null;
- public Receive() {
- this.input = new PipedInputStream();
- }
- public void run() {
- byte[] b = new byte[1024];
- int len = 0;
- try {
- len = this.input.read(b);
- this.input.close();
- } catch (Exception e) {
- }
- System.out.println(new String(b, 0, len));
- }
- public PipedInputStream getInput() {
- return input;
- }
- public void setInput(PipedInputStream input) {
- this.input = input;
- }
- }
- public class PipedStreamDemo {
- public static void main(String[] args) throws Exception {
- Send send = new Send();
- Receive receive = new Receive();
- send.getOutput().connect(receive.getInput());// 进行管道连接
- new Thread(send).start();
- new Thread(receive).start();
- }
- }
Java IO之打印流
使用 OutputStream可以完成数据的输出功能,但是如果输出一个 float 类型的数据并不好输出,它的输出功能并不强大,要想使用更强大的输出功能,则可以使用打印流。打印流有两种:一种是 PrintStream ,一种是 PrintWriter 。
PrintStream的定义:
public class PrintStream extends FilterOutputStream implements Appendable,Closeable{
}
PrintStream是 OutputStream 的子类
PrintStream的构造方法:
public PrintStream(OutputStream out){
}
实际上PrintStream 属于装饰,也就是说根据实例化 PrintStream 类的对象不同,输出的功能也不同。
下面代码为使用PrintStream 向文件输出:
- package com.chenzehe.test.io;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.PrintStream;
- public class PrintStreamDemo {
- public static void main(String[] args) throws Exception {
- File file = new File("D:" + File.separator + "demo.txt");
- PrintStream out = new PrintStream(new FileOutputStream(file));
- out.print("hello ");
- out.println("world!");
- out.println(100);
- }
- }