Java I/O学习(附实例和具体解释)
一、Java I/O类结构以及流的基本概念
在阅读Java I/O的实例之前我们必须清楚一些概念。我们先看看Java I/O的类结构图:
Java I/O主要以流的形式进行读写数据。
流是一组有顺序的。有起点和终点的字节集合。是对传输数据的总称或抽象。即数据在两设备间的传输称为流,流的本质是传输数据,依据传输数据特性将流抽象为各种类,方便更直观的进行数据操作。
依据处理数据的数据类型的不同能够分为:字符流和字节流。
字符流和字节流的主要差别:
1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文相应的字节数是两个。在UTF-8码表中是3个字节)时。先去查指定的编码表。将查到的字符返回。
2.字节流能够处理全部类型数据,如:图片,MP3,AVI视频文件。而字符流仅仅能处理字符数据。仅仅要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
3.实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的。而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。
下面我们以文件操作作为实例进一步了解。
二、字符流实例
之前提到过“仅仅要是处理纯文本数据,就要优先考虑使用字符流。除此之外都用字节流”。
因此本字符流操作实例是操作txt文件。对其进行读写操作。
2.1、一些概念
此前,我们须要了解一些概念。
Java採用16位的Unicode来表示字符串和字符的。
在写入字符流时我们都能够指定写入的字符串的编码。
这里博主贴出字符流类图结构,方便猿友阅读:
在文件操作的时候我们主要使用到FileReader和FileWriter或BufferedReader和BufferedWriter。
从类结构图来看:
FileReader是InputStreamReader的子类,而InputStreamReader是Reader的子类;
FileWriter是OutputStreamWriter的子类。而OutputStreamWriter则是Writer的子类。
2.2、FileReader和BufferedReader的使用
FileReader的经常使用构造包含下面两种:
(1)FileReader(String fileName):依据文件名称创建FileReader对象。
(2)FileReader(File file):依据File对象创建FileReader对象。
FileReader的经常用法包含下面几种:
(1)int read():读取单个字符。返回字符的整数值,假设已经到达文件尾,则返回-1.
(2)int read(char[] cbuf):将字符读入cbuf字符数组。
返回读取到的字符数,假设已经到达文件尾,则返回-1.
(3)int read(char[] cbuf,int off,int len):将读取到的字符存放到cbuf字符数组从off标识的偏移位置開始处。最多读取len个字符。
BufferedReader有下面两种构造方法:
(1)BufferedReader(Reader in):依据in代表的Reader对象创建BufferReader实例。缓冲区大小採用默认值。
(2)BufferedReader(Reader in,int sz):依据in代表的Reader对象创建BufferedReader实例。缓冲区大小採用指定sz值。
BufferedReader的经常用法包含下面几种:
(1)int read():返回字符的整数值,假设已经到达文件尾,则返回-1.
(2)int read(char[], int, int):将读取到的字符存放到cbuf字符数组从off标识的偏移位置開始处。最多读取len个字符。
(3)String readLine():读取一文本行。该方法遇到下面字符或者字符串觉得当前行结束:‘\n’(换行符),’\r’(回车符),’\r\n’(回车换行)。
返回值为该行内容的字符串。不包含不论什么行终止符,假设已到达流末尾,则返回null。
代码实例:
package java_io;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TestReader {
public static void main(String[] args) {
TestReader testReader = new TestReader();
String path = "C:\\Users\\luoguohui\\Desktop\\readerTest.txt";
testReader.readFileByFileReader(path);
testReader.readFileByBufferedReader(path);
}
public void readFileByFileReader(String path){
FileReader fileReader = null;
try {
fileReader = new FileReader(path);
char[] buf = new char[1024]; //每次读取1024个字符
int temp = 0;
System.out.println("readFileByFileReader运行结果:");
while ((temp = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, temp));
}
System.out.println();
} catch (Exception e) {
e.printStackTrace();
} finally { //像这样的i/o操作尽量finally确保关闭
if (fileReader!=null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void readFileByBufferedReader(String path){
File file = new File(path);
if (file.isFile()) {
BufferedReader bufferedReader = null;
FileReader fileReader = null;
try {
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
String line = bufferedReader.readLine();
System.out.println("readFileByBufferReader运行结果:");
while (line != null) {
System.out.println(line);
line = bufferedReader.readLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
上面代码用到finally。关于finally尽管与I/O无关,只是这里还是说一下:
1、无论有木有出现异常,finally块中代码都会运行。
2、当try和catch中有return时。finally仍然会运行;
3、finally是在return后面的表达式运算后运行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样。返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally运行前确定的;
4、finally中最好不要包含return。否则程序会提前退出,返回值不是try或catch中保存的返回值。
readerTest.txt文本内容:
运行结果:
2.3、FileWriter和BufferWriter的使用
FileWriter的经常使用构造有下面四种:
(1)FileWriter(String fileName):依据文件名称创建FileWriter对象。
(2)FileWriter(String fileName,boolean append):依据文件名称创建FileWriter对象,append參数用来指定是否在原文件之后追加内容。
(3)FileWriter(File file):依据File对象创建FileWriter对象。
(4)FileWriter(File file,boolean append):依据File对象创建FileWriter对象,append參数用来指定是否在原文件之后追加内容。
FileWriter的经常用法包含下面几种:
(1)void writer(int c):向文件里写入正整数c代表的单个字符。
(2)void writer(char[] cbuf):向文件里写入字符数组cbuf。
(3)void writer(char[] cbuf,int off, in len):向文件里写入字符数组cbuf从偏移位置off開始的len个字符。
(4)void writer(String str):向文件里写入字符串str,注意此方法不会在写入完成之后自己主动换行。
(5)void writer(String str,int off,int len):向文件里写入字符串str的从位置off開始、长度为len的一部分子串。
(6)Writer append(char c):向文件里追加单个字符c。
(7)Writer append(CharSequence csq):向文件里追加csq代表的一个字符序列。
CharSequence是从JDK1.4版本号開始引入的一个接口。代表字符值的一个可读序列,此接口对很多不同种类的字符序列提供统一的仅仅读訪问。
(8)Writer append(CharSequence csq,int start,int end):向文件里追加csq字符序列的从位置start開始、end结束的一部分字符。
(9)void flush():刷新字符输出流缓冲区。
(10)void close():关闭字符输出流。
BufferedWriter也拥有例如以下两种形式的构造方法:
(1)BufferedWriter(Writer out): 依据out代表的Writer对象创建BufferedWriter实例,缓冲区大小採用默认值。
(2)BufferedWriter(Writer out,int sz):依据out代表的Writer对象创建BufferedWriter实例,缓冲区大小採用指定的sz值。
BufferedWriter的经常用法包含下面几种:
(1)void close() :关闭字符输出流。
(2)void flush() :刷新字符输出流缓冲区。
(3)void newLine(): 写入文本行。
(4)void write(char[] cbuf, int offset, int count) :向文件里写入字符数组cbuf从偏移位置off開始的len个字符。
(5)void write(int oneChar) :写入单个字符。
(6)void write(String str, int offset, int count) :向文件里写入字符串str的从位置off開始、长度为len的一部分子串。
(7)以上的方法都是重写了Writer的,还有继承自java.io.Writer 的方法:Writer append(char c)、Writer append(CharSequence csq)、Writer append(CharSequence csq, int start, int end)、void write(char[] cbuf)、write(String str)等方法。
代码实例:
package java_io;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class TestWriter {
public static void main(String[] args) {
TestWriter testWriter = new TestWriter();
String path = "C:\\Users\\luoguohui\\Desktop\\readerTest.txt";
testWriter.writeFileByFileWriter(path);
testWriter.writeFileByBufferWriter(path);
}
public void writeFileByFileWriter(String path){
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(path,true);
//将字符串写入到流中,\r\n表示换行
//由于fileWriter不会自己主动换行
fileWriter.write("本行是通过fileWriter增加的行\r\n");
//假设想立即看到写入效果。则须要调用w.flush()方法
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void writeFileByBufferWriter(String path){
File file = new File(path);
if (file.isFile()) {
BufferedWriter bufferedWriter = null;
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(file,true);
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("本行是通过bufferedWriter增加的行\r\n");
bufferedWriter.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
我们先把readerTest.txt文件的内容清空。运行结果例如以下(不清空也行,仅仅是运行结果博主的不一样):
三、字节流实例
3.1、实例之前
再次声明之前提到过的“仅仅要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流”。
这里博主贴出字节流类图结构,方便猿友阅读:
下面我们依然以文件读写为例。
3.2、FileInputStream的使用
FileInputStream的构造方法:
(1)FileInputStream(File file) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
(2)FileInputStream(FileDescriptor fdObj) :通过使用文件描写叙述符 fdObj 创建一个 FileInputStream,该文件描写叙述符表示到文件系统中某个实际文件的现有连接。
(3)FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream的经常用法:
(1)int available():返回下一次对此输入流调用的方法能够不受堵塞地从此输入流读取(或跳过)的预计剩余字节数。
(2)void close():关闭此文件输入流并释放与此流有关的全部系统资源。
(3)protected void finalize():确保在不再引用文件输入流时调用其 close 方法。
(4)FileChannel getChannel():返回与此文件输入流有关的唯一 FileChannel 对象。
(5)FileDescriptor getFD():返回表示到文件系统中实际文件的连接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。
(6)int read():从此输入流中读取一个数据字节。
(7)int read(byte[] b):从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
(8)int read(byte[] b, int off, int len):从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
(9)long skip(long n):从输入流中跳过并丢弃 n 个字节的数据。
代码实例:
package java_io;
import java.io.FileInputStream;
import java.io.IOException;
public class TestFileInputStream {
public static void main(String[] args) {
TestFileInputStream testFileInputStream = new TestFileInputStream();
String path = "C:\\Users\\luoguohui\\Desktop\\readerTest.txt";
testFileInputStream.readFileByFileInputStream(path);
}
public void readFileByFileInputStream(String path) {
FileInputStream fileInputStream = null;
try {
// 创建文件输入流对象
fileInputStream = new FileInputStream(path);
// 设定读取的字节数
int n = 1024;
byte buffer[] = new byte[1024];
// 读取输入流
System.out.println("readFileByFileInputStream运行结果:");
while ((fileInputStream.read(buffer, 0, n) != -1) && (n > 0)) {
System.out.print(new String(buffer));
}
System.out.println();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭输入流
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
readerTest.txt内容:
运行结果:
3.3、FileOutputStream 的使用
FileOutputStream的构造方法:
(1)FileOutputStream(File file) :创建一个向指定 File 对象表示的文件里写入数据的文件输出流。
(2)FileOutputStream(File file, boolean append) :创建一个向指定 File 对象表示的文件里写入数据的文件输出流。append參数用来指定是否在原文件之后追加内容。
(3)FileOutputStream(FileDescriptor fdObj) :创建一个向指定文件描写叙述符处写入数据的输出文件流,该文件描写叙述符表示一个到文件系统中的某个实际文件的现有连接。
(4)FileOutputStream(String name) :创建一个向具有指定名称的文件里写入数据的输出文件流。
(5)FileOutputStream(String name, boolean append) : 创建一个向具有指定 name 的文件里写入数据的输出文件流。
append參数用来指定是否在原文件之后追加内容。
FileOutputStream的经常用法:
(1)void close() :关闭此输出流并释放与此流有关的全部系统资源。
(2)void flush() :刷新此输出流并强制写出全部缓冲的输出字节。
(3)void write(byte[] b) :将 b.length 个字节从指定的字节数组写入此输出流。
(4)void write(byte[] b, int off, int len) :将指定字节数组中从偏移量 off 開始的 len 个字节写入此输出流。
(6)abstract void write(int b) :将指定的字节写入此输出流。
代码实例:
package java_io;
import java.io.FileOutputStream;
public class TestFileOutputStream {
public static void main(String[] args) {
TestFileOutputStream testFileOutputStream = new TestFileOutputStream();
String path = "C:\\Users\\luoguohui\\Desktop\\readerTest.txt";
testFileOutputStream.readFileByFileOutputStream(path);
}
public void readFileByFileOutputStream(String path) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path,true);
String str = "这是使用FileOutputStream增加的内容\r\n";
byte[] b = str.getBytes();
fos.write(b);
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
运行结果: