File类虽然可以操作文件,但是并不是操作文件的内容,如果要进行内容的操作只能通过两种途径:字节流、字符流
如果要进行输入,输出操作一般都会按照如下的步骤(以文件操作为例):
- 通过File类定义一个要操作文件的路径;
- 通过字节流或字符流的子类对象为父类对象实例化;
- 进行数据的读(输入)、写(输出)操作;
- 数据流属于资源操作,资源操作必须关闭。
java.io包定义了两类流:
- 字节流(JDK 1.0) : InputStream、OutputStream;
- 字符流(JDK 1.1) : Reader、Writer。
1 字节输出流:OutputStream(重点)
OutputStream类是一个专门进行字节数据输出的一个类,定义如下:
public abstract class OutputStream
extends Object
implements Closeable, Flushable
可以发先OutputStream类实现了个两个接口:Closeable, Flushable;这两个接口定义如下:
Closeable接口(JDK 1.5) | Flushable接口(JDK 1.5) |
---|---|
public interface Closeable extends AutoCloseable | public interface Flushable |
在JDK 1.7 中引入了自动关闭机制,所以Closeable又继承AutoCloseable接口,定义如下:
public interface AutoCloseable {
public void close() throws Exception;
}
但是OutputStream类在JDK 1.0的时候就提供了,这个类原本就定义了close()和flush()两个方法,所以现在以上的两个接口就几乎可以忽略。
在OutputStream类里面提供有三个输出的方法:
- 输出单个字节:
public abstract void write(int b) throws IOException
- 输出全部字节数组:
public void write(byte[] b) throws IOException
- 输出部分字节数据:
public void write(byte[] b, int off, int len) throws IOException
OutputStream是抽象类,如果为抽象类进行实例化操作,那么必须使用抽象类的子类,由于要使用文件操作,可以使用FileOutputStream子类,这个子类里面定义如下的构造方法: - 创建或覆盖已有文件:
public FileOutputStream(File file) throws FileNotFoundException
- 文件内容追加:
public FileOutputStream(File file, boolean append) throws FileNotFoundException
范例:文件内容的输出
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class IntOrOutPutStream {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.mkdirs();
}
OutputStream output = new FileOutputStream(file);
String str = "好好学习,天天向上!";
byte[] data = str.getBytes();
output.write(data);
output.close();
}
}
以上是整个字节数组的内容进行了输出,如果此时要输出的文件不存在,就会自动创建文件。
范例:单个字节的方式输出
for (int x = 0 ; x < data.length ; x++) {
output.write(data[x]);
}
范例:输出部分字节数组内容
output.write(data, 6, 4);
以上都是直接覆盖原有文件内容,也可以实现内容的追加,只需要更换FileOutputStream类的构造方法即可:
OutputStream output = new FileOutputStream(file , true);
// \r\n 可以实现换行
String str = "好好学习,天天向上!\r\n";
2 字节输入流:InputStream
如果需要进行数据的读取操作,可以利用InputStream类实现功能,此类定义:public abstract class InputStream extends Object implements Closeable
虽然此类实现了Closeable接口,但是与OutputStream类一样,可以不用考虑接口的存在,在InputStream类里面也定义又数据读取的方法:
- 读取单个字节:
public abstract int read() throws IOException
· 返回值:返回读取的字节内容,如果结尾没有数据了,返回 -1 - 将读取的数据保存在里字节数组里:
public int read(byte[] b) throws IOException
· 返回值:返回读取的数据长度,如果已经读取到结尾,返回 -1 - 将读取的数据保存在部分字节数据里:
public int read(byte[] b, int off, int len) throws IOException
· 返回值:读取的部分数据的长度,如果已经读取到结尾,返回 -1
InputStream是一个抽象类,如果要进行文件读取使用子类FileInputStream,此子类的构造方法:public FileInputStream(File file) throws FileNotFoundException
范例:向数组里面读取数据
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class InputStreamTest {
public static void main(String[] args) throws Exception{
//1.定义要输入的文件路径
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
//2. 使用InputStream进行读取
InputStream input = new FileInputStream(file);
//3. 读取数据
byte[] data = new byte[1024]; //准备长度为1024的数组
int len = input.read(data); //将内容保存到字节数组中
//4. 关闭输入流
input.close();
System.out.println("{" + new String(data , 0 ,len) + "}");
}
}
}
范例:单个字节数据读取
- 文件有很多字节数据,所以读取数据应采用循环的方式,但由于不确定循环次数,所以使用while循环。
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
public class InputStreamWhileTest {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
InputStream input = new FileInputStream(file);
byte[] data = new byte[1024];
int temp = 0;
int foot = 0;
//temp = input.read() , 表示将read() 方法读取的字节内容赋值给temp变量
//(temp = input.read()) != -1 , 判断读取temp的内容是否是-1
while ((temp = input.read()) != -1) {
data[foot++] = (byte) temp; //有内容进行保存
}
input.close();
System.out.println("{" +new String(data , 0 , foot)+ "}");
}
}
}
3 字符输出流:Writer
Writer类是在JDK1.1之后增加的,其类的定义如下:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
这个类除了实现了Closeable与Flushable接口外,又多实现了一个Appendable,这个接口的定义如下:
public interface Appendable {
public Appendable append(char c) throws IOException {}
public Appendable append(CharSequence csq) throws IOException {}
public Appendable append(CharSequence csq, int start, int end) throws IOException {}
}
在Appendable接口里面定义了追加类的操作,而且追加的数据都是字符或者字符串。
在Writer类里面定义有一下的输出方法(部分):
- 输出全部字符数组:
public void write(char[] cbuf) throws IOException
- 输出字符串:
public void write(String str) throws IOException
Writer是一个抽象类,如果想要为这个类的对象实例化,应该使用FileWriter子类:
范例:使用Writer类实现内容输出
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class WriterTest {
public static void main(String[] args) throws Exception {
File file = new File("D:" + File.separator + "Document"
+ File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
Writer writerfile = new FileWriter(file);
String str = "Hello world!";
writerfile.write(str);
writerfile.close();
}
}
4 字符输入流:Reader
Reader 是进行字符数据读取的输入流,其本身也是一个抽象类:
public abstract class Reader extends Object implements Readable, Closeable
在Reader类里面也提供有一系列的read()方法:
- 读取内容到字符数组:
public int read(char[] cbuf) throws IOException
· 返回值:表示读取的数据长度,如果已经读取到结尾了,返回 -1;
为Reader类实例化的可以使用FileReader子类完成。
范例:使用Reader读取数据
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
public class ReaderTest {
public static void main(String[] args) throws Exception {
File file = new File(
"D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
if (file.getParentFile().exists()) {
Reader readerfile = new FileReader(file);
char[] data = new char[1024];
int len = readerfile.read(data);
readerfile.close();
System.out.println(new String(data, 0, len));
}
}
}
5 字节流与字符流的区别?
- 字节流直接与终端进行数据交互,字符流需要将数据经过缓冲去处理后才可以输出。
- 在使用OutputStream输出数据的时候,即使最后没有关闭输出流,内容也可以正常输出,但是不关闭字符输出流,就表示在缓冲区中处理的内容不会被强制性清空,所以就不会输出数据;如果有特殊情况不能够关闭字符输出流,可以使用flush()方法强制清空缓冲区。
范例:强制清空缓冲区
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class FlushTest {
public static void main(String[] args) throws Exception{
File file = new File("D:" + File.separator + "Document" + File.separator + "Document" + File.separator + "test.txt");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
Writer out = new FileWriter(file);
String str = "Hello world @!";
out.write(str);
out.flush();
}
}
在开发之中,对字节数据处理是比较多的,例如:图片、音乐、电影;而对字符流最大的好处就是可以处理中文,所以在日后的开发之中,如果要处理中文, 优先考虑字符流,没有中文时,建议使用字节流。