异常处理:
流对象一般会抛出异常,在try的外面进行对象的创建;在try内进行对象引用。
IO流用来处理数据设备之间的数据传输;Java对数据的操作是通过流的方式;Java用于操作流的对象都在IO包中;
流按操作数据分为两种:字节流与字符流;
流按流向分为两种: 输入流(读取内存),输出流(写入外设);
字节流的抽象基类:InputStream,OutputStream。
字符流的抽象基类:Reader,Writer。
数据是以(二进制)字节形式存在的。字节流可以处理所有对象。
字符流其实就是字节流+编码表;如果要操作文字数据,优先考虑字符流。
一、 IO流:
字节流的抽象基类:InputStream , OutputStream;
字符流的抽象基类:Reader,Writer.
这些体系中大多的子类都以父类名做后缀,子类名的前缀就是该对象的功能
二、 IO字符流:
1.字节流操作中文数据不是特别的方便,所以就出现了转换流。
转换流的作用就是把字节流转换字符流来使用。
2.转换流其实是一个字符流
字符流 = 字节流 + 编码表
字节流的抽象基类:InputStream,OutputStream。
字符流的抽象基类:Reader,Writer。
3.编码表
A:就是由字符和对应的数值组成的一张表
B:常见的编码表
ASCII
ISO-8859-1
GB2312
GBK
GB18030
UTF-8
C:字符串中的编码问题
编码
String -- byte[]
解码
byte[] -- String
4.体系
Reader
|--InputStreamReader
|--FileReader
|--BufferedReader
Writer
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
Writer
FileWriter
FileWriter往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖
FileWriter类中常用方法。
刷新数据flush( ); 返回值为void
关闭数据流 close();返回值为void;
此方法在关闭流资源之前会先调用flush方法刷新再关闭;与flush方法比较:flush可以用多次,但是close方法只能用一次
写入数据 write();返回值为void
续写数据 在构造函数中加入true 可以实现续写;FileWriter(String FileName,boolean true)
读取数据 read();有重载方法,有多种返回类型
Reader
FileReader
FileReader:读取字符数据的流对象,在创建读取对象时,必须要明确被读取的文件,一定要确定该文件是存在的。
字符流缓冲区:缓冲区的出现提高了对数据的读写效率。缓冲区要结合流才可以使用。在流的基础上对流的功能进行了增强,(虽然也可以自定义缓冲区)。这样可以使用字符流缓冲区对外提供的方法。
类BufferedWriter BufferedReade
BufferedWriter
BufferedReader
LineNumberReader
BufferedReader类常用方法:
read( ) 读取数据进缓冲区:可读取 字符型数据;数组数据;换行标记
readLine()读取一个行;返回值类型String
此方法使用读取缓冲区的read方法,将读取的字符进行缓冲并判断换行标记。将标记前的缓冲数据变成字符串返回。
三、IO流字节流
字节流与字符流相比而言,处理的数据单元不同;操作的数据文件格式不同,字符流只能操作文本文件,而字节流可以操作媒体文件。
字节流基类InputStream , OutputStream;
IO字符流常用子类:
InputStream
FileInputStream
FileInputStream:往一个文件中写入文字数据;如果文件不存在,则会自动创建;如果存在文件则会覆盖FileInputStream类中常用方法。
获取字节的个数available()返回int
关闭字节流close( ); 返回值为void
关于编解码:编码——看的懂的转换为看不懂的;解码——把看不懂的转换为看得懂的。
四:不同的流
数据操作流(操作基本类型数据的流)
(1)可以操作基本类型的数据
(2)流对象名称
DataInputStream
DataOutputStream
内存操作流(理解)
(1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
(2)三种
A:ByteArrayInputStream,ByteArrayOutputStream
B:CharArrayReader,CharArrayWriter
C:StringReader,StringWriter
打印流
(1)字节打印流,字符打印流
(2)特点:
A:只操作目的地,不操作数据源
B:可以操作任意类型的数据
C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
D:可以直接操作文件
问题:哪些流可以直接操作文件呢?
看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(3)复制文本文件
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true);
String line = null;
while((line=br.readLine())!=null) {
pw.println(line);
}
pw.close();
br.close();
标准输入输出流
(1)System类下面有这样的两个字段
in 标准输入流
out 标准输出流
(2)三种键盘录入方式
A:main方法的args接收参数
B:System.in通过BufferedReader进行包装
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
C:Scanner
Scanner sc = new Scanner(System.in);
(3)输出语句的原理和如何使用字符流输出数据
A:原理
System.out.println("helloworld");
PrintStream ps = System.out;
ps.println("helloworld");
B:把System.out用字符缓冲流包装一下使用
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
随机访问流
(1)可以按照文件指针的位置写数据和读数据。
(2)案例:
A:写数据
B:读数据
C:获取和改变文件指针的位置
合并流
(1)把多个输入流的数据写到一个输出流中。
(2)构造方法:
A:SequenceInputStream(InputStream s1, InputStream s2)
B:SequenceInputStream(Enumeration<? extends InputStream> e)
序列化流
(1)可以把对象写入文本文件或者在网络中传输
(2)如何实现序列化呢?
让被序列化的对象所属类实现序列化接口。
该接口是一个标记接口。没有功能需要实现。
------------------------------------------------------------------------------------------------------------------------------------------------
练习:
1、把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中?
代码:
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter
*/
public class CopyDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"a.txt"));
// 封装目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"b.txt"));
// 读写数据
// 方式1
// int ch = 0;
// while ((ch = isr.read()) != -1) {
// osw.write(ch);
// }
// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
osw.write(chs, 0, len);
// osw.flush();
}
// 释放资源
osw.close();
isr.close();
}
}
2:复制文本文件(五种方式总结)?
代码:
package IO;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 复制文本文件
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字符流更方便一些。
* 而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。
* 数据源:
* E:\\a.txt -- FileReader -- BufferdReader
* 目的地:
* F:\\b.txt -- FileWriter -- BufferedWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
String srcString = "E:\\a.txt";
String destString = "F:\\b.txt";
method5(srcString, destString);
}
// 字符缓冲流一次读写一个字符串
private static void method5(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
// 字符缓冲流一次读写一个字符数组
private static void method4(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
}
bw.close();
br.close();
}
// 字符缓冲流一次读写一个字符
private static void method3(String srcString, String destString)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(srcString));
BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
int ch = 0;
while ((ch = br.read()) != -1) {
bw.write(ch);
}
bw.close();
br.close();
}
// 基本字符流一次读写一个字符数组
private static void method2(String srcString, String destString)
throws IOException {
FileReader fr = new FileReader(srcString);
FileWriter fw = new FileWriter(destString);
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
}
fw.close();
fr.close();
}
// 基本字符流一次读写一个字符
private static void method1(String srcString, String destString)
throws IOException {
FileReader fr = new FileReader(srcString);
FileWriter fw = new FileWriter(destString);
int ch = 0;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
fw.close();
fr.close();
}
}
3.复制图片(四种方式)?
代码:
package IO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 复制图片
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字节流。
* 而字节流有4种方式,所以做这个题目我们有4种方式。第4种比较好。
*
* 数据源:
* E:\\a.jpg -- FileInputStream -- BufferedInputStream
* 目的地:
* F:\\b.jpg -- FileOutputStream -- BufferedOutputStream
*/
public class CopyImageDemo {
public static void main(String[] args) throws IOException {
// 使用File对象做为参数
File srcFile = new File("E:\\a.jpg");
File destFile = new File("F:\\b.jpg");
method4(srcFile, destFile);
}
// 字节缓冲流一次读写一个字节数组
private static void method4(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
// 字节缓冲流一次读写一个字节
private static void method3(File srcFile, File destFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bos.close();
bis.close();
}
// 基本字节流一次读写一个字节数组
private static void method2(File srcFile, File destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fos.close();
fis.close();
}
// 基本字节流一次读写一个字节
private static void method1(File srcFile, File destFile) throws IOException {
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}
4.复制多级文件夹
代码:
package IO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 需求:复制多极文件夹
*
* 数据源:E:\\java\\duoji\\ddd
* 目的地:E:\\
*
* 分析:
* A:封装数据源File
* B:封装目的地File
* C:判断该File是文件夹还是文件
* a:是文件夹
* 就在目的地目录下创建该文件夹
* 获取该File对象下的所有文件或者文件夹File对象
* 遍历得到每一个File对象
* 回到C
* b:是文件
* 就复制(字节流)
*/
public class CopyFoldersDemo {
public static void main(String[] args) throws IOException {
// 封装数据源File
File srcFile = new File("E:\\java\\duoji\\ddd");
// 封装目的地File
File destFile = new File("E:\\");
// 复制文件夹的功能
copyFolder(srcFile, destFile);
}
private static void copyFolder(File srcFile, File destFile)
throws IOException {
// 判断该File是文件夹还是文件
if (srcFile.isDirectory()) {
// 文件夹
File newFolder = new File(destFile, srcFile.getName());
newFolder.mkdir();
// 获取该File对象下的所有文件或者文件夹File对象
File[] fileArray = srcFile.listFiles();
for (File file : fileArray) {
copyFolder(file, newFolder);
}
} else {
// 文件
File newFile = new File(destFile, srcFile.getName());
copyFile(srcFile, newFile);
}
}
private static void copyFile(File srcFile, File newFile) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(newFile));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}