缓冲流
转换流
对象流
打印流
标准输入输出流
随机访问流
数组流
有关flush():所有的处理流的输出流,最外层流需要刷新。
javaIO流
1认识File类
File类的对象表示一个文件或者一个文件目录
绝对路径:包含盘符的文件完整路径
相对路径:在当前路径下的文件路径
File类中的方法,涉及到文件或文件目录的新建、删除、获取文件的路径、获取文件的大小。并没有涉及到向文件中写入或读出内容。这样的读取或写入的功能就需要IO流来完成
一般通过将File类的对象作为参数传递到流的构造器中,作为流的端点。
文件的操作
createNewFile():创建file对应的硬盘中的文件
delete():删除file对象对应的硬盘中的文件或文件目录
文件夹操作
mkDir() / mkDirs():创建文件目录.mkDir()与mkDirs()的方法的区别:当要创建的文件目录的上层目录不存在。此方法放回false,表示创建不成功。而mkDirs()会将不存在的上层文件目录一并创建
list():列举当前文件目录下的所有的子File的路径,String[]
listFiles()列举当前文件目录下的所有的子File. File[]
其他方法:
exists():判断当前文件或文件目录是否在硬盘上存在
lastModified():最后一次修改的时间
length():获取文件内容的大小,单位字节
renameTo(File newName):file1.renameTo(file2):要想返回值为true,需要保证:file1在硬盘中一定存在;file2在硬盘中一定不存在
canWrite()
canRead()
isFile()
isDirectory()
getName()
getPath()
getAbsoluteFile()
getAbsolutePath()
getParent()
java流的分类
1按照流的流向: 输入流 vs 输出流
2 按照处理数据的单位: 字节流 vs 字符流
3 按照流的角色不同: 节点流(文件流) vs 处理流
【节点流 直接连接到文件,而处理流作为节点流与程序的中介。】
二 java 流的框架结构
抽象基类
InputStream OutputStream Reader Writer
节点流(文件流)
FileInputStream FileOutputStream FileReader FileWriter
缓冲流 (处理流的一种,提高数据传输的效率)
BufferedInputStream BufferedOutputSteam
BufferedReader BufferedWriter
以文件输入流为例了解流的细节步骤:
1创建一个File类的对象,其映射着一个物理文件。【此时File类对象只是一个普通的对象,可能还没有物理文件】
File file = new File(“hello.txt”)
file.createNewFile();
2创建对应的输入流对象,将如上的File类的对象作为输入流构造器的参数(要求 :读入的物理文件一定存在。),否则报如下异常:
FileNotFoundException
FileInputStream fis = new FileInputStream(file);
3输入流的实现
byte[] buffer = new byte[10];
int len;//不是buffer.length,而是每次读入到buffer字节数组的字节数,len = fis.read(buffer)
while((len = fis.read(buffer)) != -1){//read()方法若读到文件末尾返回-1
String str = new String(buffer,0,len);
…//
}
4 流的关闭
fis.close();
注:以上只是FileInputStream流的实现步骤,在具体编写代码的时候,由于异常的存在,还需要使用try-catch-finally语句进行处理。
针对于文件输出流
1如果输出流对应的文件不存在,那么在输出的过程中,系统会自动的创建对应的文件。//此时和输入流是不一样的。
2如果输出流对应的文件存在,则输出过程是会对原有的文件进行覆盖!注意:不是对文件内容的覆盖!
字符串类型转换成字符数组:
String str = “i love java”; byt e[] buffer = str.getBytes();
字符数组转换成字符串
String str = new String(buffer,0,buffer.length);
3对于文本文件(txt)最好使用字符流
对于非文本文件(doc , jpg ,mp3,mp4 等)使用字节流
4,针对流,必须手动的关闭。
缓冲流需要注意的情况:
缓冲流需要手动的刷新,flush()方法
InputStream 和 Reader 是所有输入流的基类。
InputStream(典型实现:FileInputStream) int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
Reader(典型实现:FileReader)
int read()
int read(char [] c)
int read(char [] c, int off, int len) 程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
OutputStream 和 Writer 也非常相似: void write(int b/int c); void write(byte[] b/char[] cbuf); void write(byte[] b/char[] buff, int off, int len); void flush(); void close(); 需要先刷新,再关闭此流因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数 void write(String str); void write(String str, int off, int len);
缓冲流
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组根据数据操作单位可以把缓冲流分为: BufferedInputStream 和 BufferedOutputStream BufferedReader 和 BufferedWriter缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出。
转换流
转换流提供了在字节流和字符流之间的转换Java API提供了两个转换流: InputStreamReader和OutputStreamWriter字节流中的数据,转成字符流操作更高效。
InputStreamReader(InputStream is,Stream charset)/
charset可选项,若无,表示默认的本地编码
charset 表示字符集,用来解码输入流中的文件。用于将字节流中读取到的字节按指定字符集 解码成字符。需要和InputStream“套接”。构造方法 public InputStreamReader(InputStream in) public InputSreamReader(InputStream in,String charsetName) 如: Reader isr = new InputStreamReader(System.in,”ISO5334_1”);OutputStreamWriter用于将要写出到字符流中的字符按指定字符集编码成字节,编码过程,需要和OutputStream“套接”。构造方法 public OutputStream Writer (OutputStream out)
public OutputSream Writer (OutputStreamout,StringcharsetName) 此时的charset 表示解码到文件。
编码:字符串–>字节数组解码:字节数组–>字符串 所有的文件底层都是用字节形式保存,读入的操作属于解码,需要InputStreamReader,写出的操作属于编码,需要OutputSteamWriter类。
转换流的编码应用 可以将字符按指定编码格式存储。 可以对文本数据按指定编码格式来解读。 指定编码表的动作由构造函数完成
与标准输入输出流的配合使用:
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(reader);
br.readLine();//从键盘获取一个字符串,再利用类型转换获取其数据如char和int等。
标准输入输出流:
System.in和System.out分别代表了系统标准的输入和输出设备默认输入设备是键盘,输出设备是显示器 System.in的类型是InputStream System.out的类型是PrintStream,PrintSteam是OutputStream的子类
通过System类的setIn,setOut方法对默认设备进行改变。 public static void setIn(InputStream in) public static void setOut(PrintStream out)Scanner scanner = new Scanner(System.in);
打印流
实现将基本数据类型的数据格式转化为字符串输出打印流:PrintStream和PrintWriter提供了一系列重载的print和println方法,用于多种数据类型的输出 PrintStream和PrintWriter的输出不会抛出异常 PrintStream和PrintWriter有自动flush功能 System.out返回的是PrintStream的实例
PrintStream stream =
new PrintStream(new FileOutputStream(new File(“hello.txt”)),true);
System.setOut(PrintStream stream);
数据流
为了方便地操作Java语言的基本数据类型的数据,可以使用数据流。数据流有两个类:(用于读取和写出基本数据类型的数据) DataInputStream 和 DataOutputStream分别“套接”在 InputStream 和 OutputStream 节点流上DataInputStream中的方法 boolean readBoolean() byte readByte() char readChar() float readFloat() double readDouble() short readShort() long readLong() int readInt() String readUTF() void readFully(byte[] b)DataOutputStream的方法将上述的方法的read改为相应的write即可。1.作用:保存或读取基本数据类型、String、byte[]字节数组
2.DataInputStream 和 DataOutputStream
DataInputStream dis =
new DataInputStream(new FileInputStream(new File(“data.dat”)));
DataOutputStream dos =
new DataOutputStream(new FileOutputStream(new File(“data.dat”)));
dos.writeXxx(Xxx xxx); dos.writeUTF(String str);
对象流
ObjectInputStream和OjbectOutputSteam:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。java对象的可序列化机制:
允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,
或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制ObjectOutputStream和ObjectInputStream不能序列化
static和transient修饰的成员变量。
当我们使用对象流读入或者写出的时候,需要保证对象是序列化的,这是为了保证能把对象写入到文件,并能再把对象正确读回到程序中。java提供的绝大多数类都是序列化的。
如果一个类实现了Serializable 接口,那么实现该接口的类不需要实现额外的方法。但是该类需要一个私有的静态的常量long类型。
private static final long serialID = 2233445555L;
java虚拟机会实现Serializable接口中的方法,按照一定格式的文本将对象写入到目的地,需要注意的是,使用对象流写入到文件时,不仅保证该对象是序列化的,而且该对象的成员对象也必须是序列化的。
利用对象流实现对象的克隆
背景:如果两个对象有相同的引用,那么他们就具有相同的实体和功能。
有时候我们想得到对象的一个复制品,该复制品是原对象实体的拷贝,复制品实体的变化不会同步到原对象实体。对象调用clone()方法可以获取对象的复制品,称为原对象的克隆对象。
对象进行克隆的时候需要注意一点:如果原对象有引用型成员变量,那么克隆对象的成员变量的引用就与原对象那个成员变量的引用相同,由于引用相同,那么克隆对象的成员变量的变化就会同步到原对象的成员变量中,程序必须重写clone()方法,这无疑增大了编程的难度。
使用对象流很容易获取一个序列化对象的克隆,我们只需要将该对象写入到对象输出流,然后调用对象输入流读回对象,得到一个对象的克隆,而且没有如上的问题。
随机访问流
RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件 支持只访问文件的部分内容 可以向已存在的文件后追加内容理解:
RandomAccessFile ,随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针。
int length();返回文件的长度
RandomAccessFile 类对象可以自由移动记录指针: long getFilePointer():获取文件记录指针的当前位置 void seek(long pos):将文件记录指针定位到 pos 位置构造器 public RandomAccessFile(File file, String mode) public RandomAccessFile(String name, String mode)创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指定 RandomAccessFile 的访问模式: r: 以只读方式打开 rw:打开以便读取和写入 rwd:打开以便读取和写入;同步文件内容的更新 rws:打开以便读取和写入;同步文件内容和元数据的更新 public String readLine();读取文本的下一行,文件指针先下移,后读取。不支持完整的Unicode字符集。
public final void wirteUTF(String str) 使用UTF-8的字符编码将字符串写入文件。
随机存取文件流:RandomAccessFile
- 1.既可以作为一个输入流,也可以作为一个输出流
- 2.作为一个输出流,若输出到的文件不存在,则会在输出的过程中创建;若输出到的文件已经存在,则是对已存在的文件的内容的覆盖
- 3.实现数据的覆盖。(文件指针的概念,从0开始)
数组流
数组流的源和目标是计算机内存。字节数组输入流ByteArrayInputStream,和字节数组输出流 ByteArrayOutputStream,分别使用计算机内存的字节数组作为流的源和目标,同样也有字符数组的类CharArrayReader和CharArrayWriter。
注:字节数组流不会发生IO异常。
以字节数组为例分析数组流:
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] buf,int offset,int len);
在构造器参数指明 字节输入流的源
从流中读入的方法:
public int read(),从源中读入一个字节,该方法返回字节值。
public int read(byte[] buf),从源中读入字节放到参数buf中,该方法返回实际读出的字节个数。若未读出字节,返回-1
同理:字节数组输出流 ByteArrayOutputStream(),参数可选int类型的字节大小,默认为32字节的缓冲区,可自动扩容。
public void write(int b) 向内存缓冲区写出一个字节。
public void write(byte[] buf,int off,int len),将参数buf中指定个数的字节写出到内存缓冲区。
public byte[] toByteArray(),返回输出流写入到缓冲区的全部字节。
可以和对象流配合使用完美实现对象克隆。