字符编码
在实际开发中,常用的编码有如下几种:
- GBK/GB2312:国标编码,可以描述中文信息,其中GB2312只描述简体中文,而GBK包含简体中文和繁体中文;
- ISO8859-1:国际通用编码:可以用其描述所有的字母信息,如果是象形文字,则需要进行编码处理;
- UNICODE编码:采用十六进制的方式,可以描述所有文字信息;
- UTF编码:象形文字部分使用UNICODE编码,而普通的字母采用 ISO8859-1编码,它的优势在于适合快速的传输,节约带宽,也就成为了开发中首选的编码,主要使用“UTF-8”编码。
如果要想知道当前系统中支持的编码规则,则可以采用如下代码列出全部的本机属性。
范例:列出本机属性
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
System.getProperties().list(System.out);
}
}
- 文件的路径分割符:file.separator=/;
- 文件默认编码:file.encoding=UTF-8;
也就是说如果现在什么都不设置,则采用的编码就是UTF-8;
范例:编写程序
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
OutputStream output=new FileOutputStream(new File("/Users/fzc/Documents/mydir/mldn.txt"));
output.write("中华人民共和国万岁".getBytes());
output.close();
}
}
范例:强制性设置编码
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
OutputStream output=new FileOutputStream(new File("/Users/fzc/Documents/mydir/mldn.txt"));
output.write("中华人民共和国万岁".getBytes("utf-8"));
// output.write("中华人民共和国万岁".getBytes("ISO8859-1"));//乱码
output.close();
}
}
项目中出现的乱码问题就是编码和解码标准不统一,而解决乱码最常用的方式就是所有的编码都采用“utf-8”。
内存操作流
在之前使用的全部都是文件操作流,文件操作流的特点:程序利用InputStream读取文件内容,而后程序利用OutputStream向文件输出内容,所有的操作都是以文件为终端的。
文件流如果说现在需要实现IO操作,又不希望产生文件(临时文件),则就可以以内存为终端进行处理,这个时候的流程为:
内存流在Java中提供提供了两类的内存操作流:
- 字节内存操作流:ByteArrayOutputStream、ByteArrayInputStream
- 字符内存操作流:CharArrayWriter、CharArrayReader
下面使用ByteArrayOutputStream和ByteArrayInputStream类为主进行内存的使用分析,首先分析各自的构造方法:
- ByteArrayInputStream构造:public ByteArrayInputStream(byte[] buf);
- ByteArrayOutputStream构造:public ByteArrayOutputStream();
在ByteArrayOutputStream类中有两个很重要的方法,这两个个方法可以获取全部保存在内存流中的数据信息: - 获取数据:public byte[] toByteArray();
- 使用字符串的形式获取:public String toString();
范例:利用内存流实现一个小写字母转大写字母的操作
import java.io.*;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
String str="www.baidu.com";
InputStream input=new ByteArrayInputStream(str.getBytes());//将数据保存在内存流
OutputStream output=new ByteArrayOutputStream();//读取内存中的数据
int data=0;
while ((data=input.read())!=-1){//每次读取一个字节
output.write(Character.toUpperCase((char)data));//保存数据
}
System.out.println(output.toString());//WWW.BAIDU.COM
input.close();
output.close();
}
}
如果不希望只是以字符串的形式返回,因为可能存放的是其他二进制的数据,那么此时就可以利用OutputStream的子类ByteArrayOutputStream的扩展功能获取全部字节数据。
import java.io.*;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
String str="www.baidu.com";
InputStream input=new ByteArrayInputStream(str.getBytes());//将数据保存在内存流
ByteArrayOutputStream output=new ByteArrayOutputStream();//读取内存中的数据
int data=0;
while ((data=input.read())!=-1){//每次读取一个字节
output.write(Character.toUpperCase((char)data));//保存数据
}
byte[] result=output.toByteArray();//自己处理字节数据
System.out.println(new String(result));//WWW.BAIDU.COM
input.close();
output.close();
}
}
在最初的时候,可以利用ByteArrayOutputStream实现大规模文本文件读取。
管道流
管道流主要功能是实现两个线程之间的IO处理操作。
管道流对于管道流也分为两类
-
字节管道流:PipedOutputStream、PipedInputStream
- 连接处理:public void connect(PipedInputStream snk) throws IOException;
-
字符管道流:PipedWriter、PipedReader
- 连接处理:public void connect(PipedReader snk) throws IOException;
范例:实现管道操作
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
SendThread send=new SendThread();
ReceiveThread receive=new ReceiveThread();
send.getOutput().connect(receive.getInput());//进行管道连接
new Thread(send,"消息发送线程").start();
new Thread(receive,"消息接收线程").start();
/**
* 【第1次信息发送 - 消息发送线程】www.baidu.com
* 【第2次信息发送 - 消息发送线程】www.baidu.com
* 【第3次信息发送 - 消息发送线程】www.baidu.com
* 【第4次信息发送 - 消息发送线程】www.baidu.com
* 【第5次信息发送 - 消息发送线程】www.baidu.com
* 【第6次信息发送 - 消息发送线程】www.baidu.com
* 【第7次信息发送 - 消息发送线程】www.baidu.com
* 【第8次信息发送 - 消息发送线程】www.baidu.com
* 【第9次信息发送 - 消息发送线程】www.baidu.com
* 【第10次信息发送 - 消息发送线程】www.baidu.com
*/
}
}
class SendThread implements Runnable{
private PipedOutputStream output;//管道输出流
public SendThread() {
this.output = new PipedOutputStream();//实例化管道输出流
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
output.write(("【第"+(i+1)+"次信息发送 - "+Thread.currentThread().getName()+"】www.baidu.com\n").getBytes());
}catch (IOException e){
e.printStackTrace();
}
}
try {
this.output.close();
}catch (IOException e){
e.printStackTrace();
}
}
public PipedOutputStream getOutput(){
return output;
}
}
class ReceiveThread implements Runnable{
private PipedInputStream input;
public ReceiveThread() {
input=new PipedInputStream();
}
@Override
public void run() {
byte[] data = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();//所有的数据保存到内存输出流
try {
while ((len = input.read(data)) != -1) {
bos.write(data, 0, len);
}
System.out.println(new String(bos.toByteArray()));
bos.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public PipedInputStream getInput() {
return input;
}
}
管道中一个负责发送,一个负责接收,中间靠一个管道连接。
网友评论