嵌入式軟件開發培訓筆記——java第六天(IO、網絡編程、反射與JNI)

一、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[] bthrows 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類
    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)
        
四、JNI(參考百度百科)
    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章