Java 中 I/O 操作主要是指使用 Java 进行输入, 输出操作. Java 所有的 I/O 机制都是基于数据流进行输入输出, 这些数据流表示了字符或者字节数据的流动序列
数据流是一串连续不断的数据的集合, 就象水管里的水流, 在水管的一端一点一点地供水, 而在水管的另一端看到的是一股连续不断的水流数据写入程序可以是一段一段地向数据流管道中写入数据, 这些数据段会按先后顺序形成一个长的数据流对数据读取程序来说, 看不到数据流在写入时的分段情况, 每次可以读取其中的任意长度的数据, 但只能先读取前面的数据后, 再读取后面的数据 (不能随机读取) 不管写入时是将数据分多次写入, 还是作为一个整体一次写入, 读取时的效果都是完全一样的
简而言之: 数据流是一组有序, 有起点和终点的字节的数据序列包括输入流和输出流
当程序需要读取数据的时候, 就会建立一个通向数据源的连接, 这个数据源可以是文件, 内存, 或是网络连接类似的, 当程序需要写入数据的时候, 就会建立一个通向目的地的连接
数据流分类:
流序列中的数据既可以是未经加工的原始二进制数据, 也可以是经一定编码处理后符合某种格式规定的特定数据因此 Java 中的流分为两种: 1) 字节流: 数据流中最小的数据单元是字节 2) 字符流: 数据流中最小的数据单元是字符, Java 中的字符是 Unicode 编码, 一个字符占用两个字节
概览
Java.io 包中最重要的就是 5 个类和一个接口 5 个类指的是 FileOutputStreamInputStreamWriterReader; 一个接口指的是 Serializable 掌握了这些就掌握了 Java I/O 的精髓了
Java I/O 主要包括如下 3 层次:
流式部分最主要的部分如: OutputStreamInputStreamWriterReader 等非流式部分如: File 类 RandomAccessFile 类和 FileDescriptor 等类其他文件读取部分的与安全相关的类, 如: SerializablePermission 类, 以及与本地操作系统相关的文件系统的类, 如: FileSystem 类和 Win32FileSystem 类和 WinNTFileSystem 类
主要类如下:
File(文件特征与管理): 用于文件或者目录的描述信息, 例如生成新目录, 修改文件名, 删除文件, 判断文件所在路径等 InputStream(字节流, 二进制格式操作): 抽象类, 基于字节的输入操作, 是所有输入流的父类定义了所有输入流都具有的共同特征 OutputStream(字节流, 二进制格式操作): 抽象类基于字节的输出操作是所有输出流的父类定义了所有输出流都具有的共同特征 Reader(字符流, 文本格式操作): 抽象类, 基于字符的输入操作 Writer(字符流, 文本格式操作): 抽象类, 基于字符的输出操作 RandomAccessFile(随机文件操作): 它的功能丰富, 可以从文件的任意位置进行存取 (输入输出) 操作
I/O 流
java.io 包里有 4 个基本类: InputStreamOutputStream 及 ReaderWriter 类, 它们分别处理字节流和字符流
其他各种各样的流都是由这 4 个派生出来的
按来源 / 去向分类:
File(文件): FileInputStream, FileOutputStream, FileReader, FileWriterbyte[]:ByteArrayInputStream, ByteArrayOutputStreamChar[]: CharArrayReader, CharArrayWriterString: StringBufferInputStream, StringReader, StringWriter 网络数据流: InputStream, OutputStream, Reader, WriterInputStream
InputStream 为字节输入流, 它本身为一个抽象类, 必须依靠其子类实现各种功能, 此抽象类是表示字节输入流的所有类的超类 继承自 InputStream 的流都是向程序中输入数据的, 且数据单位为字节(8bit);
InputStream 是输入字节数据用的类, 所以 InputStream 类提供了 3 种重载的 read 方法. Inputstream 类中的常用方法:
public abstract int read( ): 读取一个 byte 的数据, 返回值是高位补 0 的 int 类型值若返回值 =-1 说明没有读取到任何字节读取工作结束 public int read(byte b[ ]): 读取 b.length 个字节的数据放到 b 数组中返回值是读取的字节数该方法实际上是调用下一个方法实现的 public int read(byte b[ ], int off, int len): 从输入流中最多读取 len 个字节的数据, 存放到偏移量为 off 的 b 数组中 public int available( ): 返回输入流中可以读取的字节数注意: 若输入阻塞, 当前线程将被挂起, 如果 InputStream 对象调用这个方法的话, 它只会返回 0, 这个方法必须由继承 InputStream 类的子类对象调用才有用, public long skip(long n): 忽略输入流中的 n 个字节, 返回值是实际忽略的字节数, 跳过一些字节来读取 public int close( ) : 使用完后, 必须对我们打开的流进行关闭
来看看几种不同的 InputStream:
FileInputStream 把一个文件作为 InputStream, 实现对文件的读取操作 ByteArrayInputStream: 把内存中的一个缓冲区作为 InputStream 使用 StringBufferInputStream: 把一个 String 对象作为 InputStreamPipedInputStream: 实现了 pipe 的概念, 主要在线程中使用 SequenceInputStream: 把多个 InputStream 合并为一个 InputStreamOutputStream
OutputStream 提供了 3 个 write 方法来做数据的输出, 这个是和 InputStream 是相对应的
public void write(byte b[ ]): 将参数 b 中的字节写到输出流 public void write(byte b[ ], int off, int len) : 将参数 b 的从偏移量 off 开始的 len 个字节写到输出流 public abstract void write(int b) : 先将 int 转换为 byte 类型, 把低字节写入到输出流中 public void flush( ) : 将数据缓冲区中数据全部输出, 并清空缓冲区 public void close( ) : 关闭输出流并释放与流相关的系统资源
几种不同的 OutputStream:
ByteArrayOutputStream: 把信息存入内存中的一个缓冲区中 FileOutputStream: 把信息存入文件中 PipedOutputStream: 实现了 pipe 的概念, 主要在线程中使用 SequenceOutputStream: 把多个 OutStream 合并为一个 OutStream
Reader 和 InputStream 类似; Writer 和 OutputStream 类似
有两个需要注意的:
InputStreamReader : 从输入流读取字节, 在将它们转换成字符 BufferReader : 接受 Reader 对象作为参数, 并对其添加字符缓冲器, 使用 readline()方法可以读取一行
如何选择 I/O 流
确定是输入还是输出
输入: 输入流 InputStream Reader
输出: 输出流 OutputStream Writer 明确操作的数据对象是否是纯文本
是: 字符流 Reader,Writer
否: 字节流 InputStream,OutputStream 明确具体的设备 文件:
读: FileInputStream,, FileReader,
写: FileOutputStream,FileWriter 数组:
- byte[ ]:ByteArrayInputStream, ByteArrayOutputStream
- char[ ]:CharArrayReader, CharArrayWriterString:
StringBufferInputStream(已过时, 因为其只能用于 String 的每个字符都是 8 位的字符串), StringReader, StringWriterSocket 流
键盘: 用 System.in(是一个 InputStream 对象)读取, 用 System.out(是一个 OutoutStream 对象)打印是否需要转换流
是, 就使用转换流, 从 Stream 转化为 ReaderWriter:InputStreamReader,OutputStreamWriter 是否需要缓冲提高效率
是就加上 Buffered:BufferedInputStream, BufferedOuputStream, BufferedReader, BufferedWriter 是否需要格式化输出
示例代码
将标准输入 (键盘输入) 显示到标准输出(显示器), 支持字符
- char ch;
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // 将字节流转为字符流, 带缓冲
- try {
- while ((ch = (char) in.read()) != -1){
- System.out.print(ch);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
将 AtomicityTest.java 的内容打印到显示器
方法一:
- BufferedReader in = new BufferedReader(new FileReader("AtomicityTest.java"));
- String s;
- try {
- while ((s = in.readLine()) != null){
- System.out.println(s);
- }
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
方法二:
- FileReader in = new FileReader("AtomicityTest.java");
- int b;
- try {
- while ((b = in.read()) != -1){
- System.out.print((char)b);
- }
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
方法三:(有可能出现乱码)
- FileInputStream in = new FileInputStream("AtomicityTest.java");
- int n = 50;
- byte[] buffer = new byte[n];
- try {
- while ((in.read(buffer,0,n) != -1 && n> 0)){
- System.out.print(new String(buffer));
- }
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
将文件 A 的内容拷贝到文件 B
- FileInputStream in = new FileInputStream("AtomicityTest.java");
- FileOutputStream out = new FileOutputStream("copy.txt");
- int b;
- while ((b = in.read()) != -1){
- out.write(b);
- }
- out.flush();
- in.close();
- out.close();
将标准输入的内容写入文件
- Scanner in = new Scanner(System.in);
- FileWriter out = new FileWriter("systemIn.log");
- String s;
- while (!(s = in.nextLine()).equals("Q")){
- out.write(s + "\n");
- }
- out.flush();
- out.close();
- in.close();
来源: http://www.jqhtml.com/14265.html