7

[Java基础教程]第十二章-Java输入输出流

 2 years ago
source link: https://blogread.cn/it/article/7899?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

[Java基础教程]第十二章-Java输入输出流

浏览:1475次  出处信息

虽然计算机的历史才六七十年,但是研究机器计算的历史非常久远,历史上很多杰出的数学家使用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 [email protected]
* @date 2016年2月12日 下午9:14:24
*/
public class FileTest {
/**
* @Title main
* @Description 测试File类
* @param args
* @return void
*
* @author sunhaojie [email protected]
* @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 [email protected]
* @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 [email protected]
* @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();
}
}

建议继续学习:

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK