一、Java IO
1、java中流的分類
按照流向分爲輸入流和輸出流 基類:InputStream OutputStream Reader Writer
按照編碼的方式分爲字節流和字符流
字節流就是二進制數據流 以Input/Output爲後綴
字符流 以Reader/Writer爲後綴
2、InputStream類是所有輸入類的父類,包含的主要方法如下:
1)、public int available() throws IOException
功能:返回當前流對象中還沒有被讀取的字節數量,即獲得流中數據長度
2)、public void close() throws IOException
功能:關閉當前流對象,釋放資源
3)、public void mark(int readlimit)
功能:爲流中當前位置設置標誌,使得以的可以從該位置繼續讀取
readlimit:流讀取的最大字節數
4):public int read(byte[] b) throws IOException
功能:按照流中的數據存儲順序依次進行讀取,最小單位是字節(byte)
5)、public long skip(long n) throws IOException
功能:跳過當前流對象中的n個字節
3、OutputStream類是所有輸出類的父類,包含的主要方法如下:
1)public int flush() throws IOException
功能:將當前流對象中的緩衝數據強制輸出,即實現立即輸出效果。
2)public void close() throws
IOException
功能:關閉當前流對象,釋放資源
3)public
int write(byte[] b) throws IOException
功能:按照數組b存儲順序依次寫入流中,最小單位是字節(byte)
4、Reader類是InputStream體系中的類
包含的主要方法與InputStream類似,功能大致相同,最大區別是讀取的數據單位是字符(char)。
5、Writer類是OutputStream體系中的類
包含的主要方法與OutputStream類似,功能大致相同,最大區別是寫入的數據單位是字符(char);
增加的部分方法:
append方法:將數據寫入流的末尾
write方法:增加了寫入字符串的方法
6、File類
java.io.File類封裝了文件對象
創建文件對象:
File myFile;
myFile = new File("xx.mp3"); //arg1是文件名
myFile = new FIle("lyrics","lzs.txt"); //arg1是路徑 arg2是文件名
在Java中,沒有表示文件路徑(目錄)的類,而是將文件路徑也當作文件來處理。
File對象常用方法
和文件名相關(String) |
getName()
|
getPath()
|
getAbsolutePath()
|
getParent()
|
boolean renameTo(File newName)
|
|
文件檢測(boolean)
|
exists()
|
canWrite()
|
canRead()
|
isFile()
|
isDirectory()
|
isAbsolute()
|
獲取常規文件信息 |
long lastModified()
|
long length()
|
boolean delete()
|
目錄操作 |
boolean mkdir()
|
String[] list() |
|
示例:
案例:將一段文字寫入文本文件
練習:將一幅圖片從D盤的某個目錄下,拷貝到E盤的某個目錄下,可以改文件名。
package copyphoto;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyPhoto {
public static void main(String[] args) {
byte []b = new byte[1024];
int len = 0;
FileInputStream fi= null;
FileOutputStream fo = null;
try {
fi = new FileInputStream("D:\\temp\\photo.jpg");
fo = new FileOutputStream("E:\\etemp\\photo.jpg");
try {
while((len = fi.read(b)) != -1) {
String str = new String(b, 0, len);
fo.write(b, 0, len);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fi != null) {
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fo != null) {
try {
fo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
7、寫入文件
通過OutputStream子類FileOutputStream
FileOutputStream foutput = new FileOutputStream("d:\\a.txt");
byte[] data =new byte[1024];
foutput.write(data);
通過Writer子類FileWriter
FileWriter fwrite = new FileWriter("d:\\a.txt");
char data[] = new char[1024];
fwrite.write(data);
8、BufferedReader/BufferedWriter
在IO操作時,爲了提高IO類的讀寫效率,提供了一類緩衝流,以便提高讀寫效率。
BufferedInputStream/BufferedOutputStream
BufferedReader/BufferedWriter
利用BufferedReader/BufferedWriter實現文件的拷貝操作
BufferedReader fbufread = new BufferedReader(new
FileReader("d:\\a.txt"));
BufferedWriter
fbufwrite = new BufferedWriter(new FileWriter("d:\\b.txt"));
String buf = null;
while((buf = fbufread.readLine()) != NULL)
{
fbufwrite.write(buf);
fbufwrite.write("\r\n");
}
二、Java網絡編程
1、java網絡編程技術
InetAddress類:該類表示一個IP地址,並將IP地址和域名相關的操作封裝在裏面。
InetAddress類中通過getByName方法獲得域名地址對象
InetAddress inet = InetAddress.getByName("www.baidu.com");
也可以通過ip地址
InetAddress inet = InetAddress.getByAddress("127.0.0.1");
獲得本地IP地址和主機名稱
InetAddress inet = InetAddress.getLocalHost();
::表示連續的0,如Linux系統/ect/hosts文件中
127.0.0.1 localhost localhost.localdomain.com
::1 localhost localhost.localdomain.com
dos命令行 命令:nsloopup www.baidu.com查看域名信息
2、Tcp編程
Tcp網絡通訊是一種固定的,可靠的連接方式。
java.net.Socket類代表了客戶端端。
java.net.ServerSocket類代表了服務器端。
在進行網絡編程時,底層細節已經進行很高的封裝,在實際編程中,只需要指定IP地址和端口,就可以建立連接。
1)Socket
Socket套接字是一種軟件形式的抽象,它用來描述兩臺機器之間的一個連接終端。可以想象機器之間有一條虛擬的網線,網線的每一端都插在“套接字”或者“插座”裏。
在java中,我們創建一個套接字,通過套接字連接兩個機器。從套接字得到我們想要的結果。我們使用套接字與使用一個文件類似。使用InputStream和OutputStream來讀和寫。
兩個基於數據流的套接字類:
ServerSocket:服務器用它來“偵聽”鏈接,ServerSocket通過accept方法來獲得一次鏈接,即返回一個實際的socket
Socket:客戶端用來建立連接
ServerSocket主要用來偵聽套接字連接請求,本身不是socket,無法接收實際的數據包。創建ServerSocket的時候,不必爲其分配IP。
創建Socket時,需要爲其分配IP以及端口號。
編程步驟:
客戶端:
a建立網絡連接
b交換數據
c關閉網絡連接
服務器端
a監聽端口
b獲得連接
c交換數據
d關閉連接
需要一個ServerSocket監聽端口
ServerSocket myserversocket = new ServerSocket(10000);
需要一個Socket傳遞信息
Socket mysocket = myServerSocket.accept();
通過Socket獲得輸入流和輸出流
InputStream in = mysocket.getInputStream();
OutputStream out = mysocket.OutputStream();
ISO網絡模型:
第一層 物理層 脈衝信號
第二層 數據鏈路層 幀Frame MAC
第三層 網絡層 包Package IP地址
第四層 傳輸層 段segment
第五層 會話層
第六層 表示層
第七層 應用層
示例1:TcpServer class服務器端
package cn.com.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcpserver {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8000);
Socket s = ss.accept();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf, 0, 1024); //讀不到時return -1;
String str = new String(buf, 0, len);
System.out.println(str);
s.close();
ss.close();
}
}
示例1:TCPClient class客戶端
package cn.com.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class Tcpclient {
public static void main(String[] args) throws IOException {
Socket s = new Socket(InetAddress.getByName("192.168.1.101"), 8000);
OutputStream out = s.getOutputStream();
out.write("你好啊,我是TCP客戶端".getBytes());
s.close();
}
}
3、UDP網絡通訊
UDP編程中需要用到DatagramSocket對象來發送和接收數據。
netstat -ano | findstr "8888"用來查看端口號
發送端:
package cn.com.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UdpSend {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
DatagramSocket ds = new DatagramSocket();
byte[] buf = "你好啊,我是UDP!".getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.101"), 8888);
ds.send(dp);
ds.close();
}
}
接收端:
package cn.com.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UdpReceive {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(8888, InetAddress.getByName("192.168.1.101"));
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 100);
ds.receive(dp);
String name = dp.getAddress().getHostName();
int port = dp.getPort();
String str = new String(buf, 0, dp.getLength());
System.out.println("遠程主機名:"+name);
System.out.println("端口號:"+port);
System.out.println("發送過來的信息是:"+str);
ds.close();
}
}
練習:寫一個聊天程序
package cn.com.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Udpchat {
public static void main(String[] args) {
try {
new Thread(new Receiver(new DatagramSocket(8000))).start();
new Thread(new Sendor(new DatagramSocket())).start();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
}
}
class Sendor implements Runnable{
DatagramSocket ds;
public Sendor(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while((line=br.readLine()) != null){
if(line.equals("stop")){
System.out.println("發送端關閉");
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"),8000); //192.168.1.255爲廣播地址
ds.send(dp);
}
} catch (IOException e) {
e.printStackTrace();
}finally
{
try {
br.close();
ds.close();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
}
class Receiver implements Runnable{
DatagramSocket ds;
public Receiver(DatagramSocket ds){
this.ds = ds;
}
@Override
public void run() {
try {
while(true){
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(),0, dp.getLength());
if(data.equals("886")){
System.out.println("接收端關閉");
break;
}
System.out.println(ip+":"+port+">"+data);
}
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e)
{
e.printStackTrace();
}finally
{
ds.close();
}
}
}
作業:
1、從A主機上發送一張圖片文件到B主機關上
2、將一個文本文件把第個字符都使用按位異或加密,傳輸到另外一臺主機上,然後解密保存文件。
三、反射
1、概念
指程序可以訪問、檢測和修改它自身行爲和狀態的能力。
Java反身機制是在運行狀態中,對於任意一個類, 都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法;同時還可以獲得類的實例,這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
2、學習反射的目的
爲了使代碼更加通用,更加高效。
多用於框架、工具和組件中,寫出擴展性高的代碼。(Android底層中)
3、反射所涉及的類有:
Class類
Field類(屬性類)
Method類(方法類)
Constructor類(構造器)
Class類位於java.lang包下,在程序運行期間,java運行時系統始終爲所有的對象維護一個被稱爲運行時類型標識的類狀態信息。這些信息被保存在一個Class對象中。簡單的理解爲:內在中的字節碼文件。
當某個“普通”類被裝載入系統時,JVM將爲其產生一個Class對象。同時根據類中的構造器、變量和方法,在內在中產生對應的Constructor對象、Field對象、Method對象。
其他類的對象要獲取它們的引用,必須首先獲得Class對象。
4、如何獲得Class對象
獲得Class對象的三種方法:
1)、在未知類時,通過完整的類名來獲得Class對象。(常用)
例如:Class c = Class.forName("java.lang.xxx");
2)、通過類名class獲得
例如:String class;
3)、通過對象獲得
例如:String s = new String("abc");
Class c = s.getClass();
示例:
5、Constructor類對象獲得方式
1)、得到所有的構造器
public Constructor<?>[]getConstructors() throws SecurityException 返回所有的public修飾的構造器對象
例如:Constructor[] ss = cls.getConstructor();
2)、public Constructor<T>getConstructor(Class<?>...parameterTypes) throws NoSuchMethodException, SecurityException
例如:Constructor c1 = cls.getConstructor(String
class);
Constructor
c1 = cls.getConstructor();
3)、使用反射創建類的對象
T newInstance()
反射機制的體現:
Class cls ------ Constructor c (構造器對象) ------ newInstance(創建對象)
示例:
6、Field類的訪問(示例見7下)
1)、設置訪問權限
public
static void setAccessible(AccessibleObject[] array, boolean flag) throws SecurityException
2)、訪問與設置
public Object get(Object
obj) throws IllegalArgumentException, IllegalAccessException
public void set(Object obj, Object value) throws IllegalArgumentException,
IllegalAccessException
反射機制的體現
Class cls-----Field(域對象)-----訪問與設置域
7、Method類的操作與Field的操作類似
所涉及的API
1)、獲得所有publi方法
Method[] ms1 = cls.getMethods();
2)、獲得所有的本類方法
Method[] ms2 = cls.getDeclaredMethods();
3)、獲得指定的成員方法
Method m1 = cls.get.getDeclaredmethod("say", String.class);
4)、通過反射執行方法
成員方法:invoke(Object, Object...args)
表態方法:invoke(null, Object...args)
反射機制的體現
Class cls ------ Method (方法對象) ----- invoke (調用方法)
示例:(綜合6、7)
1、概念
從Java1.1開始,Java Native Interface(JNI)標準成爲java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是爲了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他語言,只要調用約定受支持就可以了。使用java與本地已編譯的代碼交互,通常會喪失平臺可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬件、操作系統進行交互,或者爲了提高程序的性能。JNI標準至少保證本地代碼能工作在任何Java 虛擬機環境下。
2、書寫步驟(方法)
1)、寫程序
2)、編譯Test.java(最好在命令行下操作)
javac Test.java生成Test.class
3)、生成頭文件Test.h
javah Test生成Test.h
4)、VC++中新建一個動態鏈接庫項目,編寫C/C++文件Test.cpp
#include "jni.h"
#include "Test.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_Test_displayhelloworld(JNIEnv, jobject)
{
printf("Hello World!\n");
return;
}
5)、添加JDK的include文件路徑
VC++中“工具”---->“選項”----->“目錄”添加JDK\include JDK\include\win32 java_prog(Test.h的目錄),然後"build"
6)、將生成的Test.dll拷貝到java_prog
7)、回到命令行運行java Test