Java IO (上)
Java IO 是一套Java用来读写数据(输入和输出)的API。大部分程序都要处理一些输入,并由输入产生一些输出。Java为此提供了java.io包。
流
1.在Java IO中,流是一个核心的概念。流从概念上来说是一个连续的数据流。你既可以从流中读取数据,也可以往流中写数据。流与数据源或者数据流向的媒介相关联。
2.在Java IO中流既可以是字节流(以字节为单位进行读写),也可以是字符流(以字符为单位进行读写)。
3.字节流通常以“stream”命名,比如InputStream和OutputStream。
除了DataInputStream 和DataOutputStream 还能够读写int, long, float和double类型的值以外,其他流在一个操作时间内只能读取或者写入一个原始字节。
4.字符流通常以“Reader”或者“Writer”命名。字符流能够读写字符(比如Latin1或者Unicode字符)
Java IO类概述表
接下来是一张通过输入、输出、基于字节或者字符、以及其他比如缓冲、解析之类的特定用途划分的大部分Java IO类的表格。
InputStream
java.io.InputStream类是所有Java IO输入流的基类,通常使用输入流中的read()方法读取数据。
read()方法返回一个整数,代表了读取到的字节的内容(译者注:0 ~ 255)。当达到流末尾没有更多数据可以读取的时候,read()方法返回-1。
@Test
public void inPutStreamTest() throws IOException{
//这个例子创建了FileInputStream实例。FileInputStream是InputStream的子类,所以可以把FileInputStream实例赋值给InputStream变量
InputStream inputStream = new FileInputStream("d:\\testio.txt");
int data = inputStream.read();
while (data!=-1) {
data = inputStream.read();
}
inputStream.close();
}
read(byte[])
InputStream包含了2个从InputStream中读取数据并将数据存储到缓冲数组中的read()方法,他们分别是:
- int read(byte[])
- int read(byte, int offset, int length)
一次性读取一个字节数组的方式,比一次性读取一个字节的方式快的多,所以,尽可能使用这两个方法代替read()方法。
@Test
public void scoketTest () throws IOException{
InputStream inputStream = new FileInputStream("d:\\testio.txt");
byte [] b= new byte[1024];
int bytesRead = inputStream.read(b);
while (bytesRead!=-1) {
System.out.println(new String(b,"gbk"));
bytesRead = inputStream.read(b);
}
inputStream.close();
}
OutputStream
java.io.OutputStream是Java IO中所有输出流的基类。
1 @Test
2 public void outPutStreamTest() throws IOException{
3 OutputStream output = new FileOutputStream("d:\\testio.txt");
4 output.write("Hello World".getBytes());
5 output.close();
6 }
flush()
OutputStream的flush()方法将所有写入到OutputStream的数据冲刷到相应的目标媒介中。比如,如果输出流是FileOutputStream,那么写入到其中的数据可能并没有真正写入到磁盘中。
即使所有数据都写入到了FileOutputStream,这些数据还是有可能保留在内存的缓冲区中。通过调用flush()方法,可以把缓冲区内的数据刷新到磁盘(或者网络,以及其他任何形式的目标媒介)中。
@Test
public void outPutStream () throws IOException{
OutputStream outputStream = new FileOutputStream("d:\\outtest.txt",false);//outtest.txt
String aString="12";
outputStream.write(aString.getBytes());
outputStream.flush();
outputStream.close();
}
组合流
你可以将流整合起来以便实现更高级的输入和输出操作。比如,一次读取一个字节是很慢的,所以可以从磁盘中一次读取一大块数据,然后从读到的数据块中获取字节。
为了实现缓冲,可以把InputStream包装到BufferedInputStream中。
InputStream input = new BufferedInputStream(new FileInputStream("c:\\data\\inputTest.txt"));
Java IO的Reader和Writer除了基于字符之外,其他方面都与InputStream和OutputStream非常类似。他们被用于读写文本。
Reader
Reader类是Java IO中所有Reader的基类。子类包括BufferedReader,PushbackReader,InputStreamReader,StringReader和其他Reader。
@Test
public void readerTest() throws IOException{
Reader reader = new FileReader("d:\\testio.txt");
int data = reader.read();
while(data != -1){
data = reader.read();
}
reader.close();
}
Reader的read()方法返回一个字符,意味着这个返回值的范围在0到65535之间(当达到流末尾时,同样返回-1)。
这并不意味着Reade只会从数据源中一次读取2个字节,Reader会根据文本的编码,一次读取一个或者多个字节。
Writer
Writer类是Java IO中所有Writer的基类。子类包括BufferedWriter和PrintWriter等等
FileInputStream
FileInputStream可以以字节流的形式读取文件内容。FileInputStream是InputStream的子类,这意味着你可以把FileInputStream当做InputStream使用(FileInputStream与InputStream的行为类似)。
@Test
public void fileInputStream () throws IOException{
File file = new File("c:\\data\\input-text.txt");
InputStream input = new FileInputStream(file);
//InputStream input = new FileInputStream("c:\\data\\input-text.txt");
int data = input.read();while(data != -1) {
//do something with data...
data = input.read();
}
input.close();
}
FileOutputStream
FileOutputStream可以往文件里写入字节流,它是OutputStream的子类,所以你可以像使用OutputStream那样使用FileOutputStream
@Test
public void outputStream () throws IOException{
OutputStream output = new FileOutputStream("c:\\data\\output-text.txt");
output.write("something".getBytes());
output.close();
//appends to file
OutputStream output1 = new FileOutputStream("c:\\data\\output-text.txt", true);
//overwrites file
OutputStream output2 = new FileOutputStream("c:\\data\\output-text.txt", false);
}
RandomAccessFile
RandomAccessFile允许你来回读写文件,也可以替换文件中的某些部分。FileInputStream和FileOutputStream没有这样的功能
@Test
public void randomAccessFile () throws IOException{
/**
* 创建一个RandomAccessFile
* 在使用RandomAccessFile之前,必须初始化它
* 请注意构造函数的第二个参数:"rw",表明你以读写方式打开文件
*/
RandomAccessFile file = new RandomAccessFile("c:\\data\\file.txt", "rw");
//读取RandomAccessFile
file.read();
//写入RandomAccessFile
file.write("Hello World".getBytes());
//调用getFilePointer()获得当前文件指针的位置
long pointer = file.getFilePointer();
//在RandomAccessFile的某个位置读写之前,必须把文件指针指向该位置。通过seek()方法可以达到这一目标
file.seek(pointer);
file.close();
}