字符編碼
??在實(shí)際開發(fā)中,常用的編碼有如下幾種:
- GBK/GB2312:國標(biāo)編碼私植,可以描述中文信息官边,其中GB2312只描述簡體中文,而GBK包含簡體中文和繁體中文锄贼;
- ISO8859-1:國際通用編碼:可以用其描述所有的字母信息票灰,如果是象形文字,則需要進(jìn)行編碼處理宅荤;
- UNICODE編碼:采用十六進(jìn)制的方式屑迂,可以描述所有文字信息;
- UTF編碼:象形文字部分使用UNICODE編碼冯键,而普通的字母采用 ISO8859-1編碼惹盼,它的優(yōu)勢在于適合快速的傳輸,節(jié)約帶寬惫确,也就成為了開發(fā)中首選的編碼手报,主要使用“UTF-8”編碼。
??如果要想知道當(dāng)前系統(tǒng)中支持的編碼規(guī)則改化,則可以采用如下代碼列出全部的本機(jī)屬性掩蛤。
范例:列出本機(jī)屬性
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
System.getProperties().list(System.out);
}
}
- 文件的路徑分割符:file.separator=/;
- 文件默認(rèn)編碼:file.encoding=UTF-8陈肛;
??也就是說如果現(xiàn)在什么都不設(shè)置揍鸟,則采用的編碼就是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();
}
}
范例:強(qiáng)制性設(shè)置編碼
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();
}
}
??項(xiàng)目中出現(xiàn)的亂碼問題就是編碼和解碼標(biāo)準(zhǔn)不統(tǒng)一句旱,而解決亂碼最常用的方式就是所有的編碼都采用“utf-8”阳藻。
內(nèi)存操作流
??在之前使用的全部都是文件操作流晰奖,文件操作流的特點(diǎn):程序利用InputStream讀取文件內(nèi)容,而后程序利用OutputStream向文件輸出內(nèi)容腥泥,所有的操作都是以文件為終端的匾南。
??如果說現(xiàn)在需要實(shí)現(xiàn)IO操作,又不希望產(chǎn)生文件(臨時(shí)文件)道川,則就可以以內(nèi)存為終端進(jìn)行處理午衰,這個(gè)時(shí)候的流程為:
??在Java中提供提供了兩類的內(nèi)存操作流:
- 字節(jié)內(nèi)存操作流:ByteArrayOutputStream、ByteArrayInputStream
- 字符內(nèi)存操作流:CharArrayWriter冒萄、CharArrayReader
??下面使用ByteArrayOutputStream和ByteArrayInputStream類為主進(jìn)行內(nèi)存的使用分析臊岸,首先分析各自的構(gòu)造方法:
- ByteArrayInputStream構(gòu)造:public ByteArrayInputStream?(byte[] buf);
- ByteArrayOutputStream構(gòu)造:public ByteArrayOutputStream()尊流;
??在ByteArrayOutputStream類中有兩個(gè)很重要的方法帅戒,這兩個(gè)個(gè)方法可以獲取全部保存在內(nèi)存流中的數(shù)據(jù)信息: - 獲取數(shù)據(jù):public byte[] toByteArray();
- 使用字符串的形式獲妊录肌:public String toString()逻住;
范例:利用內(nèi)存流實(shí)現(xiàn)一個(gè)小寫字母轉(zhuǎn)大寫字母的操作
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());//將數(shù)據(jù)保存在內(nèi)存流
OutputStream output=new ByteArrayOutputStream();//讀取內(nèi)存中的數(shù)據(jù)
int data=0;
while ((data=input.read())!=-1){//每次讀取一個(gè)字節(jié)
output.write(Character.toUpperCase((char)data));//保存數(shù)據(jù)
}
System.out.println(output.toString());//WWW.BAIDU.COM
input.close();
output.close();
}
}
??如果不希望只是以字符串的形式返回,因?yàn)榭赡艽娣诺氖瞧渌M(jìn)制的數(shù)據(jù)迎献,那么此時(shí)就可以利用OutputStream的子類ByteArrayOutputStream的擴(kuò)展功能獲取全部字節(jié)數(shù)據(jù)瞎访。
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());//將數(shù)據(jù)保存在內(nèi)存流
ByteArrayOutputStream output=new ByteArrayOutputStream();//讀取內(nèi)存中的數(shù)據(jù)
int data=0;
while ((data=input.read())!=-1){//每次讀取一個(gè)字節(jié)
output.write(Character.toUpperCase((char)data));//保存數(shù)據(jù)
}
byte[] result=output.toByteArray();//自己處理字節(jié)數(shù)據(jù)
System.out.println(new String(result));//WWW.BAIDU.COM
input.close();
output.close();
}
}
??在最初的時(shí)候,可以利用ByteArrayOutputStream實(shí)現(xiàn)大規(guī)模文本文件讀取吁恍。
管道流
??管道流主要功能是實(shí)現(xiàn)兩個(gè)線程之間的IO處理操作扒秸。
??對于管道流也分為兩類
-
字節(jié)管道流:PipedOutputStream、PipedInputStream
??- 連接處理:public void connect?(PipedInputStream snk) throws IOException冀瓦;
-
字符管道流:PipedWriter伴奥、PipedReader
??- 連接處理:public void connect?(PipedReader snk) throws IOException;
范例:實(shí)現(xiàn)管道操作
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());//進(jìn)行管道連接
new Thread(send,"消息發(fā)送線程").start();
new Thread(receive,"消息接收線程").start();
/**
* 【第1次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第2次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第3次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第4次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第5次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第6次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第7次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第8次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第9次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
* 【第10次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
*/
}
}
class SendThread implements Runnable{
private PipedOutputStream output;//管道輸出流
public SendThread() {
this.output = new PipedOutputStream();//實(shí)例化管道輸出流
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
output.write(("【第"+(i+1)+"次信息發(fā)送 - "+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();//所有的數(shù)據(jù)保存到內(nèi)存輸出流
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;
}
}
??管道中一個(gè)負(fù)責(zé)發(fā)送翼闽,一個(gè)負(fù)責(zé)接收拾徙,中間靠一個(gè)管道連接。
RandomAccessFile類
??對于文件內(nèi)容的處理操作主要通過InputStream(Reader)感局、OutputStream(Writer)來實(shí)現(xiàn)尼啡,但是利用這些類實(shí)現(xiàn)的內(nèi)容讀取,只能夠?qū)?shù)據(jù)部分部分讀取進(jìn)來蓝厌,如果說現(xiàn)在有這樣一種需求玄叠。
??現(xiàn)在有一個(gè)20G大小的文件,如果按照傳統(tǒng)的IO操作進(jìn)行讀取和分析很明顯不能很好的完成拓提,所以這種情況下在java.io包中提供了一個(gè)RandomAccessFile類读恃,這個(gè)類可以實(shí)現(xiàn)文件的跳躍式的讀取,可以只讀取中間的部分內(nèi)容(前提:需要有一個(gè)完善的保存形式),數(shù)據(jù)的保存位數(shù)要確定好寺惫。
??RandomAccessFile類中定義有如下的操作方法:
- 構(gòu)造方法:
??public RandomAccessFile?(File file, String mode) throws FileNotFoundException
??- 文件處理模式:r疹吃、rw;
范例:實(shí)現(xiàn)文件的保存
import java.io.File;
import java.io.RandomAccessFile;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
String dirPath = "/Users/fzc/Documents/mydir/mldn_save.txt";//定義操作的文件
File file = new File(dirPath);
RandomAccessFile raf=new RandomAccessFile(file,"rw");//讀寫模式
String[] names=new String[]{"zhangsan","wangwu ","lisi "};
int[] ages=new int[]{30,20,16};
for (int i = 0; i < names.length; i++) {
raf.write(names[i].getBytes());
raf.writeInt(ages[i]);
}
raf.close();
}
}
??RandomAccessFile最大的特點(diǎn)是在于數(shù)據(jù)的讀取處理上西雀,因?yàn)樗械臄?shù)據(jù)是按照固定的長度進(jìn)行保存的萨驶,所以讀取時(shí)就可以進(jìn)行跳字節(jié)讀取:
??向下跳:public int skipBytes?(int n) throws IOException艇肴;
腔呜;
??向上跳:public void seek?(long pos) throws IOException;
再悼;
范例:讀取數(shù)據(jù)
import java.io.File;
import java.io.RandomAccessFile;
public class JavaApiDemo {
public static void main(String[] args) throws Exception {
String dirPath = "/Users/fzc/Documents/mydir/mldn_save.txt";//定義操作的文件
File file = new File(dirPath);
RandomAccessFile raf=new RandomAccessFile(file,"rw");//讀寫模式
//讀取"lisi"數(shù)據(jù)核畴,跳過24位
raf.skipBytes(24);
byte[] data=new byte[8];
int len=raf.read(data);
System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:lisi 冲九、年齡:16
//讀取"wangwu"數(shù)據(jù)谤草,回跳到12位
raf.seek(12);
data=new byte[8];
len=raf.read(data);
System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:wangwu 莺奸、年齡:20
//讀取"zhangsan"數(shù)據(jù)丑孩,回跳到0位
raf.seek(0);
data=new byte[8];
len=raf.read(data);
System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:zhangsan灭贷、年齡:30
}
}
??整體的使用之中由用戶自行定義要讀取的位置温学,而后按照指定的結(jié)構(gòu)進(jìn)行數(shù)據(jù)的讀取。