IO流(Input/Output)
简介:
流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出。
IO技术实际上就是让数据在电脑内存或程序系统和硬件(硬盘,内存卡)之间转换的技术。
分类:
1、按流向
输入流:读取数据,把持久设备的数据读取到内存中。
输出流:写出数据,把内存的数据写出到持久设备。
2、按种类
字节流:传输过程中,传输数据的最基本单位是字节的流,常用的文件(txt、图片、mp3、mp4等)都可以用字节流来进行IO操作。
字符流:传输过程中,传输数据的最基本单位是字符的流,一般只能用于文本文件进行IO操作。
字节流转换:字节流+编码 =》字符流 ;字符流 =》字节流 + 解码 。
字节流:
字节流就是以字节为单位进行IO操作的数据流。字节流操作基本是在File类的基础上进行操纵的!
字节流的字符编码:字符编码把字符转换成数字存储到计算机中,按ASCii将字母映射为整数。把数字从计算机转换成相应的字符的过程称为解码。
编码方式的分类:
ASCII(数字、英文):1个字符占一个字节(所有的编码集都兼容ASCII)
ISO8859-1(欧洲):1个字符占一个字节
GB-2312/GBK:1个字符占两个字节
Unicode: 1个字符占两个字节(网络传输速度慢)
UTF-8:变长字节,对于英文一个字节,对于汉字两个或三个字节。
字节流常用的流有:
- FileInputStream
- FileOutputStream
- BufferedInputStream 【BufferedInputStream不是InputStream的直接实现子类,是FilterInputStream的子类】
- BufferedOutputStream 【BufferedOutputStream不是OutputStream的直接实现子类,是FilterOutputStream的子类】
1、FileInputStream
构造函数:
常用方法:
代码实例:(基本上流程和字符流一样就不在此详细解释)
1 package InputOutput; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 7 public class FileInputStreamDemo { 8 public static void main(String[] args) throws Exception { 9 // 指定文件路径 10 String filePath = "E:\JavaCodeDemo\InputOutput\FileInputStream"; 11 // 创建File对象 12 File file = new File(filePath, "Input.txt"); 13 // 创建文件Input.txt,方法会进行判断,如果没有会创建文件 14 file.createNewFile(); 15 // 创建字节流输入对象 16 FileInputStream input = new FileInputStream(file); 17 int flag = 0; 18 while ((flag = input.read()) != -1) { 19 System.out.println(flag); 20 } 21 //关闭资源 22 input.close(); 23 } 24 }
2、FileOutputStream
构造方法:
常用方法:
代码实例:
代码1(常用方法的简单举例):
1 package InputOutput; 2 3 import java.io.File; 4 import java.io.FileDescriptor; 5 import java.io.FileOutputStream; 6 import java.nio.channels.FileChannel; 7 8 public class FileOutputStreamDemo { 9 public static void main(String[] args) throws Exception { 10 // 指定文件路径 11 String parentPath = "E:\JavaCodeDemo\InputOutput\FileXXXStream"; 12 // 创建File对象 13 File file = new File(parentPath, "Output.txt"); 14 // 创建输出对象 15 FileOutputStream out = new FileOutputStream(file); 16 // 返回与此流相关联的文件描述符。 17 FileDescriptor des = out.getFD(); 18 System.out.println(des); 19 // 返回与此文件输出流相关联的唯一的FileChannel对象。 20 FileChannel cha = out.getChannel(); 21 System.out.println(cha); 22 // 调用方法进行给文件写数据 23 // 将指定的字节写入此文件输出流。 24 // out.write('a'); 25 // 将 b.length字节从指定的字节数组写入此文件输出流。 26 // byte[] b = { 'a', 'b', 'c', 'd', 'e' }; 27 // out.write(b); 28 // 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。 29 byte[] b = { 'a', 'b', 'c', 'd', 'e' }; 30 out.write(b, 0, 2); 31 // 刷新,将数据写入到文件 32 out.flush(); 33 // 关闭资源 34 out.close(); 35 } 36 }
代码2(文本末尾添加数据):
1 package InputOutput; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 6 public class FileOutputStreamDemo2 { 7 public static void main(String[] args) throws Exception { 8 // 指定文件路径 9 String parentPath = "E:\JavaCodeDemo\InputOutput\FileXXXStream"; 10 // 创建File对象 11 File file = new File(parentPath, "Output.txt"); 12 // 创建输出对象,文本末尾添加 13 FileOutputStream out = new FileOutputStream(file,true); 14 for (int i = 0; i < 6; i++) { 15 // 用String的getBytes()方法,字符转换为byte 16 out.write(("中文" + i).getBytes()); 17 } 18 // 刷新,将数据写入到文件 19 out.flush(); 20 // 关闭资源 21 out.close(); 22 } 23 }
注意:此操纵的基础是字节,所以在写数据的时候如果是字符串则需要用getBytes()方法转换为byte数组!
3、字节流实现图片复制:
1 package InputOutput; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 public class IOStreamCopy { 9 public static void main(String[] args) throws IOException { 10 // 指定读取文件得位置 11 String parentPath = "E:/JavaCodeDemo/InputOutput/FileXXXStream/Reader"; 12 // 创建读取得File 13 File fileIn = new File(parentPath, "Ace.jpg"); 14 // 创建字节读取流 15 FileInputStream in = new FileInputStream(fileIn); 16 // 指定写入文件得位置 17 String filePath = "E:/JavaCodeDemo/InputOutput/FileXXXStream/Writer"; 18 // 创建写入得File 19 File fileOut = new File(filePath, "ASCE.jpg"); 20 // 创建字节写入流 21 FileOutputStream out = new FileOutputStream(fileOut); 22 // 调用方法读取数据 23 int flag = -1; 24 byte[] b = new byte[1024]; 25 while ((flag = in.read(b)) != -1) { 26 // 调用方法写数据 27 out.write(b, 0, flag); 28 out.flush(); 29 } 30 // 关闭资源 31 out.close(); 32 in.close(); 33 } 34 }
结果:
如果只是写入文本文件则推荐用字符流,字符流实现文本的复制性能比较高!
调用方法System.lineSeparator()识别操作系统的换行符,只可用于文本文件,其他文件可能会破坏文件!(如果此方法报错请检查JDK版本,1.7之前的版本可能不兼容此方法)
1 String lineSeparator = System.lineSeparator(); 2 while ((flag = in.read(b)) != -1) { 3 out.write(b, 0, flag); 4 out.write(lineSeparator.getBytes()); 5 out.flush(); 6 }