java基础
一. IO
1.1 io分类
1.按照流的流向分,可以分为输入流和输出流;
2.按照操作单元划分,可以划分为字节流和字符流;
3.按照流的角色划分为节点流和处理流。
所有的输入流的基类:
InputStream(字节) Reader(字符)
所有输出流的基类:
OutputStream(字节) Writer(字符)
1.2 BIO,NIO,AIO 有什么区别?
BIO是一个连接一个线程:
同步并阻塞
线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。NIO是一个请求一个线程。
适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解
NIO是一个请求一个线程:
同步非阻塞
线程发起IO请求,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调函数通知线程做IO操作,线程开始阻塞,直到操作完成
适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持
AIO是一个有效请求一个线程:
异步非阻塞
线程发起IO请求,立即返回;内存做好IO操作的准备之后,做IO操作,直到操作完成或者失败,通过调用注册的回调函数通知线程做IO操作完成或者失败。
用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持
1.3 IO流_体系结构
1.字节流:可以操作任何文件
a.输出流:OutputStream(抽象类)(三种输出方法)
|—FileOutputStream(基本类)
|—FilterOutputStream
|—BufferedOutputStream(缓存流)(无特有方法)
b.输入流:InputStream(抽象类)(俩种读取方法)
|—FileInputStream(基本类)
|—FilterInputStream
|—BufferedInputStream(缓存流)(无特有方法)
2.字符流:只能操作存文本文件
a.输出流:Writer(抽象类)(五种输出方法)
|—OutputStreamWriter(转换流):指定字符集
|—FileWrite(子类)
|—BufferedWriter(缓冲流)–除提供缓存区,有特有方法
newLine():根据平台输出一个换行符;
b.输入流:Reader(抽象类)(两种读取的方法)
|–InputStreamReader(转换流):指定字符集
|–FileReader(子类)
|–BufferedReader(缓冲流)-除提供缓存区,有特有方法
String readLine():一次读取一行。
1.3.1 IO流_字节流
1.1 输出流 FileOutputStream
构造方法:
FileOutputStream(String name) :(覆盖)创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append) (追加)创建文件输出流以指定的名称写入文件。
FileOutputStream(File file):(覆盖)创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append) (追加)创建文件输出流以写入由指定的 File对象表示的文件。
注意:
Java中所有的“输出流”构造时,文件可以不存在,会自动创建一个;
写入的方法:(三种)
write(int b):输出一个字节;
write(byte[] byteArray):输出一个字节数组;
write(byte[] byteArray,int off,int len):输出字节数组的一部分;
byteArray : 要写入的数组;
off : 起始位置索引;
len : 输出的数量;
示例代码:
public static void main(String[] args) throws IOException {
//1.构造方法:
FileOutputStream out = new FileOutputStream("demo12.txt",false);
//2.输出的方法:
//2-1:write(int b):输出一个字节
out.write(97);//97 --> 转换为二进制: 0110 0001 --> 写入文件:0110 0001
out.write(999997);//999997 -->转换为二进制:111101000010 0011 1101 --> 取最低的一个字节:写入文件:0011 1101
//2-2:write(byte[] byteArray):输出多个字节
byte[] byteArray = {97, 98, 99, 100};
out.write(byteArray);
//间接的输出一个“字符串”
out.write("大家好,呵呵".getBytes());
//输出一个换行符:
out.write("\r\n".getBytes());
//2-3:write(byte[] byteArray,int offset,int len):
//例如:写入byteArray数组中的99,100
out.write(byteArray,2,2);
//关闭流--成为垃圾--释放资源
out.close();
}
注意:
String类的getBytes()方法可以将此字符串转换为一个byte[]数组
换行:"\r\n"
流用完后,要记得“关闭”,用于“释放资源”。
1.1 输入流 FileInputStream
构造方法:
FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream 该文件由文件系统中的路径名 name命名。
FileInputStream(File file) 通过打开与实际文件的连接创建一个 FileInputStream 该文件由文件系统中的 File对象 file命名。
注意:
Java中所有的“输入流”构造时,文件必须存在,否则抛出异常;
读取的方法(两种)
public int read():读取一个字节
public int read(byte[] byteArray):读取多个字节,封装到参数数组中。
示例代码:
public class Demo {
public static void main(String[] args) throws IOException {
File file = new File("demo13.txt");
if (!file.exists()) {
file.createNewFile();
}
FileInputStream in = new FileInputStream(file);
//读一个字节
/*int b = 0;
while ((b = in.read()) != -1) {
System.out.println((char)b);
}*/
//读取多个字节:3个
byte[] byteArray = new byte[3];
int len = 0;
while ((len = in.read(byteArray)) != -1) {
//将 byte[]数组转换为String
String str = new String(byteArray,0,len);
System.out.println("转换为String后:" + str);
}
}
}
1.3.2 IO流_字符流
1.1输出流 FileWriter
1.构造方法:
FileWriter(String fileName)(覆盖)构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append) (追加)
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
FileWriter(File file)(覆盖) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append)(追加) 给一个File对象构造一个FileWriter对象。
2.输出方法:(五个)
write(int c):输出一个字符;
write(char[] chArray):输出一个字符数组;
write(char[] chArray,int off,int len):输出字符数组的一部分;
write(String str):输出一个字符串;
write(String str,int off,int len):输出字符串的一部分;
3.示例代码:
public static void main(String[] args) throws IOException {
//注意:构造时,文件可以不存在,会自动创建
FileWriter out = new FileWriter("demo02.txt");
//**********五个输出的方法*************************************//
//1.write(int c):输出一个字符
out.write(98);
//2.write(char[] chArray):输出一个字符数组
char[] chArray = {'a','b','你','号','呵','呵'};
out.write(chArray);
//3.write(char[] chArray,int off,int len("输出字符数组的一部分;
out.write(chArray,4,2);
//4.write(String s):输出一个字符串
out.write("我爱Java");
//5.write(String s,int off,int len):输出字符串的一部分
String str = "我爱北京天安门";
out.write(str,4,3);
//*******************输出换行************************//
out.write("\r\n");
out.write("你好");
//刷新缓存区
// out.flush();
//注意:"字符流"内部自带缓存区,write()之后一定要flush()/close()才能
//将缓存区的数据写入到文件。
out.close();//相当于:flush() + close()
}
1.2. 输出流 转换流OutputStreamWriter
构造方法:
1.OutputStreamWriter(OutputStream out):使用一个“字节流对象”构造一个“转换流对象”,可以实现第一个作用。
public static void main(String[] args) {
//将"字节流对象"转换为"字符流对象"
try (OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo06.txt"))) {
//"字符"通向"字节"的桥梁
out.write("呵呵");//程序中:字符 --> 编码表:UTF-8 -->十进制编码-->二进制 -->文件(字节)
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2.OutputStreamWriter(OutputStream out, String charsetName):使用一个字节流,和一个“编码表”的名字类构造一个输出流
public static void main(String[] args) {
//将"字节流对象"转换为"字符流对象",同时,又指定了编码表
try (OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream("demo06.txt"),"UTF-8")) {
out.write("呵呵");//程序中:字符 --> 编码表:UTF-8 -->十进制编码-->二进制 -->文件(字节)
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2.1输入流 FileReader
1.构造方法:
FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。
FileReader(File file) 创建一个新的 FileReader ,给出 File读取。
2.读取的方法:
int read():读取一个字符;返回值:读取的字符的“编码”
int read(char[] chArray):读取多个字符,存储到字符数组中。(读取一个字符数组)
返回值:读取的字符的“数量”。
3.示例代码:
public static void main(String[] args) throws IOException {
FileReader in = new FileReader("demo03.txt");
//一次读取一个字符
/*int c = 0;
while ((c = in.read()) != -1) {
System.out.println("读取的字符:" + (char)c);
}*/
//一次读取一个字符数组
char[] chArray = new char[2];
int len = 0;
while ((len = in.read(chArray)) != -1) {
//可以将一个字符数组的一部分转换为String
String str = new String(chArray,0,len);
System.out.println(str);
}
//关闭
in.close();
}
2.2. 输入流 转换流InputStreamReader
构造方法:
1.public InputStreamReader(InputStream in):使用一个“字节输入流”构造
public static void main(String[] args) {
//将“字节流”转换为“字符流”,而且使用系统默认编码:UTF-8
try (InputStreamReader in = new InputStreamReader(
new FileInputStream("demo06.txt"))) {
int c = 0;
while ((c = in.read()) != -1) {
System.out.println((char) c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2.public InputStreamReader(InputStream in,String charsetName):使用一个“字节流”和一个“编码表名称”构造一个转换流。
public static void main(String[] args) {
//使用一个“字节流”和“UTF-8”构造一个转换流。使用UTF-8读取。
try (InputStreamReader in = new InputStreamReader(
new FileInputStream("demo06.txt"),"UTF-8")) {
int c = 0;
while ((c = in.read()) != -1) {
System.out.println((char) c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
1.3.3.IO流_缓冲流:
分类:
字节流:
输出流:BufferedOutputStream
输入流:BufferedInputStream
字符流:
输出流:BufferedWriter
输入流:BufferedReader
作用:
磁盘一次可以读取多个字节/字符,如果一次只读取一个字节/字符降低程序的效率。所以字节流和字符流都支持一次读取多个字节符:
字节流:int read(byte[] byteArray)
字符流:int read(char[] charArray)
这个参数数组,就类似于一个“缓存区”,这样可以提高程序运行的效率。基于这种原因,Java类库中提供对字节流、字符流都提供了“自带缓存区”的“缓冲流”,可以提高程序的运行效率。
特点:
字节缓冲流:没有特有功能,只是内部提供了缓存区而已;
public static void main(String[] args) {
long start = System.currentTimeMillis();
// copy1();//273253 毫秒!
//高效缓冲流复制
// copy2();//9682 毫秒!
// copy3();//6209 毫秒!
// copy4();//4365 毫秒!
long end = System.currentTimeMillis();
System.out.println("复制时间:" + (end - start) + " 毫秒!");
}
//高效缓冲流--一次读写一个字节数组
private static void copy4() {
try (
BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\douyu.exe"));
BufferedOutputStream bufOut=new BufferedOutputStream(
new FileOutputStream("e:\\douyu_copy4.exe"))) {
//一次读写一个字节数组
byte[] byteArray = new byte[1024];
int b = 0;
while ((b = bufIn.read(byteArray)) != -1) {
bufOut.write(byteArray,0,b);
}
System.out.println("复制完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//基本字节流--一次读写一个字节数组
private static void copy3() {
//基本字节流复制
try (FileInputStream in = new FileInputStream("d:\\douyu.exe");
FileOutputStream out = new FileOutputStream(
"e:\\douyu_copy3.exe")
) {
//一次读写一个字节数组
byte[] byteArray = new byte[1024];
int b = 0;
while ((b = in.read(byteArray)) != -1) {
out.write(byteArray,0,b);
}
System.out.println("完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//高效字节流--一次读写一个字节
private static void copy2() {
try (
BufferedInputStream bufIn = new BufferedInputStream(
new FileInputStream("d:\\douyu.exe"));
BufferedOutputStream bufOut=new BufferedOutputStream(
new FileOutputStream("e:\\douyu_copy2.exe"))) {
//一次读写一个字节
int b = 0;
while ((b = bufIn.read()) != -1) {//从缓存区读
bufOut.write(b);
}
System.out.println("复制完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//基本字节流复制--一次读写一个字节
private static void copy1() {
//基本字节流复制
try (FileInputStream in = new FileInputStream("d:\\douyu.exe");
FileOutputStream out = new FileOutputStream(
"e:\\douyu_copy1.exe")
) {
//一次读写一个字节
int b = 0;
while ((b = in.read()) != -1) {//从磁盘读
out.write(b);
}
System.out.println("完毕!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
字符缓冲流:有
public static void main(String[] args) {
try (BufferedWriter out = new BufferedWriter(
new FileWriter("demo10.txt"));
BufferedReader in = new BufferedReader(
new FileReader("demo10.txt"))
) {
//1.先输出
out.write("床前明月光");
out.newLine();//特有方法
out.write("疑是地上霜");
out.newLine();
out.write("举头望明月");
out.newLine();
out.write("低头思故乡");
out.flush();
//2.再读取
String row = null;
while((row = in.readLine()) != null){//特有方法
System.out.println(row);
}
} catch (IOException e) {
e.printStackTrace();
}
}