[Java基础教程]第十二章-Java输入输出流
虽然计算机的历史才六七十年,但是研究机器计算的历史非常久远,历史上很多杰出的数学家使用10进制进行了大量的研究,20世纪人类使用电位表示2进制(0,1),计算机才有了飞速的发展。计算机的存储和网络传输都是2进制,每个位为一个bit,每8bit为一个字节。后来计算机的用途逐渐从纯粹的数学计算扩展到各个方面,为了表示文字使用固定2进制串表示各种字符集,这种方式叫编码。目前存在的编码方式各种各样,其中我们会用到的包括ASCII主要表示英文相关字母和符号,GBK编码双字节表示中文常用字符集,UTF-8使用1-3个字节常用中文字符集。如果不涉及与GBK字符集编码的应用交互,最好使用UTF-8字符集进行开发。
日常开发中经常会有访问文件的场景,Java为这种场景提供了几个工具类。
public static void main(String[] args) throws IOException { File fileTest = new File("test.txt");// 这里不是真的创建一个文件 System.out.println("文件是否存在:" + fileTest.exists()); if (!fileTest.exists()) { fileTest.createNewFile();// 这里才是创建文件 } System.out.println("第二次检查文件是否存在:" + fileTest.exists()); System.out.println("文件路径:" + fileTest.getAbsolutePath()); }
上面的代码的功能是:获取一个文件句柄,如果文件不存在则创建文件,打印文件的绝对路径。运行上面的代码后刷新一下工程文件,看是否创建一个了个”test.txt”的文件。
File文件类,描述文件(无论是否存在)的信息,exists检查文件是否存在,createNewFile创建文件,getAbsolutePath获取文件绝对路径。有绝对路径就有相对路径,这里的相对路径是指相对于运行时的跟路径,“File fileTest = new File(“test.txt”);”就是使用的相对路径,根据打印的结果我们可以看出来工程运行的根路径为”D:itemslearntest”(不同的机器路径不一样),就是工程的根路径。
根据后缀名(.txt)可以看出,我们创建的是一个文本文件,老规矩向文件中输入“Hello World,你好中国”。
FileOutputStream fos = new FileOutputStream(fileTest);// 文件输出字节流 OutputStreamWriter osw = new OutputStreamWriter(fos);// 字节流向字符流转换 默认为UTF-8编码方式 BufferedWriter bw = new BufferedWriter(osw);// 缓存字符输出流 bw.write("Hello World,你好中国"); bw.flush(); // 刷新缓存,防止未写入文件 bw.close(); // 流关闭 osw.close(); // 流关闭 fos.close(); // 流关闭 System.out.println("写入完毕");
Java的文件访问方式经常被吐槽,使用太复杂,各种流类型不断转换 ,如下图所示:
通常文件(文本文件)的访问需要至少3个流,因为文件的存储和传输都是2进制数字,所以先获取字节流OutputStream/InputStream,然后把字节流使用相应的编码方式转换成字符流Writer/Reader,字符流只能单字符传输效率太低,所以又引入一个缓冲字符流BufferedWriter/BufferedReader,缓冲区满了才做输入或者输出操作。BufferedWriter.write(String)作用是把参数的字符串输入到文件中,如果需要换行字符串中添加”n”就可以。如果入参数据太少可能会导致缓冲区没有写满,如果我们不调用flush,可能数据没有真正的写入文件,所以使用BufferedWriter写入后一定要flush。最后记得关闭流,否则可能导致内存丢失。当我们运行多次后,发现文件中仍然就一句”Hello World,你好中国”,内容覆盖了,所以如果需要在文件尾部添加需要使用BufferedWriter.append(String),并且FileOutputStream初始化时设置是否追加为true。
FileInputStream pis = new FileInputStream(fileTest, true); InputStreamReader isr = new InputStreamReader(pis); BufferedReader br = new BufferedReader(isr); String line = br.readLine();// 先读取一行 while (line != null) { // 如果不为空继续读取直到为Null System.out.println(line); line = br.readLine(); } br.close(); isr.close(); pis.close();
读取文件时,因为无法确定文件的有多少数据,所以要循环读取直到没有数据返回。
除了文件中读取数据,通过网络也可以读取或者写入数据,同样是使用输入输出流交互,下面我们做一个简单的服务器和客户端的交互测试。
public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("监听IP:" + serverSocket.getInetAddress().getLocalHost().getHostAddress() + "; 监听端口:" + serverSocket.getLocalPort()); Socket acceptSocket = serverSocket.accept(); InputStream inputStream = acceptSocket.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println("客户输入:" + line); } br.close(); isr.close(); serverSocket.close(); System.out.println("输出结束"); }
启动后使用telnet客户端可以连接并交互:
启动链接telnet 192.168.0.6 8080,注意ip和端口换成自己的
交互结果,分别输入了”hello”和”bye”
public static void main(String[] args) throws UnknownHostException, IOException { Socket socket = new Socket("127.0.0.1", 8080); OutputStream outputStream = socket.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( outputStream)); writer.write("hin"); writer.flush(); writer.write("my name is lilein"); writer.flush(); writer.write("byen"); writer.flush(); writer.close(); outputStream.close(); socket.close(); }
通过网络的数据交互使用的也是输入流和输出流,多了ServerSocket,Socket用于描述网络连接。网络就是IP:Port进行连接的。
小练习:
读取练习工程中所有的java文件,并统计字母a-z出现的次数(不区分大小写)。
课程中使用的代码:
package com.sunhaojie.learntest.twelfth; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; /** * @ClassName FileTest * @Description 文件测试类 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月12日 下午9:14:24 */ public class FileTest { /** * @Title main * @Description 测试File类 * @param args * @return void * * @author sunhaojie 3113751575@qq.com * @throws IOException * @date 2016年2月12日 下午9:14:25 */ public static void main(String[] args) throws IOException { File fileTest = new File("test.txt");// 这里不是真的创建一个文件 System.out.println("文件是否存在:" + fileTest.exists()); if (!fileTest.exists()) { fileTest.createNewFile();// 这里才是创建文件 } System.out.println("第二次检查文件是否存在:" + fileTest.exists()); System.out.println("文件路径:" + fileTest.getAbsolutePath()); FileOutputStream fos = new FileOutputStream(fileTest, true);// 文件输出字节流 OutputStreamWriter osw = new OutputStreamWriter(fos);// 字节流向字符流转换 默认为UTF-8编码方式 BufferedWriter bw = new BufferedWriter(osw);// 缓存字符输出流 bw.write("Hello World,你好中国n"); bw.append("Hello World,你好中国n"); bw.flush(); // 刷新缓存,防止未写入文件 bw.close(); // 流关闭 osw.close(); // 流关闭 fos.close(); // 流关闭 System.out.println("写入完毕"); FileInputStream pis = new FileInputStream(fileTest); InputStreamReader isr = new InputStreamReader(pis); BufferedReader br = new BufferedReader(isr); String line = br.readLine();// 先读取一行 while (line != null) { // 如果不为空继续读取直到为Null System.out.println(line); line = br.readLine(); } br.close(); isr.close(); pis.close(); } } package com.sunhaojie.learntest.twelfth; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * * @ClassName SocketServerTest * @Description 服务器端测试类 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月12日 下午10:53:45 */ public class SocketServerTest { @SuppressWarnings("static-access") public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("监听IP:" + serverSocket.getInetAddress().getLocalHost().getHostAddress() + "; 监听端口:" + serverSocket.getLocalPort()); Socket acceptSocket = serverSocket.accept(); InputStream inputStream = acceptSocket.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println("客户输入:" + line); } br.close(); isr.close(); serverSocket.close(); System.out.println("输出结束"); } } package com.sunhaojie.learntest.twelfth; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; /** * * @ClassName SocketClientTest * @Description 测试端输出类 * * @author sunhaojie 3113751575@qq.com * @date 2016年2月12日 下午10:54:03 */ public class SocketClientTest { public static void main(String[] args) throws UnknownHostException, IOException { Socket socket = new Socket("127.0.0.1", 8080); OutputStream outputStream = socket.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( outputStream)); writer.write("hin"); writer.flush(); writer.write("my name is lilein"); writer.flush(); writer.write("byen"); writer.flush(); writer.close(); outputStream.close(); socket.close(); } }
建议继续学习:
- 避免输入 (阅读:2258)
- 触摸屏输入的交互设计 (阅读:2191)
- PHP里模拟$_PUT (阅读:1910)
- [Java基础教程]第十三章-Java多线程 (阅读:2166)
- [Java基础教程]第十一章-Java类和对象 (阅读:2093)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:sunhaojie 来源: 孙豪杰的博客
- 标签: Java基础教程 输入 输出
- 发布时间:2016-03-15 23:35:34
- [54] Oracle MTS模式下 进程地址与会话信
- [54] Go Reflect 性能
- [54] IOS安全–浅谈关于IOS加固的几种方法
- [53] 如何拿下简短的域名
- [52] android 开发入门
- [49] 图书馆的世界纪录
- [48] 读书笔记-壹百度:百度十年千倍的29条法则
- [47] 【社会化设计】自我(self)部分――欢迎区
- [38] 程序员技术练级攻略
- [31] 视觉调整-设计师 vs. 逻辑