简化流FileReader
用来读取字符文件的便捷类
继承关系
构造方法:
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。 |
---|
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader |
成员方法:
3个read方法:
package com.cskaoyan.charstream;
import java.io.FileReader;
import java.io.IOException;
/**
* @description:
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo3 {
public static void main(String[] args) throws IOException {
// 创建FileReader对象
FileReader reader = new FileReader("a.txt");
// read
//int readData = reader.read();
//System.out.println(((char) readData));
// 多个字符
char[] chars = new char[1024];
int readCount = reader.read(chars);
System.out.println(new String(chars,0,readCount));
// close
reader.close();
}
}
转换流 VS 简化流
- 使用角度上看 简化流比转化流更方便
- 继承关系上看,简化流是转化流的直接子类
- 编解码角度上看,简化流不能指定编解码,只能使用默认的编解码,对于转化流来讲 可以指定编解码(最重要的区别)
package com.cskaoyan.charstream;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @description:
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo4 {
public static void main(String[] args) throws IOException {
// 简化流读取
//read1();
// 转化流读取
InputStreamReader in =
new InputStreamReader(
new FileInputStream("aa.txt"),"gbk");
// read
char[] chars = new char[1024];
int readCount = in.read(chars);
System.out.println(new String(chars,0,readCount));
in.close();
}
private static void read1() throws IOException {
FileReader reader = new FileReader("aa.txt");
//read
char[] chars = new char[1024];
int readCount = reader.read(chars);
System.out.println(new String(chars,0,readCount));
// close
reader.close();
}
}
缓冲流BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
继承关系
构造方法
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。 |
---|
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。 |
成员方法
3个read方法 + readLine()
String | readLine() 读取一个文本行。 |
---|---|
注意 | 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null |
package com.cskaoyan.charstream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* @description: BufferedReader
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo6 {
public static void main(String[] args) throws IOException {
// 创建输入流对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// read方法读取数据
//int readData = br.read();
//System.out.println(((char) readData));
// readLine
//read1(br);
//循环读
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
// close
br.close();
}
private static void read1(BufferedReader br) throws IOException {
String s = br.readLine();
System.out.println(s);
}
}
用字符流去复制文件
文本文件
package com.cskaoyan.charstream;
import java.io.*;
/**
* @description: 复制文件
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo7 {
public static void main(String[] args) throws IOException {
// 创建输入流对象
InputStreamReader inputStreamReader =
new InputStreamReader(new FileInputStream("a.txt"));
// 创建输出流对象
OutputStreamWriter out =
new OutputStreamWriter(new FileOutputStream("b.txt"));
// 边读边写
int readData;
while ((readData = inputStreamReader.read()) != -1) {
out.write(readData);
}
//close
inputStreamReader.close();
out.close();
}
}
非文本文件
package com.cskaoyan.charstream;
import java.io.*;
/**
* @description: 复制文件
* @author: songtao@cskaoyan.onaliyun.com
**/
// 不能成功复制
public class Demo8 {
public static void main(String[] args) throws IOException {
// 创建输入流对象
InputStreamReader inputStreamReader =
new InputStreamReader(new FileInputStream("D:\\mm.jpg"));
// 创建输出流对象
OutputStreamWriter out =
new OutputStreamWriter(new FileOutputStream("copy_mm.jpg"));
// 边读边写
int readData;
while ((readData = inputStreamReader.read()) != -1) {
out.write(readData);
}
//close
inputStreamReader.close();
out.close();
}
}
其他流(了解)
数据流
练习:
向文件当中写入1000 , 3.14 看一下能否成功?
不能写入
DataInputStream
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型
构造方法:
DataInputStream(InputStream in)
成员方法:
每一个java基本数据类型都有1个read方法与之对应 比如 读取int readInt()
package com.cskaoyan.otherstream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @description:
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo3 {
public static void main(String[] args) throws IOException {
// 读取java中的数据类型
DataInputStream in = new DataInputStream(new FileInputStream("b.txt"));
// read
// readInt()
int i = in.readInt();
System.out.println(i);
// readDouble()
double v = in.readDouble();
System.out.println(v);
// readBoolean
boolean b = in.readBoolean();
System.out.println(b);
in.close();
}
}
DataOutputStream
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
构造方法
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流。
成员方法:
每一种java基本数据类型都有1个write方法与之对应 比如 写入int方法 writeInt(int i)
package com.cskaoyan.otherstream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @description:
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo2 {
public static void main(String[] args) throws IOException {
// 创建数据输出流对象
DataOutputStream out = new DataOutputStream(new FileOutputStream("b.txt"));
// 用不同的类型的write方法写数据
// 写1000 writeInt(int v)
out.writeInt(1000);
// 写3.14
out.writeDouble(3.14);
// true
out.writeBoolean(true);
// close
out.close();
}
}
package com.cskaoyan.otherstream;
import java.io.*;
/**
* @description:
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo4 {
public static void main(String[] args) throws IOException {
write();
read();
}
private static void read() throws FileNotFoundException, IOException {
DataInputStream dis = new DataInputStream(
new FileInputStream("dos.txt"));
byte b = dis.readByte();
System.out.println(b);
short s = dis.readShort();
System.out.println(s);
int i = dis.readInt();
System.out.println(i);
long l = dis.readLong();
System.out.println(l);
float f = dis.readFloat();
System.out.println(f);
double d = dis.readDouble();
System.out.println(d);
char ch = dis.readChar();
System.out.println(ch);
boolean bb = dis.readBoolean();
System.out.println(bb);
dis.close();
}
private static void write() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(
"dos.txt"));
dos.writeByte(1);
dos.writeShort(20);
dos.writeInt(300);
dos.writeLong(4000);
dos.writeFloat(12.34f);
dos.writeDouble(12.56);
dos.writeChar('a');
dos.writeBoolean(true);
dos.close();
}
}
注意:
按照什么样的方式去写 那么就要按照相同的方式去读取
打印流
打印流的核心思想
把不同的数据类型都转换成了字符串 写的就是字符串
练习:
定义一个类 Printer
4个方法
printInt(int i) 写int类型的数据
printIntLn(int i) 写int类型的数据 在加上换行
printDouble(double d) 写double类型的额数据到文件
printDoubleLn(double d) 写double类型的数据 再换行
package com.cskaoyan.otherstream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @description: print思想
* @author: songtao@cskaoyan.onaliyun.com
**/
/*
定义一个类 Printer
4个方法
printInt(int i) 写int类型的数据
printIntLn(int i) 写int类型的数据 在加上换行
printDouble(double d) 写double类型的额数据到文件
printDoubleLn(double d) 写double类型的数据 再换行
*/
public class Demo5 {
public static void main(String[] args) throws IOException{
Printer printer = new Printer(new FileOutputStream("a.txt"));
// 写入int 1000
printer.printIntLn(1000);
printer.printDouble(3.14);
// close
printer.close();
}
}
class Printer{
// 定义一个成员变量
OutputStream outputStream;
public Printer(OutputStream outputStream) {
this.outputStream = outputStream;
}
// 成员方法
public void printInt(int a) throws IOException {
// int 转字符串
String s = String.valueOf(a);
// 利用out去写入数据到文件当中
outputStream.write(s.getBytes());
}
public void printIntLn(int a) throws IOException {
String s = String.valueOf(a);
outputStream.write(s.getBytes());
// 再写入一个换行符
outputStream.write(System.lineSeparator().getBytes());
}
public void printDouble(double d) throws IOException {
// double → 字符串
String s = String.valueOf(d);
// write
outputStream.write(s.getBytes());
}
public void printDoubleLn(double d) throws IOException {
// double → 字符串
String s = String.valueOf(d);
// write
outputStream.write(s.getBytes());
// 换行符
outputStream.write(System.lineSeparator().getBytes());
}
public void close() throws IOException {
outputStream.close();
}
}
字节打印流PrintStream
PrintStream
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
继承关系
构造方法:
PrintStream(File file) 创建具有指定文件且不带自动行刷新的新打印流。 |
---|
PrintStream(OutputStream out) 创建新的打印流。 |
PrintStream(OutputStream out, boolean autoFlush) |
PrintStream(String fileName) 创建具有指定文件名称且不带自动行刷新的新打印流。
成员方法:
每个java数据类型都有一个print方法
package com.cskaoyan.otherstream;
import java.io.IOException;
import java.io.PrintStream;
/**
* @description: PrintStream
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo6 {
public static void main(String[] args) throws IOException {
// 创建字节打印流对象
PrintStream printStream = new PrintStream("a.txt");
// 向文件中写数据 利用相应的print方法
printStream.println(1000);
// close
printStream.close();
}
}
字符打印流PrintWriter
向文本输出流打印对象的格式化表示形式
继承关系
构造方法
PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。 |
---|
PrintWriter(OutputStream out) 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 |
PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。 |
PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。 |
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。 |
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。 |
成员方法:
各种print方法
打印流的4个特点
- 只能操作目的地,不能操作数据来源
- 没有相应的输入流与之对应
- 可以操作任意类型的数据
- 原理就是把不同类型转化为了字符串去处理
- 如果启动了自动刷新功能 就会自动刷新
-
如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区
-
为什么能够自动刷新
-
传的参数可以是文件对象 文件名
-
标准输入输出流
System.out
- 标准输出流
- 默认的输出设备 显示器
- 本质是一个字节打印流
System.in
- 标准输入流
- 默认的输入设备 键盘
- 本质是一个普通的字节输入流
练习:
利用System.in 以及 BufferedReader 模拟 Scanner 当中的nextLine方法
package com.cskaoyan.otherstream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @description: 模拟scanner
* @author: songtao@cskaoyan.onaliyun.com
**/
/*
利用System.in 以及 BufferedReader 模拟 Scanner 当中的nextLine方法
*/
public class Demo9 {
public static void main(String[] args) throws IOException {
// 创建一个BufferedReader对象
// 问题:我们需要一个Reader 字符输入流作为参数
// 能用的就是System.in 本质是一个普通的字节输入流InputStream
// 思路:字节流 字符流的桥梁就是转换流
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
// 就可以利用readLine方法了
//read1(br);
// 可以重复输入 当输入值为"gun" 结束循环
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
// 约定1个结束标记 作为结束符
if (line.equals("gun")) {
break;
}
}
// close
br.close();
}
private static void read1(BufferedReader br) throws IOException {
String s = br.readLine();
System.out.println(s);
}
}
对象流(序列化流 反序列化流)
序列化:
把对象数据转为为二进制数据 持久化存储的过程
反序列化:
把二进制数据还原为对象数据的过程
Student s = new Student("zs",20)
序列化流ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream
继承关系
构造方法:
ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。
成员方法:
void | writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 |
---|---|
package com.cskaoyan.otherstream;
import java.io.*;
/**
* @description: 序列化
* @author: songtao@cskaoyan.onaliyun.com
**/
public class Demo10 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 把学生对象信息写入文件
serialize();
// 反序列化
// 创建一个反序列流对象
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("aa.txt"));
// readObject方法
Student student = (Student) in.readObject();
System.out.println(student);
// close
in.close();
}
private static void serialize() throws IOException {
// 创建一个学生对象
Student student = new Student("张三", 20,99);
// 创建序列化流对象
ObjectOutputStream out =
new ObjectOutputStream(new FileOutputStream("aa.txt"));
// writeObject(Object obj) 写入对象信息
out.writeObject(student);
// close
out.close();
}
}
class Student implements Serializable {
// 定义成员变量
String name;
int age;
boolean gender;
// serialVersionUID 名字要一致
static final long serialVersionUID = -2898402714175754521l;
// 添加1个分数
transient int score;
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
", score=" + score +
'}';
}
}
注意:
- 要想实习序列化功能 必须要实现Serializable接口
- Serializable接口 是一个空接口 起到一个标记的作用
- 如果在Student类中添加1个成员变量 还能否正常读取
- 要使得2个serialVersionUID保持一致
- 如果类中成员变量信息 不想被序列化 这时候 使用关键字 transient
异常:
- java.io.NotSerializableException 没有实现Serializable接口
- java.io.InvalidClassException: com.cskaoyan.otherstream.Student; local class incompatible: stream classdesc serialVersionUID = -2898402714175754521, local class serialVersionUID = -1896616544424779089 类中的信息发生改变
反序列化流ObjectInputStream
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化
继承关系
构造方法
ObjectInputStream(InputStream in)
成员方法:
readObject()
总结
类型 | 字节输出流 | 字节输入流 | 字符输出流 | 字符输入流 |
---|---|---|---|---|
基类 | OutputStream | InputStream | Writer | Reader |
文件相关 | FileOutputStream | FileInputStream | FileWriter | FileReader |
缓冲流 | BufferedOutputStream | BufferedInputStream | BufferedWriter | BufferedReader |
转换流 | OutputStreamWriter | InputStreamReader | ||
数据流 | DataOutputStream | DataInputStream | ||
打印流 | PrintStream | PrintWriter | ||
对象流 | ObjectOutputStream | ObjectInputStream | ||
作业
1.利用字符流去读取一个文本文件,每次读取一行,并将这行数据逆序,写入新的文本文件当中
public class Demo01 {
public static void main(String[] args) throws IOException {
// 创建一个输入流对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 每次接收一行存为字符串,当文本中没有数据之后,得到的是null
while((line = br.readLine()) != null){
System.out.println(line);
char[] chars = line.toCharArray();
for (int i = chars.length - 1; i >= 0; i--) {
bw.write(chars[i]);
}
bw.newLine();
}
br.close();
bw.close();
}
}
2.准备一个文本文件,其中包含英文 ,数字, 中文字符。
设计一个方法
public static void encodeFile(File encodingFile, File encodedFile);
在这个方法中把encodingFile的内容进行加密,然后保存到encodedFile文件中。
加密算法:
数字:
如果不是9的数字,在原来的基础上加1,比如5变成6, 3变成4
如果是9的数字,变成0
字母字符:
如果是非z字符,向右移动一个,比如d变成e, G变成H
如果是z,z->a, Z-A。
字符需要保留大小写
非字母字符
比如',&^ 保留不变,中文也保留不变
public class Demo02 {
public static void main(String[] args) throws IOException {
File encodingFile = new File("/Users/chelsea-he/Documents/JAVA33th/testFile/encodingFile.txt");
File encodedFile = new File("/Users/chelsea-he/Documents/JAVA33th/testFile/encodedFile.txt");
encodeFile(encodingFile, encodedFile);
}
public static void encodeFile(File encodingFile, File encodedFile) throws IOException, NullPointerException{
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(encodingFile));
bw = new BufferedWriter(new FileWriter(encodedFile));
String line;
while((line = br.readLine()) != null){
char[] chars = line.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(chars[i] >= 'a' && chars[i] <= 'z'){
if(chars[i] == 'z') chars[i] = 'a';
else chars[i] = (char)(chars[i] + 1);
}
if(chars[i] >= 'A' && chars[i] <= 'Z'){
if(chars[i] == 'Z') chars[i] = 'A';
else chars[i] = (char)(chars[i] + 1);
}
if(chars[i] >= '1' && chars[i] <= '9'){
if(chars[i] == '9') chars[i] = '0';
else chars[i] = (char)(chars[i] + '1');
}
}
bw.write(chars);
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
3.解密在文件加密中生成的文件(解密刚才加密的文件)。
设计一个方法
public static void decodeFile(File decodingFile, File decodedFile);
在这个方法中把decodingFile的内容进行解密,然后保存到decodedFile文件中。
解密算法:
数字:
如果不是0的数字,在原来的基础上减1,比如6变成5, 4变成3
如果是0的数字,变成9
字母字符:
如果是非a字符,向左移动一个,比如e变成d, H变成G
如果是a,a->z, A-Z。
字符需要保留大小写
非字母字符:
比如',&^ 保留不变,中文也保留不变
public class Demo02 {
public static void main(String[] args) throws IOException {
File encodingFile = new File("/Users/chelsea-he/Documents/JAVA33th/testFile/encodingFile.txt");
File encodedFile = new File("/Users/chelsea-he/Documents/JAVA33th/testFile/encodedFile.txt");
File decodedFile = new File("/Users/chelsea-he/Documents/JAVA33th/testFile/decodedFile.txt");
// encodeFile(encodingFile, encodedFile);
decodeFile(encodedFile, decodedFile);
}
public static void decodeFile(File encodedFile, File decodedFile){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader(encodedFile));
bw = new BufferedWriter(new FileWriter(decodedFile));
String line;
while((line = br.readLine()) != null){
char[] chars = line.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(chars[i] >= 'a' && chars[i] <= 'z'){
if(chars[i] == 'a') chars[i] = 'z';
else chars[i] = (char)(chars[i] - 1);
}
if(chars[i] >= 'A' && chars[i] <= 'Z'){
if(chars[i] == 'A') chars[i] = 'Z';
else chars[i] = (char)(chars[i] - 1);
}
if(chars[i] >= '1' && chars[i] <= '9'){
if(chars[i] == '0') chars[i] = '9';
else chars[i] = (char)(chars[i] - 1);
}
}
bw.write(chars);
bw.newLine();
}
}catch (IOException e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}