## IO流
字節流:處理字節數據的流對象,計算機中最小數據單元就是字節。InputStream OutputStream
字符流:字符編碼問題,將字節流和編碼表封裝成對象就是字符流。Reader Write
讀、寫都會發生 IO 異常。io 異常的處理方式 :io 一定要寫 finally。fw.flush();//刷新緩沖區,fw.close();//關閉流。
~~~
IO 中的使用到了一個設計模式: 裝飾設計模式。
裝飾設計模式解決:對一組類進行功能的增強。
包裝:寫一個類(包裝類)對被包裝對象進行包裝;
* 1、包裝類和被包裝對象要實現同樣的接口;
* 2、包裝類要持有一個被包裝對象;
* 3、包裝類在實現接口時,大部分方法是靠調用被包裝對象來實現的,對于需要修改的方法我們自己實現;
~~~
### 字符流
- Reader : 用于讀取字符流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。
- Writer : 寫入字符流的抽象類。子類必須實現的方法僅有 write(char[], int, int)、flush() 和 close()。
### 字節流
InputStream、OutputStream
~~~
BufferedWriter :是給字符輸出流提高效率用的,那就意味著,緩沖區對象建立時,必須要先有流對象。明
確要提高具體的流對象的效率。
FileWriter fw = new FileWriter("bufdemo.txt");
BufferedWriter bufw = new BufferedWriter(fw); // 讓緩沖區和指定流相關聯。
for(int x=0; x<4; x++){
bufw.write(x+"abc");
bufw.newLine(); // 寫入一個換行符,這個換行符可以依據平臺的不同寫入不同的換行符。
bufw.flush();//對緩沖區進行刷新,可以讓數據到目的地中。
}
bufw.close(); // 關閉緩沖區,其實就是在關閉具體的流。
-----------------------------
BufferedReader :
FileReader fr = new FileReader("bufdemo.txt");
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){ e //readLine 方法返回的時候是不帶換行符的。
System.out.println(line);
}
bufr.close();
-----------------------------
//記住,只要一讀取鍵盤錄入,就用這句話。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));//輸出到控制臺
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
51 / 65
bufw.write(line.toUpperCase());//將輸入的字符轉成大寫字符輸出
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
~~~
流的操作規律:
-
1 ,明確源和目的。
數據源:就是需要讀取,可以使用兩個體系:InputStream、Reader;
數據匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;
-
2 ,操作的數據是否是純文本數據?
如果是:數據源:Reader
數據匯:Writer
如果不是:數據源:InputStream
數據匯:OutputStream
- 3 ,雖然確定了一個體系,但是該體系中有太多的對象,到底用哪個呢?
明確操作的數據設備。
數據源對應的設備:硬盤(File),內存(數組),鍵盤(System.in)
數據匯對應的設備:硬盤(File),內存(數組),控制臺(System.out)。
- 4 ,需要在基本操作上附加其他功能嗎?比如緩沖。
如果需要就進行裝飾。
### File類
- 將文件系統中的文件和文件夾封裝成了對象。提供了更多的屬性和行為可以對這些文件和文件夾
進行操作。這些是流對象辦不到的,因為流只操作數據。
- createNewFile() 、mkdir()、getAbsolutePath()
### 遞歸
使用情況:功能內部又用到該功能,但是傳遞的參數值不確定。
- 遞歸的注意事項:
1:一定要定義遞歸的條件。
2:遞歸的次數不要過多。容易出現 StackOverflowError 棧內存溢出 錯誤。
其實遞歸就是在棧內存中不斷的加載同一個函數。
Java遞歸算法的小例子 求1+2+3…+1000 和
~~~
public class Test1 {
int sum=0;
int a=1;
public void sum()
{
sum+=a;
a++;
if(a<=1000)
{
sum();//調用自身實現遞歸
}
}
public static void main(String[] args) {
Test1 test=new Test1();
test.sum();
System.out.println("計算結果:"+test.sum+"!");
}
~~~
### 擴展功能的流對象
### PrintStream : 打印流
- PrintStream m 可以操作目的:1:File 對象。2:字符串路徑。3:字節輸出流。
- PrintWriter :該對象的目的地有四個:1:File 對象。2:字符串路徑。3:字節輸出流。4:字符輸出流。
- PrintWriter out = new PrintWriter( new FileWriter(“out.txt”), true);//設置 true 后自動刷新
- System.in,System.out 這兩個標準的輸入輸出流,在 jvm 啟動時已經存在了。隨時可以使用。當
jvm 結束了,這兩個流就結束了。但是,當使用了顯示的 close 方法關閉時,這兩個流在提前結束了。
### SequenceInputStream : 序列流
作用就是將多個讀取流合并成一個讀取流實現數據合并。
- 合并原理:多個讀取流對應一個輸出流。
切割原理:一個讀取流對應多個輸出流。
### 管道流
管道讀取流和管道寫入流可以像管道一樣對接上,管道讀取流就可以讀取管道寫入流寫入的數據。
注意 :需要加入多線程技術,因為單線程,先執行 read,會發生死鎖,因為 read 方法是阻塞式的,沒有數據的
read 方法會讓線程等待。
~~~
public static void main(String[] args) throws IOException{
PipedInputStream pipin = new PipedInputStream();
PipedOutputStream pipout = new PipedOutputStream();
pipin.connect(pipout);
new Thread(new Input(pipin)).start();
new Thread(new Output(pipout)).start();
}
~~~
### 對象序列化
靜態數據不能被序列化,因為靜態數據不在堆內存中;用transient關鍵字修飾變量,可以將非靜態數據不進行序列化。
-
Serializable :用于啟動對象的序列化功能,可以強制讓指定類具備序列化功能,該接口中沒有成員,這是一
個標記接口。
-
ByteArrayInputStream : 源 : 內存
ByteArrayOutputStream :目的:內存。
這兩個流對象不涉及底層資源調用,操作的都是內存中數組,所以不需要關閉。
## 網絡編程
端口:0-65535
~~~
//通過名稱(ip 字符串 or 主機名)來獲取一個 ip 對象。
InetAddress ip = InetAddress.getByName("www.baidu.com");//java.net.UnknownHostException
~~~
### socket
為網絡服務提供的一種機制,通信的兩端都有 Socket,網絡通信其實就是 Socket 間的通信,數據在兩個
Socket 間通過 IO 傳輸。
### udp傳輸
數據一定要封裝到數據包中,數據包中包括目的地址、端口、數據等信息。將 udp 封裝成對象,易于我們的使用,這個對象就是 DatagramSocket
發送端:
1,建立 udp 的 socket 服務,創建對象時如果沒有明確端口,系統會自動分配一個未被使用的端口。
2,明確要發送的具體數據。
3,將數據封裝成了數據包。
4,用 socket 服務的 send 方法將數據包發送出去。
5,關閉資源。
~~~
import java.net.*;
class UdpSend{
public static void main(String[] args)throws Exception {
// 1 1 ,建立 p udp 的 的 t socket 服務。
DatagramSocket ds = new DatagramSocket(8888);//指定發送端口,不指定系統會隨機分配。
// 2 2 ,明確要發送的具體數據。
String text = "udp 傳輸演示 哥們來了";
byte[] buf = text.getBytes();
// 3 3 ,將數據封裝成了數據包。
DatagramPacket dp = new DatagramPacket(buf,
buf.length,InetAddress.getByName("10.1.31.127"),10000);
// 4 4 ,用 t socket 服務的 d send 方法將數據包發送出去。
ds.send(dp);
// 5 5 ,關閉資源。
ds.close();
}
}
~~~
p udp 的接收端:
1,創建 udp 的 socket 服務,必須要明確一個端口,作用在于,只有發送到這個端口的數據才是這個接收端可
以處理的數據。
2,定義數據包,用于存儲接收到數據。
3,通過 socket 服務的接收方法將收到的數據存儲到數據包中。
4,通過數據包的方法獲取數據包中的具體數據內容,比如 ip、端口、數據等等。
5,關閉資源。
~~~
class UdpRece {
public static void main(String[] args) throws Exception{
// 1 1 ,創建 p udp 的 的 t socket 服務。
DatagramSocket ds = new DatagramSocket(10000);
// 2 2 ,定義數據包,用于存儲接收到數據。先定義字節數組,數據包會把數據存儲到字節數組中。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
// 3 3 ,通過 t socket 服務的接收方法將收到的數據存儲到數據包中。
ds.receive(dp);//該方法是阻塞式方法。
// 4 4 ,通過數據包的方法獲取數據包中的具體數據內容,比如 ip ,端口,數據等等。
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = new String(dp.getData(),0,dp.getLength());//將字節數組中的有效部分轉成字符串。
System.out.println(ip+":"+port+"--"+text);
// 5 5 ,關閉資源。
ds.close();
}
}
~~~
### tcp傳輸
兩個端點的建立連接后會有一個傳輸數據的通道,這通道稱為流,而且是建立在網絡基礎上的流,
稱之為 socket 流。該流中既有讀取,也有寫入。
TCP 客戶端 :
1,建立 tcp 的 socket 服務,最好明確具體的地址和端口。這個對象在創建時,就已經可以對指定 ip 和端口
進行連接(三次握手)。
2,如果連接成功,就意味著通道建立了,socket 流就已經產生了。只要獲取到 socket 流中的讀取流和寫入
流即可,只要通過 getInputStream 和 getOutputStream 就可以獲取兩個流對象。
3,關閉資源。
~~~
import java.net.*;
import java.io.*;
//需求:客戶端給服務器端發送一個數據。
class TcpClient{
public static void main(String[] args) throws Exception{
Socket s = new Socket("10.1.31.69",10002);
OutputStream out = s.getOutputStream();// 獲取了 t socket 流中的輸出流對象。
out.write("tcp 演示,哥們又來了!".getBytes());
s.close();
}
}
~~~
TCP 服務端:
1,創建服務端 socket 服務,并監聽一個端口。
2,服務端為了給客戶端提供服務,獲取客戶端的內容,可以通過 accept 方法獲取連接過來的客戶端對象。
3,可以通過獲取到的 socket 對象中的 socket 流和具體的客戶端進行通訊。
4,如果通訊結束,關閉資源。注意:要先關客戶端,再關服務端。
~~~
class TcpServer{
public static void main(String[] args) throws Exception{
62 / 65
ServerSocket ss = new ServerSocket(10002);//建立服務端的 socket 服務
Socket s = ss.accept();//獲取客戶端對象
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
// 可以通過獲取到的 socket 對象中的 socket 流和具體的客戶端進行通訊。
InputStream in = s.getInputStream();//讀取客戶端的數據,使用客戶端對象的 socket 讀取流
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
// 如果通訊結束,關閉資源。 注意:要先關客戶端,在關服務端。
s.close();
ss.close();
}
}
~~~
### 反射技術
反射技術可以對一個類進行解剖。
- 基本步驟:
1 、 獲得 s Class 對象 ,就是獲取到指定的名稱的字節碼文件對象 。
2 、 實例化對象, 獲得類的屬性、方法或構造函數。
3、訪問屬性、調用方法、調用構造函數創建對象
## 正則表達式
- 常見操作:
1,匹配:其實用的就是 String 類中的 matches 方法。
String reg = “[1-9][0-9]{4,14}”;
boolean b = qq. matches(reg);//將正則和字符串關聯對字符串進行匹配。
2,切割:其實用的就是 String 類中的 split 方法。
3,替換:其實用的就是 String 類中的 replaceAll();
4,獲取:
1),先要將正則表達式編譯成正則對象。使用的是 Pattern 中靜態方法 compile(regex);
2),通過 Pattern 對象獲取 Matcher 對象。
Pattern 用于描述正則表達式,可以對正則表達式進行解析。
而將規則操作字符串,需要從新封裝到匹配器對象 Matcher 中。
然后使用 Matcher 對象的方法來操作字符串。
如何獲取匹配器對象呢?
通過 Pattern 對象中的 matcher 方法。該方法可以正則規則和字符串想關聯。并返回匹配器對象。
3),使用 Matcher 對象中的方法即可對字符串進行各種正則操作。
- 前言
- 內存溢出的解決方案
- 安卓消息推送解決方案
- 語言識別和聊天機器人的實現
- 抽屜效果的實現(DrawerLayout和SlidingMenu的對比)
- 植物大戰僵尸經典開發步驟
- 屏幕適配全攻略
- 安卓圖像處理入門教程
- android開發常用工具箱
- java基礎知識總結
- 剖析軟件外包項目
- java基礎知識——網絡編程、IO流
- 安卓性能優化手冊
- 電商活動中刮刮卡的實現
- Android系統的安全設計與架構
- AsnycTask的內部的實現機制
- Android應用UI設計流程
- 數據結構與算法,每日一道
- html5全解析
- 深入解讀XML解析
- 新聞客戶端案例開發
- 細說Http協議
- win10+ubuntu雙系統安裝方案
- 隨機驗證碼實現案例
- 動態數組的實現案例
- 猜拳游戲案例
- 商業級項目——基金客戶端的架構設計與開發(上)