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); } }