目录
3.InputStream与OutputStream实现文件的拷贝
IO流的作用?
读写文件数据的
IO流是怎么划分的,大体分为几类,各自的作用?
字节流:字节输入流,字节输出流(读写字节数数据的)
字符流:字符输入流,字符输出流(读写字符数据的)
一、字节流
1.InputStream
read()读取文件中的字节
public static void main(String[] args) throws Exception {
InputStream input = new FileInputStream("src\\data.txt");
int r;
// read找不到下一位字节会返回-1
while ((r = input.read()) != -1) {
// 逐个读取,读取中文会乱码
// UTF-8每个汉字占三个字节
System.out.print((char) r);
}
System.out.println("\n===============================");
InputStream input2 = new FileInputStream("src\\data.txt");
//利用字节数组
byte[] buffer = new byte[3];
int len;// 记录buffer的长度
while ((len = input2.read(buffer)) != -1) {//读取中文也有可能乱码
System.out.print(new String(buffer, 0, len));
}
}
当文件较小时可以定义为文件大小,一次性读取文件内容,可以避免乱码
File f = new File("src\\data.txt");
InputStream input3 = new FileInputStream(f);
byte[] buffer1 = new byte[(int)f.length()];
//也可以用
//byte[] buffer1 = input3.readAllBytes();
//readAllbytes是JDK9出现的新方法
input3.read(buffer1);
System.out.print(new String(buffer1));
2.OutputStream
public static void main(String[] args) throws Exception {
//OutputStream os = new FileOutputStream("src\\data.txt");//当创建出来时就会清空文件内的信息
OutputStream os = new FileOutputStream("src\\data.txt", true);//在原有的数据上在末尾进行追加数据
// 写一个字节
os.write('q');
os.write(97);
// 写入字节数组
byte[] buffer1 = { 'p', 97, 98, 32 };
os.write(buffer1);
os.write("\r\n".getBytes());//换行
byte[] buffer2 = "我爱中国".getBytes();
os.write(buffer2);
os.flush();
// 写入的数据再缓存区,需要进行刷新才能进入文件
// 刷新后可以继续写入
os.close();
// 使用完需要关闭,释放资源
// close()包括flush(),关闭后不能再进行写入
3.InputStream与OutputStream实现文件的拷贝
/*
* 字节流适合一切文件的拷贝
*/
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("C:\\Users\\admin\\Desktop\\美女1.png");// 运行时文件路径可能报错,文件路径手动输入即可解决
os = new FileOutputStream("C:\\Users\\admin\\Desktop\\美女2.png");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
System.out.println("Success copy");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 从内到外关闭
try {
if (os != null) {// 防止还没有创建OutputStream就出现异常
os.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (is != null) {// 防止还没有创建InputStream就出现异常
is.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
二、字符流
1.Reader
读取单个字符(包括汉字)
public static void main(String[] args) throws Exception {
//每次读取一个字符
//创建一个字符输入流管道
Reader r = new FileReader("src/data.txt");
int len;
//每次读取一个字符返回,如果字节已经没有可读的返回-1
while ((len = r.read()) != -1) {
System.out.print((char) len);
}
}
使用字符数组读取一批字符
public static void main(String[] args) throws Exception {
//创建一个字符输入流管道
Reader r2 = new FileReader("src/data.txt");
//每次读取1024字符
char[] buffer = new char[1024];
int len2;
while ((len2 = r2.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, len2));
}
}
2.Writer
public static void main(String[] args) throws Exception {
//创建一个管道
//Writer wr = new FileWriter("src\\data.txt"); //创建时直接覆盖,没有追加
Writer wr = new FileWriter("src\\data.txt",true);//使用时向后追加
//写入单个字符
wr.write("\r\n");//换行
wr.write(97);
wr.write('a');
wr.write('嘿');
wr.write("\r\n");//换行
//写入字符数组
char[] buffer = {'a','b','c','d'};
wr.write(buffer);
//写入字符数组的一部分
wr.write(buffer, 0, 3);
//写入字符串
wr.write("撸起袖子加油干!");
//写入字符串的一部分
wr.write("我爱你中国", 0, 3);
//刷新
wr.flush();
//关闭,关闭也相当于刷新,关闭后不可以再进行写入
wr.close();
}
三、缓冲流
1.字节缓冲流
字节缓冲输入流:BufferedInputStream
字节缓冲输出流:BufferedOutputStream
可以提高InputStream和OutputStream的速度,BufferedInputStream和BufferedOutputStream自带8K的缓冲池。
public static void main(String[] args) {
//使用try(管道建立){}catch(){}格式不用再进行手动关闭
try (InputStream is = new FileInputStream("C:\\Users\\admin\\Desktop\\新建位图图像.bmp");
OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\新建位图图像2.bmp");
// 建立输入流缓冲管道
InputStream bis = new BufferedInputStream(is);
//建立输出流缓冲管道
OutputStream bos = new BufferedOutputStream(os);) {
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
2.字符缓冲流
字符缓冲输入流:BufferedReader
字符缓冲输出流:BufferedWriter
可以提高Reader和Writer的速度,BufferedReader和BufferedWriter自带8K的缓冲池。
①BufferedReader
public static void main(String[] args) {
try (Reader r = new FileReader("src\\data.txt"); BufferedReader br = new BufferedReader(r);) {
// BufferedReader可以直接按行读取,当文件没有下一行时返回null
String str;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
②BufferedWriter
public static void main(String[] args) {
//使用try(管道建立){}catch(){}格式不用再进行手动关闭
try (InputStream is = new FileInputStream("C:\\Users\\admin\\Desktop\\新建位图图像.bmp");
OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\新建位图图像2.bmp");
// 建立输入流缓冲管道
InputStream bis = new BufferedInputStream(is);
//建立输出流缓冲管道
OutputStream bos = new BufferedOutputStream(os);) {
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
四、转换流
用来解决文件与代码的编码格式不同(例:文件编码GBK,代码编码UTF-8)
1.使用字符输入转换流
可以提取文件(GBK)的原始字节流,原始字节不会存在问题。然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不乱码了
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("C:\\Users\\admin\\Desktop\\GBK编码格式.txt");
// 将字节流转换为字符流
Reader r = new InputStreamReader(is, "GBK");
BufferedReader br = new BufferedReader(r);
String str;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
r.close();
is.close();
}
2.使用UTF-8编码输出自己想要的GBK编码格式
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\新建文本文档.txt");
Writer w = new OutputStreamWriter(os,"GBK");
BufferedWriter bw = new BufferedWriter(w);
bw.write("我爱你中国");
bw.newLine();
bw.write("撸起袖子加油干");
bw.close();
}
五、序列化和反序列化
序列化以及反序列化使用ObjectOutputStream和ObjectInputStream
1.序列化
public class ObjectOutputDemo {
public static void main(String[] args) throws Exception {
//序列化
OutputStream is = new FileOutputStream("src\\student.txt");
ObjectOutputStream oos = new ObjectOutputStream(is);
student s = new student("1101","张三",18,180.5);
oos.writeObject(s);
}
}
2.反序列化
public class ObjectInputDemo {
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("src\\student.txt");
ObjectInputStream ois = new ObjectInputStream(is);
student s = (student)ois.readObject();
System.out.println(s);
}
}
学生类
public class student implements Serializable {// 序列化必须实现Serializable接口
private String id;
private String name;
private int age;
private transient double height;// transient修饰时,序列化直接忽视这个属性
public student() {
super();
}
public student(String id, String name, int age, double height) {
super();
this.id = id;
this.name = name;
this.age = age;
this.height = height;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
六、打印流
作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般是指:PrintStream,Printwriter两个类。
打印流性能高效,方便写内容到文件中。打印功能上PrintStream和Printwriter没有区别
public static void main(String[] args) throws Exception{
//打印流没法在文件末尾追加,如果想要追加,需要在低级流中定义追加
PrintStream ps = new PrintStream(new FileOutputStream("src\\Print.txt",true));
ps.println(97);
ps.println('a');
ps.println(true);
ps.println("我在学Java");
ps.close();
}
打印流重定向
public static void main(String[] args) throws Exception {
System.out.println("我是第一句");
PrintStream ps = new PrintStream(new FileOutputStream("src\\Print.txt",true));
System.setOut(ps);//接下来的所有输出语句都会流入“src\\Print.txt”文件中
System.out.println("我是第二句");
}