------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一,A.字节流:
1.输出流:OutputStream(抽象类)
|--FileOutputStream(类)
2.输入流:InputStream(抽象类)
B.字符流:
1.输出流:Writer(抽象的)
2.输入流:Reader(抽象的)
二,FileOutputStream的构造方法:
构造方法;
FileOutputStream(String name):使用一个文件名构造一个输出流
FileOutputStream(File file):使用一个File构造一个输出流:
三,使用FileOutputStream向文件写入数据:
成员方法:
public void write(int b):写入一个int
public void write(byte[] b):写入一个byte数组(重点掌握)(使用String类的getBytes()获取byte[]数组)
public void write(byte[] b,int off,int len):写入一个byte数组中从off开始,len个长度(重点掌握)
public void close():关闭流:
四, 换行符和追加写入:
1.换行符:Windows:\r\n
Linux : \r
Mac : \n
2.追加写入:使用FileOutputStream的其它构造方法:
public FileOutputStream(String name, boolean append):append如果为true,则追加写入
public FileOutputStream(File file, boolean append):
五,输入流:InputStream(抽象类):
子类:
FileInputStream(类):
构造方法:文件必须存在,如果不存在,则抛出异常:java.io.FileNotFoundException
FileInputStream(File file)
FileInputStream(String name)
读取方法:
public int read():一次读取一个字节
public int read(byte[] b):一次读取一个字节数组填充到参数数组b中(例子放在后面:见标题)
复制文本代码:
将项目目录下的output2.txt复制到项目目录的output2_copy.txt
步骤:
1.从output2.txt中读取数据:FileInputStream
2.一次读取一个字节
3.向output2_copy.txt中写入数据:FileOutputStream
int read():返回值就是读取的字节
int read(byte[] byteArray):一次读取一个字节数组
七,带缓冲的字节流:
1.之前我们看到,使用byte[]数组,可以大大的提高"复制文件的速度",就是由于数组作为一个"缓冲区"使用,一次读取的数据
可以一次填充到一个byte[]数组中,然后一次写入,这样可以大大提高效率;
2.Java中给我另外提供了两个"带缓冲的输入流/输出流",它们可以利用内部的"缓冲区",大大的提高读写效率:
3.带缓冲区的输出流:BufferedOutputStream:该类实现缓冲的输出流。
带缓冲区的输入流:BufferedInputStream:该类实现缓冲的输入流:
4.输出流的构造方法:
BufferedOutputStream:都是带一个字节输出流:只要是OutputStream的子类都可以,我们学过:FileOutputStream;
BufferedOutputStream只提供了"缓冲区",内部写入,仍然使用参数传递的FileOutputStream对象实现:
|--BufferedOutputStream(OutputStream out) :创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
|--BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
--输出流的写入的方法:它没有特有的写入方法,使用父类的即可
八,带缓冲的输入流:BufferedInputStream:
构造方法:参数使用:FileInputStream
BufferedInputStream(InputStream in) : 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferedInputStream(InputStream in, int size) : 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
没有特有的"读取"的方法,使用父类的:
int read():读取一个字节
int read(byte[] byteArray):读取一个字节数组
九,转换流:
输出流:OutputStreamWriter:
转换流-->输出流:OutputStreamWriter:
构造方法:
public OutputStreamWriter(OutputStream out):使用一个字节输出流构造一个转换流
public OutputStreamWriter(OutputStream out,String charsetName):使用一个字节输出流,和编码方式,构造一个转换流:
写入的方法:
public void write(int c):写入一个字节;(不常用)
public void write(char[] cbuf):写入一个字符数组
public void write(char[] cbuf,int off,int len):写入一个字符数组的一部分
public void write(String str):直接写入一个字符串(最常用,也最方便)
public void write(String str,int off,int len):写入字符串的一部分:
输入流:InputStreamReader:
构造方法:
public InputStreamReader(InputStream in):使用一个字节输入流构造
public InputStreamReader(InputStream in,String charsetName):使用一个字节输入流,和一个编码方式构造;
成员方法:
public int read():读取单个字符
public int read(char[] cbuf):读取到一个字符数组cbuf,返回读取的字符的数量;
复制单级文件夹代码
需求:将D:\\aaa目录,复制到E:\\
思路:
1.封装源目录的File对象;
2.封装目标目录的File对象;
3.判断目标目录是否存在这个要复制的目录,如果没有,则创建;
4.将源目录中的所有文件获取出来:File[] listFile();
5.遍历文件数组:针对每一个文件,定义"输入流"和"输出流":统一使用带缓冲的字节流;
操作基本数据类型
DataInputStream
构造方法:
DataInputStream(InputStream in) 使用指定的底层 InputStream 创建一个 DataInputStream
DataOutputStream
构造方法:
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流
十一,打印流:
1.字节打印流:PrintStream:
2.字符打印流:PrintWriter:
打印流的特点:
1.只能操作目的地,不能操作数据(只能写入,没有读取);
2.可以操作任何类型的数据:基本数据类型,引用类型;
3.如果启动了自动刷新,内部的部分方法会带自动刷新;
4.它可以对文件进行操作:
Writer:
|--PrintWriter:
构造方法:
PrintWriter(OutputStream out) :根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。
参数:autoFlush:true:自动刷新;
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。
注意:如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
标准的输入输出流:
1.System.in:输入流:返回:InputStream类型:InputStream的子类对象的引用
2.System.out:输出流:返回:PrintStream类型(类):是OutputStream的子类
从控制台接收数据的三种方式:
1.Scanner类;
2.main()方法的形参;
3.System.in:
1).返回的InputStream(抽象类)类型;
2).返回的具体类型:BufferedInputStream:
十二,随机访问流 RandomAccessFile类:
1.它是在io包,但不属于"流",它直接继承自Object;
2.它内部包含了InputStream和OutputStream两种流,
也就意味着,此类可以对文件进行"读取"和"写入";
3.构造方法:
RandomAccessFile(File file, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode):创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
参数mode:
值 含意
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
十三,序列化流概述:
1.序列化:之前我们可以向文件中写入一些数据,可以指定编码;序列化:是可以将一个内存中的"对象"写入到一个文件中,包括这个对象中的所有属性的值。
也可以将一个对象,通过网络传输到另一台机器上。这个过程就叫:序列化;
反序列化:当将一个对象"序列化"后,我们可以将其"反序列化",将对象的信息读入到程序;例如:从一个文件中读取一个"对象的信息";从网络接收到一个
对象的信息。
2.序列化和反序列化使用的类:
1.输出流:ObjectOutputStream:序列化;
构造方法:
public ObjectOutputStream(OutputStream out):
成员方法:
public final void writeObject(Object obj):
注意:需要被序列化的类,必须实现Serializable接口。这个接口是一个"标识性"的接口,没有抽象方法。
实现此接口的类,表示可以被序列化。
2.输入流:ObjectInputStream:反序列化;
构造方法:
ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。
成员方法:
public final Object readObject():
3.注意:每个被序列化的类,都隐式的有一个属性:serialVersionUID,而且有一个默认值。
如果我们不显示定义这个属性,java会自动添加一个这个属性:
这时,如果我们将此类的对象序列化后,如果更改了类结构,这个属性的值也会随之改变,那么就与已经序列化的对象
的这个属性值不匹配了。当我们反序列化时,Java会验证这个属性值,如果不匹配,则抛出:InvalidClassException异常;
建议:在需要序列化的类中显示的定义serialVersionUID属性,并赋予一个值。如果这个值不发生变化,反序列化就不会有问题。
使用transient关键字声明不需要序列化的成员变量
十四,Properties类:
1.它不是IO流类;
2.它是Map的子类,直接继承自Hashtable;
3.它内部结合输入、输出流,可以对"配置文件"进行读写;
什么是配置文件:
1.一般软件运行时都会记录一些用户的"设置信息"、"操作信息"等一些信息,记录的目的是为了下次再启动软件时,
可以根据用户上次的设置或使用情况,来显示软件;
2.例如:QQ的登录窗体:会记录我们以往登录的所有QQ号,可以通过下拉列表快速选择;
暴风影音:播放列表:
上述的一些内容都可以记录到"配置文件"中;
3.配置文件就是一个"文本文件";
4.它内部一般以"键值对"的形式存储。
例如:游戏账户:
疲劳值=1200
金币=500
经验=5000
敏捷=20
5.上面这种键值对形式的配置文件内容,就可以使用Properties类进行方便的读写;
Properties类的使用:
Map的方法:
put(Object key ,Object value):存储元素
keySet():获取键的集合
get(Object key):通过键获取值
特有方法:
public Object setProperty(String key,String value):存储元素:相当于put()方法
public String getProperty(String key):获取元素。相当于get()方法
public Set<String> stringPropertyNames():获取所有键名。相当于keySet()方法
Properties和IO流的结合使用
public void load(Reader reader):从配置文件中读取;
public void store(Writer writer,String comments):向配置文件中写入
一,A.字节流:
1.输出流:OutputStream(抽象类)
|--FileOutputStream(类)
2.输入流:InputStream(抽象类)
B.字符流:
1.输出流:Writer(抽象的)
2.输入流:Reader(抽象的)
二,FileOutputStream的构造方法:
构造方法;
FileOutputStream(String name):使用一个文件名构造一个输出流
FileOutputStream(File file):使用一个File构造一个输出流:
三,使用FileOutputStream向文件写入数据:
成员方法:
public void write(int b):写入一个int
public void write(byte[] b):写入一个byte数组(重点掌握)(使用String类的getBytes()获取byte[]数组)
public void write(byte[] b,int off,int len):写入一个byte数组中从off开始,len个长度(重点掌握)
public void close():关闭流:
四, 换行符和追加写入:
1.换行符:Windows:\r\n
Linux : \r
Mac : \n
2.追加写入:使用FileOutputStream的其它构造方法:
public FileOutputStream(String name, boolean append):append如果为true,则追加写入
public FileOutputStream(File file, boolean append):
五,输入流:InputStream(抽象类):
子类:
FileInputStream(类):
构造方法:文件必须存在,如果不存在,则抛出异常:java.io.FileNotFoundException
FileInputStream(File file)
FileInputStream(String name)
读取方法:
public int read():一次读取一个字节
public int read(byte[] b):一次读取一个字节数组填充到参数数组b中(例子放在后面:见标题)
复制文本代码:
将项目目录下的output2.txt复制到项目目录的output2_copy.txt
步骤:
1.从output2.txt中读取数据:FileInputStream
2.一次读取一个字节
3.向output2_copy.txt中写入数据:FileOutputStream
一次输出一个字节;
public class Demo {
public static void main(String[] args) {
//1.实例化输入输出流
try{
FileInputStream in = new FileInputStream("output2.txt");
FileOutputStream out = new FileOutputStream("outptu2_copy.txt");
//一次读取一个字节:
int n = 0;
while((n = in.read()) != -1){
out.write(n);
}
//释放资源
in.close();
out.close();
System.out.println("复制完毕!");
}catch(Exception e){
}
}
}
六,FileInputStream读取数据一次一个字节数组:
int read():返回值就是读取的字节
int read(byte[] byteArray):一次读取一个字节数组
七,带缓冲的字节流:
1.之前我们看到,使用byte[]数组,可以大大的提高"复制文件的速度",就是由于数组作为一个"缓冲区"使用,一次读取的数据
可以一次填充到一个byte[]数组中,然后一次写入,这样可以大大提高效率;
2.Java中给我另外提供了两个"带缓冲的输入流/输出流",它们可以利用内部的"缓冲区",大大的提高读写效率:
3.带缓冲区的输出流:BufferedOutputStream:该类实现缓冲的输出流。
带缓冲区的输入流:BufferedInputStream:该类实现缓冲的输入流:
4.输出流的构造方法:
BufferedOutputStream:都是带一个字节输出流:只要是OutputStream的子类都可以,我们学过:FileOutputStream;
BufferedOutputStream只提供了"缓冲区",内部写入,仍然使用参数传递的FileOutputStream对象实现:
|--BufferedOutputStream(OutputStream out) :创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
|--BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
--输出流的写入的方法:它没有特有的写入方法,使用父类的即可
八,带缓冲的输入流:BufferedInputStream:
构造方法:参数使用:FileInputStream
BufferedInputStream(InputStream in) : 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferedInputStream(InputStream in, int size) : 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
没有特有的"读取"的方法,使用父类的:
int read():读取一个字节
int read(byte[] byteArray):读取一个字节数组
九,转换流:
输出流:OutputStreamWriter:
转换流-->输出流:OutputStreamWriter:
构造方法:
public OutputStreamWriter(OutputStream out):使用一个字节输出流构造一个转换流
public OutputStreamWriter(OutputStream out,String charsetName):使用一个字节输出流,和编码方式,构造一个转换流:
写入的方法:
public void write(int c):写入一个字节;(不常用)
public void write(char[] cbuf):写入一个字符数组
public void write(char[] cbuf,int off,int len):写入一个字符数组的一部分
public void write(String str):直接写入一个字符串(最常用,也最方便)
public void write(String str,int off,int len):写入字符串的一部分:
输入流:InputStreamReader:
构造方法:
public InputStreamReader(InputStream in):使用一个字节输入流构造
public InputStreamReader(InputStream in,String charsetName):使用一个字节输入流,和一个编码方式构造;
成员方法:
public int read():读取单个字符
public int read(char[] cbuf):读取到一个字符数组cbuf,返回读取的字符的数量;
复制单级文件夹代码
需求:将D:\\aaa目录,复制到E:\\
思路:
1.封装源目录的File对象;
2.封装目标目录的File对象;
3.判断目标目录是否存在这个要复制的目录,如果没有,则创建;
4.将源目录中的所有文件获取出来:File[] listFile();
5.遍历文件数组:针对每一个文件,定义"输入流"和"输出流":统一使用带缓冲的字节流;
public class Demo {
public static void main(String[] args) throws IOException{
//1.封装源目录
File srcFile = new File("D:\\aaa");
//2.封装目标目录:
File destFile = new File("E:\\");
//调用方法:
copyFile(srcFile,destFile);
System.out.println("复制完毕!");
}
private static void copyFile(File srcFile, File destFile) throws IOException{
File newFile = new File(destFile,srcFile.getName());//E:\\aaa(new File("E:\\","aaa"))
//判断目录是否存在
if(!newFile.exists()){
newFile.mkdir();//创建目录
}
//获取源目录下的所有文件
File[] fileArray = srcFile.listFiles();
for(File f : fileArray){
//针对每个文件定义输入流和输出流
BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(newFile,f.getName())));
//一次读写一个字节数组
byte[] byteArray = new byte[1024];
int n = 0;
while((n = in.read(byteArray)) != -1){
out.write(byteArray,0,n);
}
//释放资源
in.close();
out.close();
System.out.println("文件:" + f.getAbsolutePath() + " 复制完毕!");
}
}
}
十,数据输入流和数据输出流
操作基本数据类型
DataInputStream
构造方法:
DataInputStream(InputStream in) 使用指定的底层 InputStream 创建一个 DataInputStream
DataOutputStream
构造方法:
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流
十一,打印流:
1.字节打印流:PrintStream:
2.字符打印流:PrintWriter:
打印流的特点:
1.只能操作目的地,不能操作数据(只能写入,没有读取);
2.可以操作任何类型的数据:基本数据类型,引用类型;
3.如果启动了自动刷新,内部的部分方法会带自动刷新;
4.它可以对文件进行操作:
Writer:
|--PrintWriter:
构造方法:
PrintWriter(OutputStream out) :根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。
参数:autoFlush:true:自动刷新;
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。
注意:如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
标准的输入输出流:
1.System.in:输入流:返回:InputStream类型:InputStream的子类对象的引用
2.System.out:输出流:返回:PrintStream类型(类):是OutputStream的子类
从控制台接收数据的三种方式:
1.Scanner类;
2.main()方法的形参;
3.System.in:
1).返回的InputStream(抽象类)类型;
2).返回的具体类型:BufferedInputStream:
十二,随机访问流 RandomAccessFile类:
1.它是在io包,但不属于"流",它直接继承自Object;
2.它内部包含了InputStream和OutputStream两种流,
也就意味着,此类可以对文件进行"读取"和"写入";
3.构造方法:
RandomAccessFile(File file, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode):创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
参数mode:
值 含意
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
十三,序列化流概述:
1.序列化:之前我们可以向文件中写入一些数据,可以指定编码;序列化:是可以将一个内存中的"对象"写入到一个文件中,包括这个对象中的所有属性的值。
也可以将一个对象,通过网络传输到另一台机器上。这个过程就叫:序列化;
反序列化:当将一个对象"序列化"后,我们可以将其"反序列化",将对象的信息读入到程序;例如:从一个文件中读取一个"对象的信息";从网络接收到一个
对象的信息。
2.序列化和反序列化使用的类:
1.输出流:ObjectOutputStream:序列化;
构造方法:
public ObjectOutputStream(OutputStream out):
成员方法:
public final void writeObject(Object obj):
注意:需要被序列化的类,必须实现Serializable接口。这个接口是一个"标识性"的接口,没有抽象方法。
实现此接口的类,表示可以被序列化。
2.输入流:ObjectInputStream:反序列化;
构造方法:
ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。
成员方法:
public final Object readObject():
3.注意:每个被序列化的类,都隐式的有一个属性:serialVersionUID,而且有一个默认值。
如果我们不显示定义这个属性,java会自动添加一个这个属性:
这时,如果我们将此类的对象序列化后,如果更改了类结构,这个属性的值也会随之改变,那么就与已经序列化的对象
的这个属性值不匹配了。当我们反序列化时,Java会验证这个属性值,如果不匹配,则抛出:InvalidClassException异常;
建议:在需要序列化的类中显示的定义serialVersionUID属性,并赋予一个值。如果这个值不发生变化,反序列化就不会有问题。
使用transient关键字声明不需要序列化的成员变量
十四,Properties类:
1.它不是IO流类;
2.它是Map的子类,直接继承自Hashtable;
3.它内部结合输入、输出流,可以对"配置文件"进行读写;
什么是配置文件:
1.一般软件运行时都会记录一些用户的"设置信息"、"操作信息"等一些信息,记录的目的是为了下次再启动软件时,
可以根据用户上次的设置或使用情况,来显示软件;
2.例如:QQ的登录窗体:会记录我们以往登录的所有QQ号,可以通过下拉列表快速选择;
暴风影音:播放列表:
上述的一些内容都可以记录到"配置文件"中;
3.配置文件就是一个"文本文件";
4.它内部一般以"键值对"的形式存储。
例如:游戏账户:
疲劳值=1200
金币=500
经验=5000
敏捷=20
5.上面这种键值对形式的配置文件内容,就可以使用Properties类进行方便的读写;
Properties类的使用:
Map的方法:
put(Object key ,Object value):存储元素
keySet():获取键的集合
get(Object key):通过键获取值
特有方法:
public Object setProperty(String key,String value):存储元素:相当于put()方法
public String getProperty(String key):获取元素。相当于get()方法
public Set<String> stringPropertyNames():获取所有键名。相当于keySet()方法
Properties和IO流的结合使用
public void load(Reader reader):从配置文件中读取;
public void store(Writer writer,String comments):向配置文件中写入