目录
I / O流(上)
1. 什么是I / O流
过程分析
I / O的来源
Java 中的 I / O流
2. 字节流
OutputStream 常用方法
文件输出流 FileOutputStream 构造方法
示例
InputStream 常用方法
文件输入流 FileInputStream 构造方法
示例
综合练习
字节流应用场景
Java SE文章参考:Java SE入门及基础知识合集-CSDN博客
I / O流(上)
1. 什么是I / O流
在使用计算机时,你可能遇到过如下场景:
当你在编写一个文档时,突然断电了或者计算机蓝屏了,而文档又没有保存。当你重启计算机后,发现文档中修改的那部分内容丢失了,但保存过的内容依然还在。这是为什么呢?因为我们编写文档的时候,编写的内容是存储在计算机的内存中,这些内容属于临时数据,当我们保存文档后,这些临时数据就写进了磁盘,得以保存。
过程分析
编写文档内容存储在内存,换言之,就是向内存写数据
保存文档内容至磁盘,换言之,就是将内存中的数据取出来存储到磁盘
I / O的来源
I / O是 Input 和 Ouput 两个单词的首字母,表示输入输出。其参照物就是内存,写入内存,就是输入,从内存读取数据出来,就是输出。
Java 中的 I / O流
磁盘和内存是两个不同的设备,它们之间要实现数据的交互,就必须要建立一条通道,在Java 中实现建立这样的通道的是I / O 流。 Java 中的 I / O 流是按照数据类型来划分的。分别是字节流(缓冲流、二进制数据流和对象流)、字符流
2. 字节流
字节流 来自官方的说明
Programs use byte streams to perform input and output of 8-bit bytes. All byte stream classes are descended from InputStream and OutputStream.程序使用字节流执行 8 位字节的输入和输出。 所有字节流类均来自 InputStream 和 OutputStream 。
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 ;public void flush () throws IOException ; // 强制将通道中数据全部写出public void close () throws IOException ; // 关闭通道
文件输出流 FileOutputStream 构造方法
public FileOutputStream ( String name ) throws FileNotFoundException ; // 根据提供的文件路径构建一条文件输出通道// 根据提供的文件路径构建一条文件输出通道,并根据 append 的值决定是将内容追加到末尾还是直接覆盖public FileOutputStream ( String name , boolean append ) throws FileNotFoundException ;public FileOutputStream ( File file ) throws FileNotFoundException ; // 根据提供的文件信息构建一条文件输出通道// 根据提供的文件信息构建一条文件输出通道,并根据 append 的值决定是将内容追加到末尾还是直接覆盖public FileOutputStream ( File file , boolean append ) throws FileNotFoundException ;
示例
使用文件输出流将 " 文件输入输出流 " 写入磁盘文件中
package com .we . io ;import java . io . * ;/*** 使用文件输出流将 " 文件输入输出流 " 写入磁盘文件中*/public class Example1 {/*** 增强 for 循环语法:* for( 数据类型 变量名 : 遍历的数组 ){** }* @param args*/public static void main ( String [] args ) {//将内容写入文件时,需要保证这个文件的父级目录一定存在,否则将报文件未找到异常try {File dir = new File ( "F:\\aa" );if ( ! dir . exists ()) dir . mkdirs ();File file = new File ( dir , "io.txt" );//构建磁盘文件与内存之间的通道OutputStream os = new FileOutputStream ( file , true );String text = "文件输入输出流 " ;byte [] bytes = text . getBytes ();// for(byte b: bytes){// os.write(b);//一次向通道中写一个字节至文件中// }// os.write(bytes);//向通道中一次将所有字节数组中的内容全部发送过去//使用偏移量和长度的时候需要考虑数组下标越界os . write ( bytes , 3 , bytes . length - 3 );//在通道关闭之前使用,强制将通道中的数据写入文件中os . flush ();os . close (); // 关闭通道} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}}}
InputStream 常用方法
public abstract int read () throws IOException ; // 读取一个字节public int read ( byte b []) throws IOException ; // 读取多个字节存储至给定的字节数组中// 读取多个字节按照给定的偏移量及长度存储在给定的字节数组中public int read ( byte b [], int off , int len ) throws IOException ;public void close () throws IOException ; // 关闭流,也就是关闭磁盘和内存之间的通道public int available () throws IOException ; // 获取通道中数据的长度
文件输入流 FileInputStream 构造方法
public FileInputStream ( String name ) throws FileNotFoundException ; // 根据提供的文件路径构建一条文件输入通道public FileInputStream ( File file ) throws FileNotFoundException ; // 根据提供的文件信息构建一条文件输入通道
示例
使用文件输入流将文件信息从磁盘中读取到内存中来,并在控制台输出。
package com .we . io ;import java . io . FileInputStream ;import java . io . FileNotFoundException ;import java . io . IOException ;import java . io . InputStream ;/*** 使用文件输入流将文件信息从磁盘中读取到内存中来,并在控制台输出。*/public class Example2 {public static void main ( String [] args ) {try {InputStream is = new FileInputStream ( "F:\\aa\\io.txt" );int length = is . available (); // 获取通道中的数据长度//根据通道中数据的长度构建字节数组。byte [] buffer = new byte [ length ];// int index = 0;// while (true){// //读取通道中的数据,一次读取一个字节。如果读取到末尾,则返回-1// byte b = (byte) is.read();// if(b == -1) break;// buffer[index++] = b;index++;// }int readCount = is . read ( buffer ); // 将通道中的数据全部读取到 buffer 数组中System . out . println ( " 读取了 " + readCount + " 个字节 " );System . out . println ( new String ( buffer ));is . close (); // 关闭通道} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}}}
如果通道中数据长度过长,那么根据通道中数据的长度来构建字节数组,则可能导致内存不够,比如使用流读取一个大小为10G的文件,那么通道中就应该存在 10G 长的数据,此时应该怎么办?
package com . we . io ;import java . io . FileInputStream ;import java . io . FileNotFoundException ;import java . io . IOException ;import java . io . InputStream ;public class Example3 {public static void main ( String [] args ) {try {InputStream is = new FileInputStream ( "F:\\aa\\io.txt" );//实际开发过程中字节数组的长度一般定义为1024的整数倍byte [] buffer = new byte [ 31 ]; // 构建了一个长度为 31 的字节数组while ( true ){//从通道中读取数据存入字节数组buffer中,返回值就是读取的字节长度.//如果读取到数据的末尾,则返回-1int len = is . read ( buffer );if ( len == - 1 ) break ;System . out . println ( len );System . out . println ( new String ( buffer ));}is . close ();} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}}}
综合练习
使用字节流实现磁盘文件拷贝功能
package com . we . io ;import java . io . * ;/*** 文件拷贝*/public class Example5 {public static void main ( String [] args ) {String sourceFile = "F:\\study\\java\\chapter16\\src\\com\\cyx\\io\\Example1.java" ;String destFile = "F:\\aa\\IO.java" ;copyFile ( sourceFile , destFile );}public static void copyFile2 ( String sourceFile , String destFile ){File file = new File ( destFile );File parent = file . getParentFile ();if ( ! parent . exists ()) parent . mkdirs ();//try(){}catch(){} JDK 1.7//写在括号中的代码只能够是实现了AutoClosable接口的类try ( InputStream is = new FileInputStream ( sourceFile );OutputStream os = new FileOutputStream ( destFile );) {byte [] buffer = new byte [ 4096 ];while ( true ){int len = is . read ( buffer );if ( len == - 1 ) break ;os . write ( buffer , 0 , len );}os . flush ();} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}}public static void copyFile ( String sourceFile , String destFile ){File file = new File ( destFile );File parent = file . getParentFile ();if ( ! parent . exists ()) parent . mkdirs ();InputStream is = null ;OutputStream os = null ;try {is = new FileInputStream ( sourceFile );os = new FileOutputStream ( destFile );byte [] buffer = new byte [ 4096 ];while ( true ){int len = is . read ( buffer );if ( len == - 1 ) break ;os . write ( buffer , 0 , len );}os . flush ();} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();} finally {// if(is != null){// try {// is.close();// } catch (IOException e) {// }// }// if(os != null){// try {// os.close();// } catch (IOException e) {// }// }close ( is , os );}}//不定长自变量,本质是一个数组。在使用不定长自变量作为方法的参数时,必须为该方法参数列表的最后一个参数public static void close ( Closeable ... closeables ){for ( Closeable c : closeables ){if ( c != null ){try {c . close ();} catch ( IOException e ) {}}}}}
字节流应用场景
Byte streams should only be used for the most primitive I / O .字节流仅仅适用于读取原始数据(基本数据类型)