主要内容
1.编码问题
2.File类的使用
3.RandomAccessFile的使用
4.I/O 输入输出流
编码问题:
View Code
File类的使用:
JAVA.io.File类用于表示文件(目录)
File类只用于表示文件( 目录)的信息(名称、大小等),不能用于文件内容的访问
File类的常用API:
1.创建File对象:File file=new File(String path);注意:File.seperater();获取系统分隔符,如:”\“.
2.boolean file.exists();是否存在.
3.file.mkdir();或者file.mkdirs();创建目录或多级目录。
4.file.isDirectory()或者file.isFile()判断是否是目录或者是否是文件。
5.file.delete();删除文件或目录。
6.file.createNewFile();创建新文件。
7.file.getName()获取文件名称或目录绝对路径。
8.file.getAbsolutePath()获取绝对路径。
9.file.getParent();获取父级绝对路径。
10.file.getSize();获取文件大小。
11.file.getFormat();获取文件格式名。
FileDemo
遍历目录
FileUtils
RandomAccessFile的使用
RandomAccessFile JAVA提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile支持随机访问文件,可以访问文件的任意位置
(1)JAVA文件模型
在硬盘上的文件是byte byte byte存储的,是数据的集合
(2)打开文件
有两种模式"rw"(读写) "r"(只读)
RandomAccessFile raf = new RandomeAccessFile(file,"rw")
文件指针,打开文件时指针在开头 pointer = 0;
(3) 写方法
raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
提供和很多方法能够一次读写一个基本类型的数据
(4)读方法
int b = raf.read()--->读一个字节
(5)文件读写完成以后一定要关闭(Oracle官方说明)
RafDemo
RafReadDemo
序列化与基本类型序列化
1)将类型int 转换成byte或将其他数据类型转换成byte的过程叫序列化
数据---->n byte
2)反序列化
将n个byte 转换成一个数据的过程
nbyte ---> 数据
3)RandomAccessFile提供基本类型的读写方法,可以将基本类型数据
序列化到文件或者将文件内容反序列化为数据
RandomAccessFileSeriaDemo
I/O 输入输出流
流的定义:
流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。
这根用于数据传输的管道就是流,流就是一根管道
输入时,程序在源(文件,网络,内存)上打开一个流,然后如图一个一个顺序读。写也一样。
流的分类和使用:
四大基本抽象流,文件流,缓冲流,转换流,数据流,Print流,Object流。
JAVA.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同角度对其进行分类:
*按数据流的方向不用可以分为输入流和输出流
*按处理数据单位不同可以分为字节流和字符流
*按照功能不同可以分为节点流和处理流
JAVA中所提供的的所有流类型位于包JAVA.io内,都分别继承自以下四种抽象流类型:
节点流与处理流:
节点流可以从一个特定的数据源(节点)读取数据(如:文件,内存)
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
节点流也叫原始流,处理流也叫包裹流。
流与类的关系:
如果一个类是用作设备和程序之间的数据传输,则这个类有一个新的名字叫做流
流一定是类,但类不一定是流
四大基本流的介绍
输入流,输出流,字节流,字符流
InputStream和OutputStream读写数据的单位是一个字节
Reader和Writer读写数据的单位是一个字符
在JAVA中一个字符占两个字节
InputStream,OutputStream,Reader,Writer都是抽象类,或者说都是抽象流,通常我们使用的都是它们的子类,凡是以Stream结尾的都是字节流。
InputStream 流中的常用方法:
OutputStream 流中的常用方法:
Reader 流中的常用方法:
Writer 流中的常用方法:
文件流
文件流包括:
FileInputStream FileOutputStream --字节流
FileReader FileWriter --字符流
实例:读取一个文件的内容并将其输出到显示器上,并统计读取的字节个数
View Code
FileInputStream的使用
FileReader的使用
字节流与字符流的区别:
FileInputStream 和FileOutputStream 可以完成所有格式文件的复制
FileReader和FileWriter只可以完成文本文件的复制,却无法完成其他格式文件的复制
因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题
字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据
实例:编程实现文件的复制
TestFileInputStreamOutputStreamCopy
TestFileReaderWriterCopy
缓冲流
缓冲流就是带有缓冲区的输入输出流
缓冲流可以显著的减少我们对IO访问的次数,保护我们的硬盘
缓冲流本事就是处理流(包裹流),缓冲流必须得依附于节点流(原始流)
处理流包裹在原始节点流上的流,相当于包裹在管道上的管道
缓冲流要"套接"在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。JAVA提供了四种缓冲流,其常用的构造方法为:
BufferedOutputStream 和 BufferedInputStream
BufferedOutputStream :带有缓冲的输出流,允许一次向硬盘写入多个字节的数据。
BufferedInputStream:带缓冲的输入流,允许一次向程序中读入多个字节的数据。
BufferedOutputStream 和 BufferedInputStream都是包裹流,必须依附于OutputStream和InputStream
例子:利用BufferedOutputStream 和 BufferedInputStream 完成大容量文件的复制,这远比单纯利用FileInputStream和FileOutputStream要快的多
TestBufferedInputStreamOutputStreamCopy
TestBufferedInputStreamOutputStreamCopy_2
一定要注意,bis.read(buf,0,1024);这不是从buf中读数据,而是从bis所关联到的“D:\\综艺\\电影\\猫和老鼠\\CD4.rmvb”文件中读取数据,并将读取的数据写入bis自己的默认缓冲区中,然后再将缓冲区的内容写入buf数组中,每次最多向buf数组中写入1024个字节,返回实际写入buf数组的字节个数,如果读到了文件的末尾,无法再向buf数组中写入数据,则返回-1
BufferedInputStream流中有public int read(byte[] b)方法用来把从当前流关联到的设备中读取出来的数据存入一个byte数组中
BufferedOutputStream 流中有public int write(byte[] b)方法用来把byte数组中的数据输出来当前流所关联到的设备中
如果我们希望用BufferedInputStream 和 BufferedOutputStream 完成“将一个设备中的数据导入另一个设备中”,我们就应该定义一个临时的byte类型的数据,用这个临时数组作为输入流和输出流进行交互的中转枢纽。
BufferedReader 和 BufferedWriter
实例:利用BufferedReader 和 BufferedWriter完成文本文件的复制
TestBufferedReaderWriterCopy
数据流DataInputStream DataOutputStream
DataInputStream能够以一种与机器无关的方式,直接从底层字节输入流读取JAVA基本类型和String类型的数据。常用方法包括:
DataInputStream 是包裹流,必须依附于InputStream
DataOutputStream能够以一种机器无关的方式,直接将JAVA基本类型和String类型数据写出到其他的字节输出流。常用方法包括:
DataOutputStream 是包裹流,它必须依附于OutputStream
数据流实例:
编程实现将long类型数据写入byte数组,然后再从byte数组中吧该数据读出来{
*这是Socket编程中经常要完成的功能。
*因为网络编程中经常要把数据存入byte数组中,然后把byte数组打包成数据包(DatagramPacket),再把数据包经过网络传输到目的机,目的机再从byte数组中把原数值型数据还原回来。
}
本程序要使用到:
DataInputStream
DataOutputStream
ByteArrayInputStream
ByteArrayOutputStream
TestByteArrayOutputStream1
TestByteArrayOutputStream2
转换流:OutputStreamWriter InputStreamReader
OutputStreamWriter 流是把OutputStream流 转化成Writer流的流
InputStreamReader 流是把InputStream流转化为Reader
OutputStreamWriter 和 InputStreamReader都是包裹流
实例:如何将键盘输入的字符组成字符串直接赋给String对象。
TestStringInput
readLine()与回车符的问题:
Print流 PrintWriter PrintStream
Print 流只有输出,没有输入
分类:
PrintWriter输入字符
PrintStream输出字符
PrintWriter在OutputStream基础之上提供了增强的功能,既可以方便地输出各种类型数据(而不仅限于byte型)的格式化表示形式。
PrintStream重载了print和println方法,用于各种不同类型数据的格式化输出。
格式化输出是指将一个数据用其字符串格式输出。
DataOutputStream 中的 WriteXXX(data)方法是把data在内存中的二进制数据写入文件
PrintStream 中的println(data)是该数据格式化后的字符串写入文件
TestPrintStream_1
PrintWriter 提供了PrintStream的所有打印方法, 其方法也从不抛出IOException。
与PrintStream的区别:
标准输入输出的重定向:
实例:编程实现将键盘输入的数据输入A文件中,如果输入有误,则把出错信息输出到B文件
TestSetSystemOut
TestSetOutErr
对象的序列化 ObjectOutputStream ObjectInputStream
所谓序列化是指:把一个Object对象直接转化为字节流,然后把这个字节流直接写入本地硬盘或网络中
序列化流(ObjectOutputStream)----writeObject
反序列化流(ObjectInputStream)---readObject
如果想把某个对象序列化,则必须实现Serializable接口
transient关键字用用它修饰变量后该变量不会进行jvm默认的序列化
当我们要把一个对象在网络上传输转化成字节序列,我们有些变量没必要使用,放在网络上传输会浪费资源,这个时候我们就会用transient关键字
transient修饰的属性我们可以自己完成序列化
transient关键字在有些情况下可以提高性能
实例:
TestObjectIO
分析ArrayList源码中序列化和反序列化的问题
ArrayList的底层虽然是一个数组,但是这个数组不一定放满,没有放满的数组元素是不需要进行序列化的,我们必须自己完成序列化,把有效元素一个一个自己完成序列化 ,反序列化也一样,所以ArrayList源码中的序列化和反序列化的作用就是把ArrayList中的有效元素进行序列化 无效元素不进行序列化,可以提高性能。
对ArrayList的源码有个初步的了解,能够进行序列化的优化问题
序列化中 子类和父类构造函数的调用问题
当一个子类的父类实现了序列化接口,子类可以直接进行序列化 ,子类序列化时会递归调用父类的构造方法。
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造方法会被调用