本文有些内容转载自:
赵彦军博客
目录
JavaIO流结构:
什么是IO
- 其实I/O的解释有很多,这里主要讲的I/O 是 Input/Output 的缩写, I/O 技术是非常实用的技术,List item用于处理设备之间的数据传输 。 如 读 写文件,网络通讯等。
- Java 程序中,对于数据的输入 输出操作 以 “流 stream 的方式进行。
- java.io 包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法 输入或输出数据。
流的分类
- 根据处理数据类型的不同分为:字符流和字节流。
- 根据数据流向不同分为:输入流和输出流。
字符流与字节流
- 字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点.
- 所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列.
- 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 2.字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。
输入流与输出流
- 按对象分别:若将数据传到程序则为输入流,从程序输出到数据即为输出流,看上图。
四个重要基类:
- InputStream 字节输入流
- OutputStream 字节输出流
- Reader 字符输入流
- Writer 字符输出流
节点流与处理流
节点流:直接从数据源或目的地读写数据
常用的节点流
-
父 类 :InputStream 、OutputStream、 Reader、 Writer
-
文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
-
数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
-
字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
常用的处理流
- 缓冲流:BufferedInputStrean 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
- 转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
- 数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。
转换流
- InputStreamReader 、OutputStreamWriter 要InputStream或OutputStream作为参数,实现从字节流到字符流的转换
在实际例子中先介绍java.io.File类
- 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
File类常用的构造器与方法
iO流实例用法
1.首先造流
2. 读入或写出
3. 关流
必须掌握:节点流的文件复制演示
字节流Demo:
@Test
public void testFileInputOutputStream() {
//1.造流
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//用File类读入文件
File srcFile = new File("xxx.jpg");
File destFile = new File("xxx2.jpg");
//将文件放入流中
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
//复制的过程
byte[] buffer = new byte[5];
int len;
while((len = fis.read(buffer)) != -1){
fos.write(buffer,0,len);//写出文件
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null){
//关流
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
必须掌握:使用缓冲流加速视频复制效果,这里我写成了方法:
- 为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
//实现文件复制的方法
public void copyFileWithBuffered(String srcPath,String destPath){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.造文件
File srcFile = new File(srcPath);
File destFile = new File(destPath);
//2.造流
//2.1 造节点流
FileInputStream fis = new FileInputStream((srcFile));
FileOutputStream fos = new FileOutputStream(destFile);
//2.2 造缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3.复制的细节:读取、写入
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.资源关闭
if(bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCopyFileWithBuffered(){
long start = System.currentTimeMillis();
String srcPath = "C:\\Users\\Administrator\\Desktop\\01-视频.avi";
String destPath = "C:\\Users\\Administrator\\Desktop\\03-视频.avi";
copyFileWithBuffered(srcPath,destPath);
long end = System.currentTimeMillis();
System.out.println("复制操作花费的时间为:" + (end - start));//618 - 176
}
必须掌握:转换流演示实现字节流转向字符流:
将UTF-8格式转换为gbk格式
@Test
public void test2() {
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
//1.造文件、造流
File file1 = new File("dbcp.txt");
File file2 = new File("dbcp_gbk.txt");
//造字节流
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
isr = new InputStreamReader(fis, "utf-8");
osw = new OutputStreamWriter(fos, "gbk");
//2.读写过程
char[] cbuf = new char[20];
int len;
while ((len = isr.read(cbuf)) != -1) {
osw.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.关闭资源
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
必须掌握:对象流演示,序列化时注明序列号!
- 作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
序列化机制:
- 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种
- 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
- 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
//序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
// 使用ObjectOutputStream实现
@Test
public void testObjectOutputStream(){
ObjectOutputStream oos = null;
try {
//1.
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
//2.
oos.writeObject(new String("我爱中国"));
oos.flush();//刷新操作
} catch (IOException e) {
e.printStackTrace();
} finally {
if(oos != null){
//3.
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
反序列化:将磁盘文件中的对象还原为内存中的一个java对象
使用ObjectInputStream来实现
*/
@Test
public void testObjectInputStream(){
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.dat"));
Object obj = ois.readObject();
String str = (String) obj;
System.out.println(str);//我爱中国
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
最后:
知识是分享的,小白想与大家学习,若文章不好,请大佬指点!
喜欢我的话可以关注公众号:小白编码。
本文有些内容有些转载于:赵彦军