IO
字符集:
常见字符集:ASCll 包括了数字,英文,符号。
ASCll使用一个字节存储字符,一个字节是八位,总共可以表示128个字符
GBK:用来存储中文字符,window系统默认的字符
Unicode码表:统一全球的编码,万国码。UTF-8,UTF-16…。技术UTF_8人员都应该使用UTF_8,编码前和解码后必须要一致,不然会乱码。
字符的编码有多种方案,一个英文字符在ASCII码、Unicode码、UTF-8编码中,分别占用一个、两个、一个字节的空间;一个汉字字符在ASCII码、Unicode码、UTF-8编码中,分别占用两个、两个、三个字节的空间
结论:计算机底层可以表示十进制编号。计算机可以给人类符号进行编号存储,即字符集
IO流概述:
按方向分类:分为输入流,输出流
输入流:是数据从硬盘文件,读入到内存的过程
输出流:是内存程序的数据从内存写出到硬盘文件的过程,称之为输出,负责写。
按流中的数据最小单位分为:字节流,字符流。
-
字节输入流:以内存为基准,来自磁盘中的文件/网络中的数据以字节的形式读入到内存中,称为字节输入流
-
字节输出流:以内存为基准,来自内存的数据以字节的形式读入到磁盘中的文件/网络中,称为字节输出流
- InputStream,OutputStream
-
字符输入流:以内存为基准,来自磁盘中的文件/网络中的数据以字符的形式读入到内存中,称为字符输入流
-
字符输出流:以内存为基准,来自内存的数据以字符的形式读入到磁盘中的文件/网络中,称为字符输出流
- Reader , Writer
//文件字节输入流,api
public int read();
//每次读取一个字节返回,如果没有字节返回-1;
读取一个字节存在什么问题:
- 性能较慢
- 读取中文字符,容易出现乱码问题。
文件字节输入流:FileInputStream
文件字节输出流:FileOutputStream
//以字节的形式将数据读取到内存中去
public int read();
public int read(byte[] buffer);
控制台=内存,磁盘,网络文件
外:磁盘,网络文件
内:内存,控制台
字节流读取:
常用API:
write();
read();
根据参数不同选择不同
int,char[],String,off,set如下代码:
package com.pan.Stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class FileStream {
public static void main(String[] args) throws Exception {
File f= new File("FileTest/src/test.txt");
InputStream is = new FileInputStream(f);
/* int b1 = is.read();
System.out.println(b1);
int b4 = is.read();
System.out.println(b4);
int b3 = is.read();
System.out.println(b3);
int b2 = is.read();
System.out.println(b2);
*/
//依然无法避免乱码,会把中文截断,一个中文字符栈用三个字节,一个英文字符占一个字节
/*byte[] bytes = new byte[3];
int len;
while((len = is.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}*/
/*System.out.println("读取了几个字节"+len);
String rs = new String(bytes,1,2);
System.out.println(rs);*/
//将文件所有的字符一次性接收
/* byte[] buffer = new byte[(int) f.length()];
int len = is.read(buffer);
System.out.println("长度为:"+len);
System.out.println("长度为:"+f.length());
System.out.println(new String(buffer));*/
// byte[] buffer = is.readALLBByte();
}
}
字符流读取:
package com.pan.Stream;
/*
*由于字节流读取文件会出现乱码
* 使用字符流读取和写入,最小单位是按照字符开始的
* Reader(抽象)--->FileReader(实现类)
* */
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
public class FileInputStringStream {
public static void main(String[] args) throws Exception {
//目标:每次读取一个字符
//1。创建一个字符输入流管道与原文件接通
Reader reader = new FileReader("FileTest/src/dataCode.txt");
//2.读取一个字符
int count = reader.read();
System.out.println((char)count);
int code ;
while((code = reader.read()) != -1){
System.out.print((char)code);
}
//不能重复读,上面的循环完后,下面的循环输出为空;必须注释掉上面
char[] characters = new char[1024];
// int count1 = reader.read(characters,0,3);
//记录读取字符的个数
int len;
System.out.println("=========================================================================");
while((len = reader.read(characters)) != -1){
String rs = new String(characters,0,len);
System.out.print(rs);
}
//System.out.println((char)count1);
}
}
输出流
package com.pan.Stream;
/*
* 写入外部文件,以字符为基础
* 写到磁盘文件
* Writer(抽象类)---->FileWriter(实现类)
* */
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class FileOutStringStream {
//1.创建一个文件输出流
public static void main(String[] args) throws IOException {
Writer writer = new FileWriter("FileTest/src/data字符.txt",true);
//2.常用API
writer.write(99);
writer.write("年后就");
writer.write('a');
//换行
writer.write("\r\n");
char[] chars = "我似乎好像是输出流".toCharArray();
writer.write(chars);
writer.write("\r\n");
writer.write("我是中国人",0,2);
//刷新
writer.flush();//刷新后,流可以继续使用
//关闭流
writer.close();//关闭包含刷新,关闭后流不可以使用
}
}
字节 缓冲流
package com.pan.StreamAreasBuffer;
import java.io.*;
/*
* Buffer高级流,性能更好
* */
public class ByteBufferDemo {
public static void main(String[] args) {
// InputStream inputStream = null;
// OutputStream outputStream = null;
//创建一个字节输入流管道与视屏文件接通
try(
//try()中会自动关闭流。
InputStream inputStream = new FileInputStream("E:\\图库\\OIP-C.jpg");
//2.创建一个字节输出流管道与目标文件接通
//把原始的字节输入流包装成高级的缓冲输入流
InputStream bis = new BufferedInputStream(inputStream);
//文件的速度慢于内存,outputStream 不在内存中非常慢
OutputStream outputStream = new FileOutputStream("FileTest/src/image01.png");
//把字节输出流包装在高级的缓冲字节输出流管道,8kb的缓冲池,存储空间小,查找快,读取快
OutputStream outputStream1 = new BufferedOutputStream(outputStream);
) {
byte[] buffer = new byte[1024];
int len ;
while((len = bis.read(buffer) ) != -1){
outputStream1.write(buffer,0,len);
}
System.out.println("赋值完成了");
} catch (IOException e) {
e.printStackTrace();
}
finally {
System.out.println("=====================finally=================");
}
}
}
文件复制案例与性能对比
package com.pan.StreamAreasBuffer;
import java.io.*;
import java.nio.Buffer;
import java.util.Collections;
public class CompareTimeBuffer {
public static void main(String[] args) {
copyBufferStreamTime();
copyOldStreamTime();
copyBufferStreamTimeBit();
copyOldStreamTimeBit();
}
public static void copyOldStreamTime(){
long startTime = System.currentTimeMillis();
// InputStream inputStream = null;
// OutputStream outputStream = null;
//创建一个字节输入流管道与视屏文件接通
try(
InputStream inputStream = new FileInputStream("E:\\图库\\2019年下半年软件设计师下午真题及答案解析.word");
//2.创建一个字节输出流管道与目标文件接通
OutputStream outputStream = new FileOutputStream("FileTest/src/papers01.pdf");
) {
byte[] buffer = new byte[1024];
int len ;
while((len = inputStream.read(buffer) ) != -1){
outputStream.write(buffer,0,len);
}
System.out.println("赋值完成了");
} catch (IOException e) {
e.printStackTrace();
}
finally {
System.out.println("=====================finally=================");
}
long endTime = System.currentTimeMillis();
System.out.println("使用--原始的--字节流(一个数组)的形式复制文件"+(endTime - startTime)/1000.0 + "s");
}
public static void copyBufferStreamTime(){
long startTime = System.currentTimeMillis();
// InputStream inputStream = null;
// OutputStream outputStream = null;
//创建一个字节输入流管道与视屏文件接通
try(
InputStream inputStream = new FileInputStream("E:\\图库\\2019年下半年软件设计师下午真题及答案解析.word");
InputStream inputStream1 = new BufferedInputStream(inputStream);
//2.创建一个字节输出流管道与目标文件接通
OutputStream outputStream = new FileOutputStream("FileTest/src/papers02.pdf");
OutputStream outputStream1 = new BufferedOutputStream(outputStream);
) {
byte[] buffer = new byte[1024];
int len ;
while((len = inputStream1.read(buffer) ) != -1){
outputStream1.write(buffer,0,len);
}
System.out.println("赋值完成了");
} catch (IOException e) {
e.printStackTrace();
}
finally {
System.out.println("=====================finally=================");
}
long endTime = System.currentTimeMillis();
System.out.println("使用--缓冲--字节流(一个数组)形式复制文件"+(endTime - startTime)/1000.0 + "s");
}
public static void copyOldStreamTimeBit(){
long startTime = System.currentTimeMillis();
// InputStream inputStream = null;
// OutputStream outputStream = null;
//创建一个字节输入流管道与视屏文件接通
try(
InputStream inputStream = new FileInputStream("E:\\图库\\2019年下半年软件设计师下午真题及答案解析.word");
//2.创建一个字节输出流管道与目标文件接通
OutputStream outputStream = new FileOutputStream("FileTest/src/papers03.pdf");
) {
//一个一个字节输出
int len ;
while((len = inputStream.read() ) != -1){
outputStream.write(len);
}
System.out.println("赋值完成了");
} catch (IOException e) {
e.printStackTrace();
}
finally {
System.out.println("=====================finally=================");
}
long endTime = System.currentTimeMillis();
System.out.println("使用--原始的--字节流(一个一个字节)的形式复制文件"+(endTime - startTime)/1000.0 + "s");
}
public static void copyBufferStreamTimeBit(){
long startTime = System.currentTimeMillis();
// InputStream inputStream = null;
// OutputStream outputStream = null;
//创建一个字节输入流管道与视屏文件接通
try(
InputStream inputStream = new FileInputStream("E:\\图库\\2019年下半年软件设计师下午真题及答案解析.word");
InputStream inputStream1 = new BufferedInputStream(inputStream);
//2.创建一个字节输出流管道与目标文件接通
OutputStream outputStream = new FileOutputStream("FileTest/src/papers04.pdf");
OutputStream outputStream1 = new BufferedOutputStream(outputStream);
) {
int len ;
while((len = inputStream1.read() ) != -1){
outputStream1.write(len);
}
System.out.println("赋值完成了");
} catch (IOException e) {
e.printStackTrace();
}
finally {
System.out.println("=====================finally=================");
}
long endTime = System.currentTimeMillis();
System.out.println("使用--缓冲--字节流(一个一个字节)的形式复制文件"+(endTime - startTime)/1000.0 + "s");
}
}
结果如下:
赋值完成了
=====finally=
使用–缓冲–字节流(一个数组)形式复制文件0.014s
赋值完成了
=====finally=
使用–原始的–字节流(一个数组)的形式复制文件0.026s
赋值完成了
=====finally=
使用–缓冲–字节流(一个一个字节)的形式复制文件0.046s
赋值完成了
=====finally=
使用–原始的–字节流(一个一个字节)的形式复制文件10.532sProcess finished with exit code 0
字符缓冲流
BufferedRead
package com.pan.StreamAreasBuffer;
/*
* 目标:学会使用字符缓冲输入流/输出流提高自己的性能(8k空间)
* 并学习新增的方法(readLine())优先使用
* Reader---->BufferedReader(继承)
* 经典代码:字符流,行读,不需要字符流桶,桶读会截断。
* */
import java.io.*;
public class BufferReaderDemo01 {
public static void main(String[] args) throws Exception {
try ( //1.创建一个Reader的字符流与原文件接通
Reader reader = new FileReader("FileTest/src/data1.txt");
BufferedReader bufferedReader = new BufferedReader(reader);
) {
//2.用循环,将文件读取出来
// char[] chars = new char[1024];
// int len ;
// while((len = reader.read(chars)) != -1){
// String s = new String(chars,0,len);
// System.out.println(s);
// }
String line;
while((line = bufferedReader.readLine())!= null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出
package com.pan.StreamAreasBuffer;
/*
* 目标:学会使用字符缓冲输出流/输出流提高自己的性能(8k空间)
* 并学习新增的方法()优先使用
* Writer---->BufferedWriter(继承)
* */
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class BufferWriterDemo01 {
//1.创建一个文件输出流
public static void main(String[] args) throws IOException {
Writer fw = new FileWriter("FileTest/src/data字符.txt",true);
BufferedWriter bufferedWriter = new BufferedWriter(fw);
//2.常用API
bufferedWriter.write(99);
bufferedWriter.write("年后就========================================================");
bufferedWriter.write('a');
//换行
bufferedWriter.write("\r\n");
char[] chars = "我似乎好像是输出流".toCharArray();
bufferedWriter.write(chars);
bufferedWriter.write("\r\n");
bufferedWriter.write("我是中国人",0,2);
//刷新
bufferedWriter.flush();//刷新后,流可以继续使用
//关闭流
bufferedWriter.close();//关闭包含刷新,关闭后流不可以使用
}
java
}
案例:
乱序的出师表恢复
package com.pan.items;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
* 拷贝一个出师表
* */
public class TeacherForm {
public static void main(String[] args) {
try( //1.创建一个Buffered输入流
Reader reader = new FileReader("FileTest/src/出师表.txt");
BufferedReader bufferedReader = new BufferedReader(reader);) {
//2.创建一个list数组存放行字符,list可以默认排序
List<String> data = new ArrayList<>();
//按行读取字符,并添加到数组里
String Line;
while((Line = bufferedReader.readLine()) != null){
data.add(Line);
}
System.out.println(data);
//排序
Collections.sort(data);
System.out.println(data);
//自定义排序规则
List<String> size = new ArrayList<>();
Collections.addAll(size,"一","二","三","四","五","六","七","八","九");
Collections.sort(data, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return size.indexOf(o1.substring(0,o1.indexOf("\\.")))- size.indexOf(o2.substring(0,o2.indexOf("\\.")));
}
});
System.out.println(data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
读取乱码问题(代码与文件编码不一致)
读写编码格式设置
使用以下两个流
InputStreamReader: 有多种构造器
package com.pan.problemsolve;
/*
* 当文件编码格式与代码编码格式不一致时解决办法
* 使用 Reader ----> InputStreamReader(input,charset);
* */
import java.io.*;
public class ConfuseCode {
public static void main(String[] args) throws Exception {
try ( //1.创建一个Reader的字符流与原文件接通,文档编码不一致,一个是GBK 一个是UTF-8,由于对中文编码字节数数不一致的
// Reader reader = new FileReader("E:/文档/data.txt");,这是原本的文件读取方式,会出现乱码,由于编码的不一致
// BufferedReader bufferedReader = new BufferedReader(reader);
InputStream inputStream = new FileInputStream("E:/文档/data01.txt");
//BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//2.通过字符流的子实现类的构造方式去确定流的读取编码方式。得到流数据
Reader reader = new InputStreamReader(inputStream,"GBK");
//3.设置缓冲区流,将流反倒缓冲区
BufferedReader bufferedReader = new BufferedReader(reader);
) {
//当然也可以让直接字节容器读取,但要确定文件大小才行
/* byte[] bytes = new byte[10];
int line;
while((line = bufferedInputStream.read(bytes))!= -1){
String s = new String(bytes,0,line);
System.out.println(s);*/
//4.读取到控制台,按行读取。
String Line;
while((Line = bufferedReader.readLine() ) != null){
System.out.println(Line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutStreamWriter: 有多种构造器
package com.pan.problemsolve;
/*
*
* */
import java.io.*;
public class ConfuseCodeOut {
public static void main(String[] args) {
//1.定义一个字节输出流
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream("FileTest/src/datacodetest.txt");
//低级流,并指定编码。idea默认为UTF-8
Writer writer = new OutputStreamWriter(outputStream,"GBK");
//高级流
BufferedWriter bufferedWriter = new BufferedWriter(writer);
bufferedWriter.write("我爱你中国~~~~~~~~~");
bufferedWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}