嵌入式软件开发培训笔记——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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值