持续更新…
程序中的变量和数组存储数据是暂时的,因为他们存储在内存中,而且有定义范围和生命周期。而文件是存储在磁盘、光盘
或磁带等二级存储设备上的,保存的数据是永久的。对于支持商业应用的语言来说,文件操作是十分重要的。而想要对文件
进行读写操作,就必须掌握Java的输入输出操作JavaAPI中的java.io包就是专门处理输入输出的类和方法。
Java中,把不同的输入源(输入设备)、输出源(输出设备)抽象的表示为流(stream)。流是计算机中输入和输出之间运动的数据序列。流代表任何有能力生成数据的数据源对象或者是有能力接收数据的接收端对象。流屏蔽了实际的I/O设备中处理数据的细节。可以将流分成输入流和输出流。
注:流只能显示字符而不能输出图像。
Java.io包支持两种类型的流:包含字节的字节流(Byte stream)和包含字符数据的字符流(Character stream)。另外,还有包含二进制数据的二进制流(Binary stream)。
1.二进制流
数据以一系列与内存中完全相同的字节的形式写入的流。 传输过程中不能进行任何数据转换。Java中的二进制流就是数据流。二进制的数值只是按字节序列写入。二进制流由DataInput接口和DataOutput接口处理。
2. 字节流
字节流的每个字节都是ASCII吗,代表一个字符。使用ASCII码的形式输出,与ASCII码的字符是一一对应的,一个字节表示一个ASCII码字符。所以有利于对ASCII码的字符进行处理,也便于输出ASCII码的字符。向字节流写入字符或者从字节流读取字符,都不会发生任何转换过程。
字节流由InputStream和OutputStream处理、
3. 字符流
字符流把内存中的数据转换为Unicode码,一个Unicode由两个字节组成。字符流应用于存储和获取文本文件,还可以读取非Java语言生成的文本文件。所有二进制数值形式的数据写入字符流之前都必须首先转换成文本的形式。当字符数据的形式把字符串写入到流中。在读取字符串时,把流中数据从本地计算机的表示形式(本地机器字符编码)转换回Unicode码。在写字符流时,字符从Unicode码转换成字符的本地机器字符编码表示。字符流由Reader和Writer处理。
当开始运行一个应用时,系统会自动创建3个流对象
所谓的Console I/O,就操作系统来说就是通过命令提示符窗口进行数据输入输出。
标准输入流(standard Input stream)的默认输入位置是Console,也就是操作系统的命令提示符窗口。通常对于键盘,使一个程序能够接收从键盘输入的信息。由System类的in成员封装,具有InputStream类型。
标准输出流(standard Output stream)的默认输出位置是Console,也就是操作系统的命令提示符窗口。通常对于命令行输出,使一个程序能够向显示屏输出信息。由System类的out成员封装,具有PrintStream类型。
标准错误输出流(standard error Outputstream)的默认输入位置是Console,也就是操作系统的命令提示符窗口。通常把错误信息映射到命令行输出,使一个程序能够向显示屏输出错误信息。由System类的err成员封装,具有PrintStream类型。
控制台的输入输出
关于控制台的输入输出可以参考我的另外一篇博文
https://blog.csdn.net/dypnlw/article/details/80241897
下面将详细讲述字节流和字符流中Java.io包对应的类和方法。
如果想要读写8位的字节,程序应该使用字节流,即InputStream和OutputStream的下层类。
类名 | 描述 |
---|---|
BufferedInputStream | 缓冲输入流 |
BufferedOutputStream | 缓冲输出流 |
ByteArrayInputStream | 从字节数组读取的输入流 |
ByteArrayOutputStream | 向字节数组写入的输出流 |
DataInputStream | 包含读取Java标准数据类型方法的输入流 |
DataOutputStream | 包含编写Java 标准数据类型方法的输出流 |
FileInputStream | 读取文件的输入流 |
FileOutputStream | 写文件的输出流 |
FilterInputStream | 实现 InputStream |
FilterOutputStream | 实现 OutputStream |
InputStream | 描述流输入的抽象类 |
OutputStream | 描述流输出的抽象类 |
PipedInputStream | 输入管道 |
PipedOutputStream | 输出管道 |
PrintStream | 包含print( ) 和 println( )的输出流 |
PushbackInputStream | 支持向输入流返回一个字节的单字节的“unget”的输入流 |
RandomAccessFile | 支持随机文件输入/输出 |
SequenceInputStream | 两个或两个以上顺序读取的输入流组成的输入流 |
InputStream类
方法 | 描述 |
---|---|
int available() | 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 |
void close() | 关闭此输入流并释放与该流关联的所有系统资源。 |
void mark(int readlimit) | 在此输入流中标记当前的位置。 |
boolean markSupported() | 测试此输入流是否支持 mark 和 reset 方法。 |
abstract int read() | 从输入流中读取数据的下一个字节。 |
int read(byte[] b) | 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 |
int read(byte[] b, int off, int len) | 将输入流中最多 len 个数据字节读入 byte 数组。 |
void reset() | 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。 |
long skip(long n) | 跳过和丢弃此输入流中数据的 n 个字节。 |
OutputStream类
方法 | 描述 |
---|---|
void close() | 关闭此输出流并释放与此流有关的所有系统资源。 |
void flush() | 刷新此输出流并强制写出所有缓冲的输出字节。 |
void write(byte[] b) | 将 b.length 个字节从指定的 byte 数组写入此输出流。 |
void write(byte[] b, int off, int len) | 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void write(int b) | 将指定的字节写入此输出流。 |
FileInputStream类
FileOutputStream类
其他子类API说明详参:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
文件按字节流的方式拷贝:
package JavaReview.FileIO;
import java.io.*;
//文件按字节流的方式拷贝
public class CopyFileByte {
public static void main(String args[]) throws IOException
{
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\input.txt");
out = new FileOutputStream("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\output.txt");
int c;
//read()方法读到文件末尾时,返回-1
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
例1中,上面使用的是文件名来创建FileInoutStream和FileOutputStream,实际上可以还可以使用文件对象来创建输入输出流。字节流的每次操作都是一个数据单位——字节,假如input.txt文件中包含 Hello world ,那么它将复制完“H”之后,再复制“e”,接着就是“l”,如此类推直到其结束。in.read()每次从输入流中读取一个字节,如果达到文件末尾就返回-1。使用完了,还要关闭这些字节流,调用close()方法。
File inFile = new File("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\input.txt");
File outFile = new File("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\output.txt");
FileInputStream in = new FileInputStream(inFile);
FileOutputStream out = new FileOutputStream(outFile);
Reader类和Writer类的下层类
类名 | 含义 |
---|---|
BufferedReader | 缓冲输入字符流 |
BufferedWriter | 缓冲输出字符流 |
CharArrayReader | 从字符数组读取数据的输入流 |
CharArrayWriter | 向字符数组写数据的输出流 |
FileReader | 读取文件的输入流 |
FileWriter | 写文件的输出流 |
FilterReader | 过滤读 |
FilterWriter | 过滤写 |
InputStreamReader | 把字节转换成字符的输入流 |
LineNumberReader | 计算行数的输入流 |
OutputStreamWriter | 把字符转换成字节的输出流 |
PipedReader | 输入管道 |
PipedWriter | 输出管道 |
PrintWriter | 包含print( )和println( )的输出流 |
PushbackReader | 允许字符返回到输入流的输入流 |
Reader | 描述字符流输入的抽象类 |
StringReader | 读取字符串的输入流 |
StringWriter | 写字符串的输出流 |
Writer | 描述字符流输出的抽象类 |
类似于字节,字符的抽象类Reader和 Writer中也定义了关键方法read()和write(),它们分别对字符进行读写。两种方法也都是抽象方法,被子类重载。
Reader类
Writer类
其他子类API参考链接:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
例子代码:
package JavaReview.FileIO;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFileCharacter {
public static void main(String[] args) throws IOException {
FileReader in=null;
FileWriter out=null;
try {
in=new FileReader("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\input.txt");
out=new FileWriter("D:\\IDEA_Pro\\JavaPro\\src\\JavaReview\\FileIO\\output.txt");
int c;
while((c=in.read())!=-1) {
out.write(c);
}
}finally {
if (in!=null){
in.close();
}
if(out!=null){
out.close();
}
}
}
}
字节流和字符流的对比
缓冲区
在实际的编写输入输出的代码时,经常会用到BufferWriter或者BufferReader,这样做的目的是为了利用缓冲区,将读入或者要写入的数据添加到缓冲区,当缓冲区满的时候总的进行一次读入或者写入操作,这样的话能够有效地提高程序的效率。