java第22天----編碼問題,網路通訊,TCP,
文章目錄
昨天知識總結
- 1.轉換流
- 2.多個輸入源輸出源的組合
- 3.更換輸入源輸出源
- 4.列印流
- 位元組列印流
- 字元列印流
- 5.序列流,資料流,記憶體流
- 6.Properties
- 7.序列化流
編碼問題
- 轉換流的編碼:
- 常用字符集:
- 中國的:GBK/GB2312---------2個位元組
- 歐洲的:ISO8859-1---------不支援中文,但是一個漢字對應1個位元組
- 國標:UTF-8---------3個位元組
- 內部編碼:unicode------2個位元組
- 美國的:ASCII
- 編碼:由字串轉成byte的過程
- 解碼:由byte轉成字串的過程
- 亂碼:編碼與解碼的過程中,使用了不同的字符集,造成編碼錯誤,出現了亂碼
- 常見的出現亂碼的組合:
- 使用GBK編碼,ISO8859-1解碼 或者UTF-8編碼,ISO8859-1解碼
- 舉例:使用GBK編碼,UTF-8解碼 或者UTF-8編碼,GBK解碼
public static void main(String[] args) throws IOException {
//寫的時候採用UTF-8編碼
writeData1();
readData1();//使用utf-8字符集
readData2();//使用GBK字符集
//寫的時候採用GBK編碼
writeData2 ();
readData3();//使用utf-8字符集
readData4();//使用GBK字符集
}
//寫出
//編碼格式是utf-8
public static void writeData1() throws IOException {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("utf8.txt"),"utf-8");
outputStreamWriter.write("冰冰");
outputStreamWriter.close();
}
//寫出
//編碼格式是GBK
public static void writeData2() throws IOException {
//建立輸出流並關聯檔案 第一個引數是位元組輸出流 第二個引數是:輸出時指定的編碼格式
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("GBK.txt"),"GBK");//預設GBK
outputStreamWriter.write("冰冰");
outputStreamWriter.close();
}
//讀入
//編碼格式是utf8
public static void readData1() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("utf8.txt"),"utf-8");
char[] arr = new char[100];
int num = inputStreamReader.read(arr);
System.out.println("readData1:"+new String(arr,0,num));
inputStreamReader.close();
}
//讀入
//編碼格式是GBK
public static void readData2() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("utf8.txt"),"GBK");//預設utf8
char[] arr = new char[100];
int num = inputStreamReader.read(arr);
System.out.println("readData2:"+new String(arr,0,num));
inputStreamReader.close();
}
//讀入
//編碼格式是utf8
public static void readData3() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("GBK.txt"),"utf-8");
char[] arr = new char[100];
int num = inputStreamReader.read(arr);
System.out.println(new String(arr,0,num));
inputStreamReader.close();
}
//讀入
//編碼格式是utf8
public static void readData4() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("GBK.txt"),"GBK");//預設GBK
char[] arr = new char[100];
int num = inputStreamReader.read(arr);
System.out.println(new String(arr,0,num));
inputStreamReader.close();
}
- 研發中的編碼:
- 說明:GBK,UTF-8是支援中文的,ISO8859-1不支援中文
- 編碼:
- byte[] getBytes() //對於中文 預設的格式
- 使用平臺的預設字符集將此 String 編碼為 byte 序列,
- 並將結果儲存到一個新的 byte 陣列中。
- byte[] getBytes(Charset charset)
- 使用給定的 charset 將此 String 編碼到 byte 序列,並將結果儲存到新的 byte 陣列。
- 解碼:
- String(byte[] bytes) //對於中文 預設是格式
- 通過使用平臺的預設字符集解碼指定的 byte 陣列,構造一個新的 String。
- String(byte[] bytes, Charset charset)
- 通過使用指定的 charset 解碼指定的 byte 陣列,構造一個新的 String。
public static void main(String[] args) throws UnsupportedEncodingException {
//使用GBK編碼解碼
String s1 = "你好";
byte[] bs1 = s1.getBytes("GBK");//編碼
System.out.println(new String(bs1,"GBK"));
System.out.println(Arrays.toString(bs1));
//使用UTF-8編碼解碼
String s2 = "你好";
byte[] bs2 = s1.getBytes("UTF-8");//編碼
System.out.println(new String(bs2,"UTF-8"));
System.out.println(Arrays.toString(bs2));
//使用ISO8859-1編碼解碼
String s3 = "你好";
byte[] bs3 = s1.getBytes("ISO8859-8");//編碼
System.out.println(new String(bs3,"ISO8859-8"));
System.out.println(Arrays.toString(bs3));
}
解決亂碼
- 解決亂碼:
- 出現的情況:編碼與解碼字符集不一樣
- 解決方法:通過再編碼再解碼解決亂碼,但是實在保證第一次編碼沒有問題的前提下
- 是否可以採用在編碼再解碼解決
編碼 | 解碼 | 可行性 |
---|---|---|
GBK | UTF-8 | 不可以 |
GBK | ISO8859-8 | 可以 |
UTF | GBK | 不可以 |
UTF | ISO8859-8 | 可以 |
ISO8859-1 | GBK | 不可以(編碼就出錯了) |
ISO8859-1 | UTF-8 | 不可以(編碼就出錯了) |
public static void main(String[] args) throws UnsupportedEncodingException {
//1.GBK編碼 UTF-8解碼
// String s1 = "你好";
// byte[] bs1 = s1.getBytes("GBK");
// String strbs1 = new String(bs1, "utf-8");
// System.out.println("utf8解碼:"+strbs1);//utf8解碼:���
//
// //再編碼
// byte[] bs11 = strbs1.getBytes("utf-8");
// //再解碼
// System.out.println(new String(bs11,"GBK"));//錕斤拷錕�
//2.GBK編碼 ISO8859-1解碼
// String s1 = "你好";
// byte[] s1b = s1.getBytes("GBK");
// String sr1b = new String(s1b,"ISO8859-1");
// System.out.println("ISO8859-1解碼:"+sr1b);//????
//
// //再編碼
// byte[] s1bb = sr1b.getBytes("ISO8859-1");
// //再解碼
// System.out.println("GBK再編碼:"+new String(s1bb,"GBK"));//你好
//3.utf8編碼 GBK解碼
String s1 = "你好啊";
byte[] s1b = s1.getBytes("utf-8");
String sr1b = new String(s1b,"GBK");
System.out.println("GBK解碼:"+sr1b);//浣犲ソ鍙?
//再編碼
byte[] s1bb = sr1b.getBytes("GBK");
//再解碼
System.out.println("utf8再編碼:"+new String(s1bb,"utf-8"));//你好??
//4.utf8編碼 ISO8859-1解碼
// String s1 = "你好號";
// byte[] s1b = s1.getBytes("utf-8");
// String sr1b = new String(s1b,"ISO8859-1");
// System.out.println("ISO8859-1解碼:"+sr1b);//????????·
//
// //再編碼
// byte[] s1bb = sr1b.getBytes("ISO8859-1");
// //再解碼
// System.out.println("utf8再編碼:"+new String(s1bb,"utf-8"));//你好號
}
網路通訊
- 網路程式設計的基礎
- 網路的通訊:三要素:協議,IP,埠
- 1.IP:在網路上惟一的標記一臺主機 127.0.0.1:保留地址,本地地址 javajiang IP面向物件了形成的類叫InetAddress
- 2.埠:區分一臺主機上的多個服務區,取值範圍為(0,65535) 注意:在通訊時要保證客戶和伺服器端使用的埠號一致
- 3.協議:制定的一個統一的標準
七層協議
-
七層協議:
-
應用層:與其他計算機進行通訊的一個應用,它是對應應用程式的通訊服務的。例如:一個沒有通訊功能的自處理程式就不能執行通訊程式碼,從事字處理工作的程式設計師也不關心OSI的第7層。但是,如果添加了一個傳輸檔案的選項,那麼字處理器的程式設計師就需要實現OSI的第七層。
-
示例:TELNET HTTP FTP NFS SMTP等。
-
表示層
-
這一層的主要功能是定義資料格式及加密,例如,FTP允許比選擇以二進位制或ASCII格式傳輸,如果選擇二進位制,那麼傳送方和接收方不改變檔案的內容。如果選擇ASCII格式,傳送放將把文字從傳送方的字符集轉換成標準的ASCII後傳送資料。在接受方將標準的ASCII轉換成接收方計算機的字符集。
- 例項:加密,ASCII等
-
會話層:
-
他定義瞭如何開始。控制和結束一個回話,包括對多個雙向訊息的控制和管理,一遍在只完成連續訊息的一部分是可以通知應用,從而使表示層看到的資料是連續的,在某些情況下,如果表示層收到了所有的資料,則用資料代表表示層。、
- 例項RPC,SQL等
-
傳輸層
-
這層的功能包括是否選擇差錯恢復協議還是無差錯恢復協議,及在統一主機上對不同應用的資料流的輸入進行服用,還包括對收到的順序不對的資料包的重新排序功能,
- 示例:TCP,UDP,SXP。
-
網路層
-
這層對端到端的包傳輸進行定義,它定義了能夠標識所有結點的邏輯地址,還定義了路由實現的方式和學習的方式。為了適應最大傳輸單元長度小於包長度的傳輸介質, 網路層還定義瞭如何將一個包分解成更小的包的分段方法。
-
示例:IP,IPX等。
-
資料鏈路層 它定義了在單個鏈路上如何傳輸資料。這些協議與被討論的各種介質有關。
- 示例:ATM,FDDI等。
-
物理層
-
OSI的物理層規範是有關傳輸介質的特性標準,這些規範通常也參考了其他組織制定的標準。連線頭、幀、幀的使用、電流、編碼及光調製等都屬於各種物理層規範中的內容。物理層常用多個規範完成對所有細節的定義。
-
示例:Rj45,802.3等
獲取主機
public static void main(String[] args) throws UnknownHostException {
//IP地址:java面向物件後形成的類InetAddress
//獲取自己的主機
InetAddress address1 = InetAddress.getLocalHost();
System.out.println(address1.getHostName());
System.out.println(address1.getHostAddress());
//獲取網路上任意一臺主機
InetAddress address2 = InetAddress.getByName("www.baidu.com");//域名
System.out.println(address2.getHostName());
System.out.println(address2.getHostAddress());
}
TCP/UDP
- 網路通訊之Socket通訊:TCP/UDP
- TCP與UDP通訊的區別:
- TCP與UDP通訊的區別:
TCP | UDP |
---|---|
是建立在連線的基礎上 | 建立在非連線的基礎上 |
安全性高 | 安全性低 |
傳輸速度低 | 速度高 |
4.適合傳輸資料量大的資料 | 資料量小的資料 |
- 客戶端(app/瀏覽器)
- 伺服器端:!=主機
- 埠號:同一臺主機上的每一個伺服器的都擁有自己的埠號,取值範圍(0,65535),常用的埠:80,8080
- 注意點:
- 1.要保證客戶端和伺服器端的埠號一致
- 2.要保證同一臺主機上的不同伺服器埠號不同
UDP
- 客戶端
- 實現過程:
- 1.建立UDP通訊的物件----socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送與接收)
- 2.資料的封裝–裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
- 3.傳送–呼叫send方法傳送
- 4.關閉資源
public static void main(String[] args) throws IOException {
// * 1.建立UDP通訊的物件----socket物件,對應的類是DatagramSocket(用於UDP通訊資料的傳送與接收)
DatagramSocket datagramSocket = new DatagramSocket();
// * 2.資料的封裝--裝包(打包),DatagramPacket(資料包,包括相關的屬性,資料等)
/*
* 第一個引數:包的內容
* 第二個引數:資料的長度
* 第三個引數:副武器的主機物件
* 第四個引數:伺服器的埠
*/
byte[] buf = "bingbing".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length, InetAddress.getLocalHost(),20000);//埠與伺服器一致
// * 3.傳送--呼叫send方法
datagramSocket.send(datagramPacket);
// * 4.關閉資源
datagramSocket.close();
}
- 伺服器端----接受資料
- 1.建立socket物件,繫結埠
- 2.建立包物件,建立空陣列,準備接受傳過來的資料
- 3.接收資料
- 4.關閉資源
public static void main(String[] args) throws IOException {
// * 1.建立socket物件
DatagramSocket Socket = new DatagramSocket(20000);
// * 2.建立包物件,建立空陣列,準備接受傳過來的資料
byte[] buf = new byte[1024];
DatagramPacket Packet = new DatagramPacket(buf, buf.length);
// * 3.接收資料--當伺服器運轉起來,這個方法會一致處於堅挺狀態。
Socket.receive(Packet);
//將資料從包中取出
byte[] arr = Packet.getData();
System.out.println(new String(arr));
// * 4.關閉資源
Socket.close();
}
TCP
- 客戶端
- 在使用者端與伺服器端通訊的時候,對於客戶端既要進行輸入又要進行輸出,所以Socket物件的內部就內建了輸入流和輸出流
- 當進行資料傳輸的時候,將資料放入socket物件的內部,將socket物件傳到伺服器端,相當於在客戶端與伺服器端建立了一個通道,
- 兩者使用同一個socket物件。
public static void main(String[] args) throws UnknownHostException, IOException {
//1.建立Socket物件,並繫結伺服器的埠和主機地址
Socket socket = new Socket(InetAddress.getLocalHost(),30000);
//2.準備資料
String data = "BigData1715,你好";
//3.獲取Socket物件內部的輸出流
OutputStream outputStream = socket.getOutputStream();
//4.將資料寫入網路
outputStream.write(data.getBytes());
//接收從伺服器回傳的資料
InputStream inputStream = socket.getInputStream();
byte[] bs = new byte[103];
int num = 0;
num = inputStream.read(bs);
System.out.println(new String(bs,0,num));
//資料的關閉
outputStream.close();
socket.close();
}
- 伺服器端
public static void main(String[] args) throws IOException {
//1.建立ServerSocket物件並繫結埠
ServerSocket serverSocket = new ServerSocket(30000);
//2.接收套接字---socket物件accept()方法會一直處於監聽狀態
Socket socket = serverSocket.accept();
//3.獲取輸入流
InputStream inputStream = socket.getInputStream();
//4.將內容寫到控制檯
byte[] bs = new byte[3];
int num = 0;
num = inputStream.read(bs);
System.out.println(new String(bs,0,num));
// while((num = inputStream.read(bs))!= -1) {
// System.out.print(new String(bs,0,num));
// }
System.out.println("qersadfseara");
//完成資料的回傳
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好,BigData1715".getBytes());
//5.關閉流
outputStream.close();
serverSocket.close();
}