I/O框架
I---input
O---output
流----流向划分:输入和输出
流---单元划分:字节流和字符流
字符流基于字节流
以Stream结尾的为字节流,以write或者Reader结尾的为字符流,所有的输出流都是抽象类IuputStream(字节流)或者抽象类Reader(字符输出流)的子类。所有的输出流都是抽象类OutputStream(字节输出流)或者抽象类OutputWriter(字符输出流)的子类。
字符流能实现的功能字节流都能实现,反正不一定。比如图片、视频等等二进制文件。
file类
File file = new File("A");
file.mkdir();
File files = new File("B/C/D");
files.mkdirs();
file.delete();
files.delete();
File file1 = new File("a.txt");
File file2 = new File("C:\\Users\\WHD\\Desktop\\test.txt");
try {
file1.createNewFile();
file2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("a.txt文件是否存在" + file1.exists());
System.out.println("a.txt文件的相对路径" + file1.getPath());
System.out.println("a.txt文件的绝对路径" + file1.getAbsolutePath());
System.out.println("a.txt文件的大小" + file1.length());
System.out.println("a.txt文件的名称" + file1.getName());
System.out.println("a.txt是否是一个文件" + file1.isFile());
System.out.println("a.txt是否是一个文件夹" + file1.isDirectory());
System.out.println("是否删除成功" + file1.delete());
字节流
字节文件读取流
父类--abstract InputStream
字节读取流---FileInputStream
raed()
//每次读取一个字节返回值是读取内容的ascii码值
read(byte[] datas)
//可以读取指定数组长度的内容,返回值是每次读取的长度,读取的内容存放在数组中,可以使用String类构造方法来封装为字符串new String(byte[] b,int offset,int length);
字节
byte 8位 ASCII码
父类--
FileInputStream fis = null;
try {
fis = new FileInputStream("b.txt");
int data = -1;
while((data = fis.read()) != -1) {
System.out.print((char)data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
byte[] datas = new byte[2];
FileInputStream file = null;
try {
file = new FileInputStream("b.txt");
int data = -1;
while ((data = file.read(datas)) != -1) {
System.out.println(data);
System.out.println(new String(datas, 0, data));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(file != null) {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileInputStream file = null;
try {
file = new FileInputStream("b.txt");
byte [] datas = new byte[file.available()];
int data = -1;
while((data = file.read(datas)) != -1) {
System.out.println(new String(datas, 0, data));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(file != null) {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节文件写入流
父类---abstract OutputStream
字节文件写入流---FileOutputStream
void write();
//每次写入一个字节
void write(byte [] datas);
//写入一个byte数组,可以使用String类的getBytes()方法将字符串转换为byte数组
flush();
//内容刷新到文件中
close():
//关闭资源
FileOutputStream fos = null;
try {
fos = new FileOutputStream("b.txt");
fos.write(97);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream("c.txt", true);
String str = "学java 到千锋 郑州千锋找帅栋 23564545";
byte [] datas = str.getBytes();
fos.write(datas);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流
字符的文件读取流
父类---abstract Reader
FileReader---基于字符的文件读取流
int read();
//每次读取一个字符
int read(char[] datas);
//每次读取char数组长度的内容,返回值是读取的长度,读取的内容存放在数组中,可以直接打印
try {
FileReader fr = new FileReader("c.txt");
int data = -1;
while((data =fr.read()) != -1) {
System.out.println((char)data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
FileReader fr = null;
try {
fr = new FileReader("c.txt");
char [] datas = new char[100];
int dataCount = -1;
while((dataCount = fr.read(datas)) != -1) {
System.out.println(dataCount);
System.out.println(datas);
System.out.println(new String(datas, 0, dataCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符的文件读取缓冲流
BufferedReader---基于字符的文件读取缓冲流
1).从字符输入流中读取文本,缓冲各个字符,实现字符、数组和行的高校读取。
2).可以指定缓冲区的大小,或者使用默认的大小。大多数情况下默认就足够大。
3).通常,Reader所做的每个读取请求都会导致对底层字符或者字节流进行相应的读取请求,建议BufferedReader包装所有其read()操作可能开销很高的Reader(如FileReader和InputStreamReader)
例如 BufferedReader = new BufferedReader(new FileReader("a.txt"));
4).将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("c.txt");
br = new BufferedReader(fr);
int data = -1;
while((data = br.read()) != -1) {
System.out.println((char)data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("c.txt");
br = new BufferedReader(fr);
String line = null;
while((line = br.readLine()) !=null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
指定编码格式的字符读取流
InputStreamReader---可以指定编码格式的字符读取流
FileInputStream fis;
try {
fis = new FileInputStream("C:\\Users\\WHD\\Desktop\\testCode.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");
char []datas = new char[100];
int dataCount = -1;
while((dataCount = isr.read(datas)) != -1) {
System.out.println(datas);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
}
字符的文件写入流
父类---abstract Writer
FileWriter---基于字符的文件写入流
write();
//每次写入一个字符
write(char [] datas);
//每次写入一个char数组
write(String str);
//每次写入一个字符串
FileWriter
try {
FileWriter fw = new FileWriter("d.txt", true);
fw.write("hello nihao\n世界你好");
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
}
字符的文件写入缓冲流
BufferedWriter---基于字符的文件写入缓冲流
write();
//每次写入一个字符
write(char [] datas);
//每次写入一个char数组
newLine();//换行
1).将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
2).可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
3).该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。
4).通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
5).缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。
缓冲区的工作原理:1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内。2、通过缓冲区的read()方法从缓冲区获取具体的字符数据,这样就提高了效率。3、如果用read方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了readLine()功能。
FileWriter
try {
FileWriter fw = new FileWriter("d.txt", true);
fw.write("hello nihao\n世界你好");
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
}
指定编码格式的字符写入流
子类:OutputStreamWriter
write():每次写入一个字符
write(char [] datas):每次写入一个char数组
write(String str):每次写入一个字符串
FileOutputStream fos;
try {
fos = new FileOutputStream("f.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("hello world");
osw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
数据流
数据流属于字节流,用于读取二进制文件,比如图片,音频,视频等等
DataInputStream 负责读取二进制文件
DataOutputStream 负责写入二进制文件
FileInputStream fis;
try {
FileOutputStream fos = new FileOutputStream("copy.png");
fis = new FileInputStream("C:\\Users\\18409\\Desktop\\zs.png");
DataInputStream dps = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);
byte[] datas = new byte[fis.available()];
int data = -1;
while((data = dps.read(datas))!=-1) {
dos.write(datas);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
}
对象流
对象流输入字节流,用于读取对象和写入对象
ObjectInputStream 对象读取流---序列化:讲对象以二进制的形式写入(存储)文件中
ObjectOutputStream 对象写入流---反序列化:将存有对象的文件读取出来生成对象
被序列化的对象必须实现Serializable接口
此接口是空接口,相当于一个标识,实现此接口的了才能被序列化
FileOutputStream fos;
try {
fos = new FileOutputStream("stu.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student stu1 = new Student("赵四", 20);
Student stu2 = new Student("广坤", 22);
Student stu3 = new Student("小宝", 19);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.writeObject(stu3);
FileInputStream fis = new FileInputStream("stu.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
while(fis.available()>0) {
Student readStu1 = (Student) ois.readObject();
System.out.println(readStu1);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
乱码
乱码出现的原因:
编码的方式和解码的方式不一样
编码文件类型
java文件编码
html文件编码
数据库文件编码
js文件编码
...
解决乱码的方式:
统一编码
可以将出现的乱码的内容打散(iso-8859-1)按照我们自己的编码方式组合
常见的编码格式:
GBK国标扩展版 简体和繁体
GB2312 国标版本 简体
ISO-8859-1 最原始的编码方式,通常用于解决乱码
UTF-8 unicode 万国吗 包含世界上大多数国家的语言编码
ANSI 不具体制定某一编码,因为在不同的操作系统上,表示对应的编码 比如Win10中文版就是GBK