BIO
同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理
字节流
InputStream和OutputStream,都实现了Coloseable接口,都支持try-resource来抛出异常
- read():返回值为int,每次读取一个字节,0-255之间,-1表示流结束
- read(byte[]):返回值为int,表示读取具体的字节个数,-1表示流结束
- close():返回值void,用来关闭流
练习:读取一个英文文本文件,并在控制台上输出显示
//一次一字节的读取方式
public static void main(String[] args){
InputStream is = null;//构建流对象
try{
is = new FileInputStream("cc.txt");
int len = 0;
while((len = is.read()) > 0){
System.out.print((char)len);//将其强制转换为字符
}
}catch(IOException e){
e.printStackTrace();
}finally{
try{
is.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
//缓冲数组方式进行读取
public static void main(String[] args){
InputStream is = null;
try{
is = new FileInputStream("cc.txt");
int len = 0;
byte[] buffer = new byte[8192];
while((len = is.read(buffer)) > 0){
String str = new String(buffer,0,len);
System.out.print(str);
}
}catch (IOException e){
e.printStackTrace();
}finally{
try{
is.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
OutputStream
- write():返回值为int,每次读取一个字节,0-255之间,-1表示流结束
- write(byte[], int 起始下标, int 长度):返回值void,表示具体的字节个数,-1表示流结束
- close():返回值为void,用来关闭流
练习:使用字节流进行文件拷贝
public static void main(String[] args){
InputStream is = null;
OutputStream os = null;
try{
is = new FileInputStream("a.txt");
os = new FileOutputStream("b.txt");
byte[] buffer = new byte[8192];
int len = 0;
while((len = is.read(buffer))>0){
os.writer(buffer,0,len);
}
}catch (IOException e){
e.printStackTrace();
}finally{
try{
if(is!=null && os!=null){
is.close();
os.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
字符流
一次一个字符的进行传输,如果涉及了中文信息,则需要考虑编码字符集
Reader
- read():返回值为int,返回读取到的字符数据,范围为0-65535,-1表示流末尾
- read(char[]):返回值int,返回读取的字符个数,流结束返回-1
- close():返回值为void,用来关闭流
练习:从一个txt文件中读取数据,并在控制台上显示输出,并写入到指定文件
public static void main(String[] args) throws IOException {
try(
Reader reader = new FileReader("a.txt");
Writer writer = new FileWriter("b.txt");
){
char[] buffer = new char[8192];
int len = 0;
while((len = reader.read(buffer))>0){
String str = new String(buffer,0,len);
System.out.print(str);
writer.wite(str);
reader.close();
writer.close();
}
}
}
节点流
文件流
- FIleInputStream和FileReader用于从一个文件中读取数据,FileInputStream文件输入字节流,FileReader文件输出字符流
- FIleOutputStream和FileWrite用于向一个文件写入数据
- FileOutputStream(“文件名称”),如果文件不存在,则自动创建,如果文件存在,则覆盖原文件的内容
- FileOutStream(“文件名称”, boolean 是否追加方式),如果文件不存在,则自动创建,如果文件存在并且博哦了安值为true,则表示采用追加的方式进行写入内容
练习:从控制台向一个文件内写入内容
public static void main(String[] args) throws IOException{
InputStream is = System.in;
byte[] buffer = new byte[8192];
int len = is.read(buffer);
for(len > 0){
OutputStream os = new FileOutputStream("File.txt",true);
os.write(buffer,0,len);
os.close();
}
}
文件流输入节点流,输入流的源端和输出断点的目标都是磁盘文件,沟通方法允许通过文件的路径或者文件对象的方式进行构建
练习:拷贝Data目录到D:/bbb目录下
public class Test {
private static String source = "Data";
private static String target = "D:/bbb";
public static void main(String[] args) {
File file = new File(source);
copy(file);
System.out.println("拷贝完毕");
}
public static void copy(File file){
if (file != null){
if (file.isFile()){
String oldPath = file.getAbsolutePath();
int pos = oldPath.indexOf(source);
String substring = target + oldPath.substring(pos+source.length());
byte[] buffer = new byte[1024];
int len = 0;
try(
InputStream is = new FileInputStream(file);
OutputStream os = new FileOutputStream(substring);
){
while ((len = is.read(buffer))>0){
os.write(buffer,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
}else if (file.isDirectory()){
//将原路径转换为新路径
String path = file.getAbsolutePath();
int pos = path.indexOf(source);
String substring = target + path.substring(pos + source.length());
File tmp = new File(substring);
if (!tmp.exists())
tmp.mkdirs();
File[] files = file.listFiles();
for (File tmp1:files) {
copy(tmp1);
}
}
}
}
}
内存数组节点流
如果是文本字符则使用char[],如果是二进制数据则使用byte[]
输入流
- CharArrayReader(char[]):其中char[]就是数据的来源
- CharArrayReader(char[] 数据, int 起始下标, int 最大长度)
练习
public static void main(String[] args){
String str = "我是李明";
char[] chars = str.toCharArray();//将字符串转换为数组,实际上Java提供字符串流
Reader reader = new CharArrayReader(arr);
int date = 0;
while((data = reader.read())>0){
System.out.println((char)data);
}
reader.close();
}
输出流
CharArrayWriter用于向一个字符数组中写入数据,这个数组的大小可以自动调整
- CharArrayWriter():自动创建一个关联char[]的输出流
- CharArrayWriter(int):自动创建一个管理char[]的输出流,参数代表char[]的初始化大小
public static void main(Stirng[] args) throws IOException {
Writer writer = new CHarArrayWriter();
//从键盘读取数据,并写入char[]中
Scanner sc = new Scanner(System.in);
String line = Scanner.nextLine();//读取一行数据
while(!"exit".equals(line)){
writer.write(line);
line = scanner.nextLine()+"\n;
}
sc.close();
CharArrayWriter caw = (CharArrayWriter)writer;
String str = new String(caw.toCharArray());//获取关联的char[]
System.out.println(str);
}
内存字符流
StringReader用于从一个String中读取数据
public static void main(String[] args){
String str = "我是彭于晏";
Reader reader = new StringReader(str);
int len = 0;
while((len = reader.read())>0){
System.out.println((char)len);
}
reader.close();
}
StringWriter用于向一个StringBuffer中写入数据,实现了一个可变长度的字符串
public static void main(String[] agrs) throws Exception{
Scanner sc = new Scanner(System.in);
try(
StringWriter sw = new StringWriter();
Writer writer = new FileWirter("String.txt");
){
String str = sx.nextLine();
while(!"quit".equals(str)){
if(str!=null && str.trim().length()>0)
sw.write(str+"\n");
str = sc.nextLine();
}
System.out.println(sw.toString());
writer.write(sw.toString());
}
sc.close();
}
过滤流
过滤流就是节点流的基础上附加功能
实例:循环13加密(以输入方式进行加密)
public class MyFilterReader extends FilterReader{
protected MyFilterReader(Reader in){
super(in);
}
public int read() throws IOException {
int num = super.read();
if (num >= 'a' && num <= 'z') {
num = (num - 'a' + 13) % 26 + 'a';
} else if (num >= 'A' && num <= 'Z') {
num = (num - 'A' + 13) % 26 + 'A';
} else if (num >= '0' && num <= '9') {
num = (num - '0' + 5) % 10 + '0';
}
return num;
}
public static void main(String[] args){
MyFilterReader mfr = new MyFilterReader(new FileReader("Data/Test.java"));
int kk;
while ((kk = mfr.read()) != -1) {
System.out.print((char) kk);
}
sr.close();
}
}
实例:循环13加密(以输出方式进行加密)
class MyFilter extends FilterWriter {
protected MyFilterWriter(Writer out){
super(out);
}
public void write(int c) throws IOException {
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + 13) % 26 + 'A';
} else if (c >= '0' && c <= '9') {
c = (c - '0' + 5) % 10 + '0';
}
super.write(c);
}
public static void main(String[] args){
try(
Reader r = new FileReader("a.txt");
MyFilterWriter w = new MyFilterWriter(new FileWriter("b.txt"));
){
int len = 0;
while((len=r.read()>0)){
w.write(len);
}
r.close();
w.close();
}
}
}
桥接流
实现字节记录和字符流之间的自动转换,从字节输入流读取字节数据,并按照编码规范转换为字符;向字节输出流写出数据是,先将字符按照编码规范转换为字节,然后再进行输出。使用桥接流时应该指定编码字符集名称,以便实现流的转换,如果不指定,则使用当前默认的编码字符集。
- InputStreamReader用于将一个InputStream自动转换为Reader
- OutputStreamWriter用于将一个Writer自动转换为OutPutStream
InputStreamReader
- InputStreamReader(InputStream)
- InputStreamReader(InputStream in,String charsetName)
- InputStreamReader(InputStream in,Charset cs),直接使用charsetName编码字符集名称的方式进行设定编码字符集可能会出错,所以可以使用Charset指定编码字符集名称
public static void main(String[] args){
Reader r = new InputStreamReader(System.in);
int len = r.read();
System.out.println((char)len);//只读取一个字符
//使用UTF-8编码字符集
Reader r = new InputStreamReader(System.in,"UTF-8");
int len = r.read;
System.out.println((char)len);
}
缓冲流
缓冲流时套装在相应的节点流之上,对读写操作提供缓冲作用,提高的效率,并引入一个新方法BufferedInlutStream()
public static void main(String[] args){
//没有缓冲流的时间统计
long start = System.currentTimeMillis();
InputStream is = new FileInputStream("a.txt");
int len = 0;
while((len=is.read())>0){
System.out.print((char)len);
}
is.close();
long end = System.currentTimeMillis();
System.out.println("执行时间为:"+(end-start)+"ms");
//有缓冲流的时间统计
long start1 = System.currentTimeMills();
InputStream is1 = new BufferedInputStream(new FileInputStream("a.txt"));
int len1 = 0;
while((len1 = is1.read())>0){
System.out.print((char)len1);
}
is.close();
long end1 = System.currentTimeMillis();
System.out.println("执行时间为:"+(end1-start1)+"ms");
}
- 读写文件使用文件流,如果操作文本文件建议使用FileReader和FileWriter,如果是操作二进制文件,则建议使用FileInputStreamhe FileOutputStream。
- 需要建立缓冲区,可以考虑建立临时文件,但是这种方式效率低下,所以一般建议考虑使用CharArrayReader/CharArrayWriter和ByteArrayInputStream/ByteArrayOutputStream或者StringReader/StringWriter充当内存缓冲区
- 如果需要二进制缓冲可以ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓冲区,可以使用CharArrayReader/CharArrayWriter、StringReader/StringWriter
- 如果数据量不是特别大,则使用CharArrayReader/CharArrayWriter更为方便一些,如果数据量大,可能需要直接操作缓冲区,则可以使用StringReader/StringWriter
- StringWriter中提供了一个getBuffer()方法,可以获取到StringBuffer