从流动方向来看,input代表从读取外部文件内容到java程序里,ouput代表从内存写入数据到文件里
https://blog.csdn.net/qq_34626097/article/details/84112199
程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
- 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
- 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
https://www.cnblogs.com/wxgblogs/p/5647415.html
一般output,input都是相对于当前运行的内存。
//解读以下
PrintWriter pw = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("pw2.txt")
, "UTF-8")
)
);
FileOutputStream:输出节点流
OutputStream(OutputStream out, String charsetName): 使用指定的字符集将字符编码为字节
out:字节输出流,可以用来写转换之后的字节到文件中
charsetName:指定的编码表名称,不区分大小写,可以是utf-8/UTF-8,gbk/GBK,...不指定默认使用UTF-8
BufferedReader和BufferedWriter是带有默认缓冲区的字符输入输出流,其效率相较于没有缓冲区要高:
1.java.io.BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读
取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
2. 从标准输入流System.in中直接读取使用者输入时,使用者每输入一个字符,System.in就读取一个字符。为了能
一次读取一行使用者的输入,使用了BufferedReader来对使用者输入的字符进行缓冲。readLine()方法会在读取到使用者的换行字符时,再一次将整行字符串传入。
3. System.in是一个位流,为了转换为字符流,可使用InputStreamReader为其进行字符转换,然后再使用Buffer
edReader为其增加缓冲功能。
—————————————————————————————————
综合案例 https://segmentfault.com/a/1190000012316621
printWrite 不开自动刷, 会等缓冲区数据到一定大小,才会从缓冲区写入
public class MyServer {
private static ExecutorService executorService = Executors.newCachedThreadPool(); //创建一个线程池
//一旦有新的客户端请求,创建这个线程进行处理
private static class HandleMsg implements Runnable{
Socket client; //创建一个客户端
public HandleMsg(Socket client){ //构造传参绑定
this.client = client;
}
@Override
public void run() {
BufferedReader bufferedReader = null; //创建字符缓存输入流
PrintWriter printWriter = null; //创建字符写入流
try {
//1,从client中获得输入流,用于读取client输入内容;
//2,基于以上节点流转换为inputstreamreader处理(转换流,实现字节-字符转换
//3,根据以上处理流创建缓冲流,优化性能
//获取客户端的输入流
bufferedReader = new BufferedReader(new InputStreamReader(client.getInput
Stream()));
//获取客户端的输出流,true是随时刷新,等待写入;
printWriter = new PrintWriter(client.getOutputStream(),true);
String inputLine = null;
long a = System.currentTimeMillis();
while ((inputLine = bufferedReader.readLine())!=null){
printWriter.println(inputLine);
}
long b = System.currentTimeMillis();
System.out.println("此线程花费了:"+(b-a)+"秒!");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bufferedReader.close();
printWriter.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws IOException { //服务端的主线程是用来循环监听客户端请求
ServerSocket server = new ServerSocket(8686); //创建一个服务端且端口为8686
Socket client = null;
while (true){ //循环监听
client = server.accept(); //服务端监听到一个客户端请求
System.out.println(client.getRemoteSocketAddress()+"地址的客户端连接成功!");
executorService.submit(new HandleMsg(client)); //将该客户端请求通过线程池放入HandlMsg线程中进行处理
}
}
}
public class MyClient {
public static void main(String[] args) throws IOException {
Socket client = null;
PrintWriter printWriter = null;
BufferedReader bufferedReader = null;
try {
client = new Socket();
client.connect(new InetSocketAddress("localhost",8686));
printWriter = new PrintWriter(client.getOutputStream(),true);
printWriter.println("hello");
printWriter.flush();
bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream())); //读取服务器返回的信息并进行输出
System.out.println("来自服务器的信息是:"+bufferedReader.readLine());
} catch (IOException e) {
e.printStackTrace();
}finally {
printWriter.close();
bufferedReader.close();
client.close();
}
}
}
零拷贝收集:
mmap,sendfile,DMA gather 知乎 https://zhuanlan.zhihu.com/p/357820303