Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,又称万国码。由Ken Thompson于1992年创建。现在已经标准化为RFC 3629。UTF-8用1到6个字节编码UNICODE字符。用在网页上可以同一页面显示中文简体繁体及其它语言(如英文,日文,韩文)。
GBK编码,是在GB2312-80标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),共23940个码位,共收录了21003个汉字,完全兼容GB2312-80标准,支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。GBK编码方案于1995年10月制定, 1995年12月正式发布,目前中文版的WIN95、WIN98、WINDOWS NT以及WINDOWS 2000、WINDOWS XP、WIN 7等都支持GBK编码方案。

————————————————————————————————————————-

虽然计算机的历史才六七十年,但是研究机器计算的历史非常久远,历史上很多杰出的数学家使用10进制进行了大量的研究,20世纪人类使用电位表示2进制(0,1),计算机才有了飞速的发展。计算机的存储和网络传输都是2进制,每个位为一个bit,每8bit为一个字节。后来计算机的用途逐渐从纯粹的数学计算扩展到各个方面,为了表示文字使用固定2进制串表示各种字符集,这种方式叫编码。目前存在的编码方式各种各样,其中我们会用到的包括ASCII主要表示英文相关字母和符号,GBK编码双字节表示中文常用字符集,UTF-8使用1-3个字节常用中文字符集。如果不涉及与GBK字符集编码的应用交互,最好使用UTF-8字符集进行开发。

日常开发中经常会有访问文件的场景,Java为这种场景提供了几个工具类。

[code lang=”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());
}
[/code]

上面的代码的功能是:获取一个文件句柄,如果文件不存在则创建文件,打印文件的绝对路径。运行上面的代码后刷新一下工程文件,看是否创建一个了个”test.txt”的文件。
File文件类,描述文件(无论是否存在)的信息,exists检查文件是否存在,createNewFile创建文件,getAbsolutePath获取文件绝对路径。有绝对路径就有相对路径,这里的相对路径是指相对于运行时的跟路径,“File fileTest = new File(“test.txt”);”就是使用的相对路径,根据打印的结果我们可以看出来工程运行的根路径为”D:itemslearntest”(不同的机器路径不一样),就是工程的根路径。

根据后缀名(.txt)可以看出,我们创建的是一个文本文件,老规矩向文件中输入“Hello World,你好中国”。

[code lang=”java”]
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("写入完毕");
[/code]

Java的文件访问方式经常被吐槽,使用太复杂,各种流类型不断转换 ,如下图所示:

输入输出流

通常文件(文本文件)的访问需要至少3个流,因为文件的存储和传输都是2进制数字,所以先获取字节流OutputStream/InputStream,然后把字节流使用相应的编码方式转换成字符流Writer/Reader,字符流只能单字符传输效率太低,所以又引入一个缓冲字符流BufferedWriter/BufferedReader,缓冲区满了才做输入或者输出操作。BufferedWriter.write(String)作用是把参数的字符串输入到文件中,如果需要换行字符串中添加”n”就可以。如果入参数据太少可能会导致缓冲区没有写满,如果我们不调用flush,可能数据没有真正的写入文件,所以使用BufferedWriter写入后一定要flush。最后记得关闭流,否则可能导致内存丢失。当我们运行多次后,发现文件中仍然就一句”Hello World,你好中国”,内容覆盖了,所以如果需要在文件尾部添加需要使用BufferedWriter.append(String),并且FileOutputStream初始化时设置是否追加为true。

[code lang=”java”]
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();
[/code]

读取文件时,因为无法确定文件的有多少数据,所以要循环读取直到没有数据返回。

除了文件中读取数据,通过网络也可以读取或者写入数据,同样是使用输入输出流交互,下面我们做一个简单的服务器和客户端的交互测试。

[code lang=”java”]
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("输出结束");
}
[/code]

启动后使用telnet客户端可以连接并交互:
启动链接telnet 192.168.0.6 8080,注意ip和端口换成自己的

telnet连接

交互结果,分别输入了”hello”和”bye”

telnet连接输出结果
下面我们再看一下测试客户端代码:

[code lang=”java”]
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();
}
[/code]

通过网络的数据交互使用的也是输入流和输出流,多了ServerSocket,Socket用于描述网络连接。网络就是IP:Port进行连接的。

小练习:
读取练习工程中所有的java文件,并统计字母a-z出现的次数(不区分大小写)。

课程中使用的代码:

[code lang=”java”]
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();
}
}
[/code]

****************************************************************************************************
****************************************************************************************************
*******                                     Java免费在线培训学员招募                                          *******
****************************************************************************************************
****************************************************************************************************