欢迎来到Heck's Blog,专业承接拿站、企业建站、仿站、网上商城架构、门户网站搭建、空间域名注册、软件定制等项目。关注网络安全,因为专注,所以专业,懂得放弃,才能收获。有事请发邮件至i@heckjj.com,请记住本站网址:http://www.heckjj.com,多谢。
10月14

昨天我们谈了怎么建立socket通信的服务端和客户端,今天我们就来谈一谈怎么封装报文。

什么是报文这里我就不在阐述了,不清楚的朋友可以自己去查资料。我们今天要谈的报文主要友以下几个部分组成:

3位同步校验位+8位报文长度+报文头+报文体+32位MD5校验位

基本格式如下:

0X110X120X1300000232<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code><Name>张三</Name></ROOT>B251AB76B11114DB176023A0AA27A524

说明:

  前面的0X110X120X13是3位16进制的同部位,这里为了大家理解,所以就以字符的形式谢出来了。00000232是报文长度。<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code></ROOT>是报文头。即每个报文都包含的信息。<Name>张三</Name>是报文体。B251AB76B11114DB176023A0AA27A524是加密数据。

关于如何将对象转换为xml格式的报文我将在下一篇写,这里主要是给大家如何将如上的这些字符串转化为字节以及如何发送和接收报文。

1.建立报文的对象

public class SocketPacket {


    private String bodyLen;

    private String body;

    private String syncStr;

    private String md5;

    public String getBodyLen() {

        return bodyLen;

    }

    public String getBody() {

        return body;

    }

    public String getSyncStr() {

        return syncStr;

    }

    public String getMd5() {

        return md5;

    }

    public void setBodyLen(String bodyLen) {

        this.bodyLen = bodyLen;

    }

    public void setBody(String body) {

        this.body = body;

    }

    public void setSyncStr(String syncStr) {

        this.syncStr = syncStr;

    }

    public void setMd5(String md5) {

        this.md5 = md5;

    }

    

    

    public byte[] getByteStream() throws UnsupportedEncodingException{

        byte[] bodyBytes = this.body.getBytes("gbk");//获得body的字节数组

        int bodyLength = bodyBytes.length;

        int socketLength = 3+bodyLength+8+32;

        byte [] soc = new byte[socketLength];

        //添加校验数据

        int index = 0;

        soc[0]=0x11;

        soc[1]=0x12;

        soc[2]=0x13;

        index+=3;

        //添加8位报文长度(我的博文中也有NumberFormat的用法介绍)

        NumberFormat numberFormat = NumberFormat.getNumberInstance();

        numberFormat.setMinimumIntegerDigits(8);

        numberFormat.setGroupingUsed(false);

        byte [] num = numberFormat.format(socketLength).getBytes();

        for(int i = 0;i<8;i++){

            soc[index++]= num[i];

        }

        //添加body内容

        for(int i = 0;i<bodyLength;i++){

            soc[index++] = bodyBytes[i];

        }

        //添加md5校验码

        byte [] md5Bytes = this.md5.getBytes();

        for (int i = 0; i < num.length; i++) {

            soc[index++] = md5Bytes[i];

        }

        return soc;

    }

    

    //字节装转报文string

    public String getString(byte [] socketBytes){

        String syncStr = this.bytesToString(socketBytes, 0, 3);

        String socketLength = this.bytesToString(socketBytes, 3, 3+8);

        String body = this.bytesToString(socketBytes, 3+8, socketBytes.length-32);

        String md5 = this.bytesToString(socketBytes,socketBytes.length-32,socketBytes.length);

        return syncStr+socketLength+body+md5;

    }

    

    //将字节数组转化为string

    public String bytesToString(byte [] bytes,int start,int end){

        String str = "";

        if(bytes.length<end-start){

            return str;

        }

        byte [] bs = new byte[end-start];

        for(int i = 0;i<end-start;i++){

            bs[i] = bytes[start++];

        }

        str = new String(bs);

        return str;

    }

    

    public String toString(){

        return this.syncStr+this.bodyLen+this.body+this.md5;

    }

    

}


2.封装发送和接收报文的工具类

/**

* 报文发送

*/

public class SockeUtil {

    Socket socket = null;

    public SockeUtil(String ip,int port) throws UnknownHostException, IOException{

        socket = new Socket(ip, port);

    }

    //

    public SocketPacket sentSocket(SocketPacket socketPacket) throws UnsupportedEncodingException, IOException{

        SocketPacket sPacket = new SocketPacket();

        OutputStream output=null;

        InputStream input =null;

        // 同步字符串(3byte)

        byte[] sync = null; //

        byte[] bodyLen = null; // 8位长度

        byte[] body = null; // 内容

        byte[] md5 = null;  // MD5

        output = socket.getOutputStream();

        //写数据发送报文

        output.write(socketPacket.getByteStream());

        //获得服务端返回的数据

        input = socket.getInputStream();

        sync = this.streamToBytes(input,3);

        bodyLen = this.streamToBytes(input, 8);

        String lenString = new String(bodyLen);

        int len = Integer.valueOf(lenString);

        body = this.streamToBytes(input, len);

        md5 = this.streamToBytes(input, 32);

        sPacket.setSyncStr(new String(sync,Charset.forName("gbk")));

        socketPacket.setBodyLen(new String(bodyLen,Charset.forName("gbk")));

        socketPacket.setBody(new String(body,Charset.forName("gbk")));

        socketPacket.setMd5(new String(md5,Charset.forName("gbk")));

        return sPacket;

    }

    

    public byte[] streamToBytes(InputStream inputStream,int len){

        /**

         * inputStream.read(要复制到得字节数组,起始位置下标,要复制的长度)

         * 该方法读取后input的下标会自动的后移,下次读取的时候还是从上次读取后移动到的下标开始读取

         * 所以每次读取后就不需要在制定起始的下标了

         */

        byte [] bytes= new byte[len];

        try {

            inputStream.read(bytes, 0, len);

        } catch (IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        return bytes;

    }

}

3.在封装一个调用报文发送的类:

public String socket(SocketPackage socketPackage) throws UnsupportedEncodingException{

        

        SocketClient socketClient=null;;

        try {

            socketClient = new SocketClient(ip,端口);

        } catch (UnknownHostException e) {

            log.error("socket链接异常,链接信息:"+ip+端口);

            e.printStackTrace();

        } catch (IOException e) {

            log.error("socket IO异常");

            e.printStackTrace();

        }      

        SocketPackage s = null;

        try {

            s = socketClient.sendMsg(socketPackage);

        } catch (Exception e) {

            try {

                log.error("socket发送消息异常,发送信息:"+new String(socketPackage.getByteStream(),"GBK"));

            } catch (UnsupportedEncodingException e1) {

                log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());

                e1.printStackTrace();

            }

            e.printStackTrace();

        }      

        String result = "";

        try {

             result = new  String(s.getStream(),"GBK");

        } catch (UnsupportedEncodingException e) {

            log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());

            e.printStackTrace();

        }

        return result ;

  }

这样我们就能发送报文和接收报文了!赶紧试一下吧!^_^

10月14

今天来和大家分享一下java中如何使用socket进行通信。先来啰嗦两句,看看Tcp/ip和udp:

TCPTransfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送 或接收操作。

UDPUser Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

(一)两者之间的比较

UDP

  1. 每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
  2. UDP传输数据时有大小限制的,每个被传输的数据报必须限定在64KB之内
  3.  UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

TCP

  1. 面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中需要连接时间。
  2. TCP传输数据大小限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大的 数据。
  3. TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。

(二)应用

  1. TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP
  2. UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

注:以上内容是在网上找的,为了节省时间,我就不再自己写了。

 

下面我们来看看如何搭建socket环境:

     socket通信分为客户端和服务器端。服务器端会不停的监听,当服务器端监听到有客户端向其发送通信请求的时候,双方建立连接。通信完毕后,双方关闭连接。

 首先我们来看如何搭建客户端:

public class SocketClient {

    public static void main(String[] args) throws IOException{


    try{

            Socket socket=new Socket("127.0.0.1",5200);

            System.out.println("client start ...");

            //向本机的52000端口发出客户请求

            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

            //由系统标准输入设备构造BufferedReader对象

            PrintWriter write=new PrintWriter(socket.getOutputStream());

            //由Socket对象得到输出流,并构造PrintWriter对象

            BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //由Socket对象得到输入流,并构造相应的BufferedReader对象

            String readline;

            readline=br.readLine(); //从系统标准输入读入一字符串

            while(!readline.equals("end")){

                //若从标准输入读入的字符串为 "end"则停止循环

                write.println(readline);

                //将从系统标准输入读入的字符串输出到Server

                write.flush();

                //刷新输出流,使Server马上收到该字符串

                System.out.println("Client:"+readline);

                //在系统标准输出上打印读入的字符串

                System.out.println("Server:"+in.readLine());

                //从Server读入一字符串,并打印到标准输出上

                readline=br.readLine(); //从系统标准输入读入一字符串

            } //继续循环

            write.close(); //关闭Socket输出流

            in.close(); //关闭Socket输入流

            socket.close(); //关闭Socket                       

        }catch(Exception e) {

            System.out.println("can not listen to:"+e);//出错,打印出错信息

        }

    }


}

下面是服务器端得搭建:

public class SocketService {

    public static void main(String[] args) throws IOException{

        SocketService socketService = new SocketService();

        socketService.oneServer();

    }

    

    public  void oneServer(){

        try{

            ServerSocket server=null;

            try{

                server=new ServerSocket(5200);

                System.out.println("server start is ok...");

                //创建一个ServerSocket在端口5200监听客户请求

            }catch(Exception e) {

                    System.out.println("can not listen to:"+e);

                    //出错,打印出错信息

            }

            Socket socket=null;

            try{

                socket=server.accept();

                //使用accept()阻塞等待客户请求,有客户

                //请求到来则产生一个Socket对象,并继续执行

            }catch(Exception e) {

                System.out.println("Error."+e);

                //出错,打印出错信息

            }

            String line;

            BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //由Socket对象得到输入流,并构造相应的BufferedReader对象

            PrintWriter writer=new PrintWriter(socket.getOutputStream());

            //由Socket对象得到输出流,并构造PrintWriter对象

            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

            //由系统标准输入设备构造BufferedReader对象

            System.out.println("Client:"+in.readLine());

            //在标准输出上打印从客户端读入的字符串

            line=br.readLine();

            //从标准输入读入一字符串

            while(!line.equals("end")){

            //如果该字符串为 "bye",则停止循环

                writer.println(line);

                //向客户端输出该字符串

                writer.flush();

                //刷新输出流,使Client马上收到该字符串

                System.out.println("Server:"+line);

                //在系统标准输出上打印读入的字符串

                System.out.println("Client:"+in.readLine());

                //从Client读入一字符串,并打印到标准输出上

                line=br.readLine();

                //从系统标准输入读入一字符串

            } //继续循环

            writer.close(); //关闭Socket输出流

            in.close(); //关闭Socket输入流

            socket.close(); //关闭Socket

            server.close(); //关闭ServerSocket

        }catch(Exception e) {//出错,打印出错信息

            System.out.println("Error."+e);

        }

    }

}


这是我们先启动服务器端,再启动客户端(顺序不能乱),当我在客户端输入abc时,如下:

我们再打开服务器端得控制台,会看到客户端发送的消息:

然后我们再输入123:

我们再打开客户端得控制台:

这里显示了服务端回传的信息,证明我们的通信是没有问题的了。

以上的服务端只能监听一个客户端,要想是想监听多个客户端,我们对服务端做一下修改:

public  void manyServer() throws IOException{

     boolean flag = true;

      ServerSocket serverSocket = null;

      serverSocket = new ServerSocket(5200);

      int clientNum = 0;

      while(flag){

          new SocketServerTherd(serverSocket.accept(), clientNum).start();

          clientNum++;

      }

      serverSocket.close();

    }


public class SocketServerTherd extends Thread{

    Socket socket = null;

    int clientNum = 0;

     public SocketServerTherd(Socket socket,int num){

         this.socket = socket;

         this.clientNum = num+1;

     }

     public void run(){

         try{

             String line;

             BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));

             //由Socket对象得到输入流,并构造相应的BufferedReader对象

             PrintWriter writer=new PrintWriter(socket.getOutputStream());

             //由Socket对象得到输出流,并构造PrintWriter对象

             BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

             //由系统标准输入设备构造BufferedReader对象

             System.out.println("Client:"+in.readLine());

             //在标准输出上打印从客户端读入的字符串

             line=br.readLine();

             //从标准输入读入一字符串

             while(!line.equals("end")){

             //如果该字符串为 "bye",则停止循环

                 writer.println(line);

                 //向客户端输出该字符串

                 writer.flush();

                 //刷新输出流,使Client马上收到该字符串

                 System.out.println("Server:"+line);

                 //在系统标准输出上打印读入的字符串

                 System.out.println("Client:"+in.readLine());

                 //从Client读入一字符串,并打印到标准输出上

                 line=br.readLine();

                 //从系统标准输入读入一字符串

             } //继续循环

             writer.close(); //关闭Socket输出流

             in.close(); //关闭Socket输入流

             socket.close(); //关闭Socket             

         }catch(Exception e) {//出错,打印出错信息

             System.out.println("Error."+e);

         }

           

     }

}

今天就先说到这里吧,明天我将告诉大家如何利用报文进行通行。

9月28
最近和前端同学调试,发现我这里总是无法验证通过,因为他传给我的MD5和我生成的MD5总是对不上。

但是一开始的时候,我是验证了两边的方法的,以test为例

在页面的console中输入

MD5('test')
则输出结果为

098f6bcd4621d373cade4e832627b4f6

在java中的代为如下

System.out.println(DigestUtils.md5Hex("test"));
则输出的结果为

098f6bcd4621d373cade4e832627b4f6

通过对比可以发现是一致的,OK,那就开始调试吧,刚开始就出问题了,验证不通过

拿出有问题的数据做了一下验证,果然不一致,比如“小妹妹,叔叔给你棒棒糖吃”

js的输出结果是      792050820fd52f250ee4f47f58d6198f

java的输出结果是  863088240a7c59d82b7792be48d371ec

果然是中文问题,具体原因没有去详查,于是和前端约定,大家都先encode,然后再求MD5

在页面的console中输入

MD5(encodeURIComponent('小妹妹,叔叔给你棒棒糖吃'))
此时的输出为

8bb9c0940ce8fcc0790303a6a5266a34

在java中的代为进行如下修改

System.out.println(DigestUtils.md5Hex(URLEncoder.encode("小妹妹,叔叔给你棒棒糖吃")));
修改的输出结果如下

8bb9c0940ce8fcc0790303a6a5266a34

终于一致了,继续调试,验证通过。
9月25
项目要做一个后台消息推送,在测试过程中,发现每隔1分半自由,WebSocket会走OnError方法,将异常抛出,异常是java.io.EOFException.然后走@OnClose方法,将连接自动关闭,首先需要加上心跳,并且将nginx中加上proxy_read_timeout 设置为 2000s。

     heartCheckFun(){
        var that = this;
        //心跳检测,每20s心跳一次
        that.heartCheck = {
          timeout: 20000,
          timeoutObj: null,
          serverTimeoutObj: null,
          reset: function(){
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
          },
          start: function(){
            var self = this;
            this.timeoutObj = setTimeout(function(){
              //这里发送一个心跳,后端收到后,返回一个心跳消息,
              //onmessage拿到返回的心跳就说明连接正常
              that.websocketSend("HeartBeat");
              console.info("客户端发送心跳");
              self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
                that.websock.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
              }, self.timeout)
            }, this.timeout)
          }
        }
      },

nginx的设置为:
location /{
      proxy_pass http://xx.xxx.xxx.xx:xxxx;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_read_timeout 2000s;
      keepalive_timeout  2000s;
            proxy_set_header   Host    $host;
      proxy_set_header   X-Real-IP   $remote_addr;
      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
  }

尽管设置2000s,但是当到达设置时间,如果websocket没有进行通讯,还是会断开连接.可以前端做一个心跳检测,每隔20秒钟发起一次通信就行.

希望能帮到你;
9月21
在安装npm时,可能根据某个教程设置了例如:

npm config set prefix "C:\Program Files\nodejs\node_global"
以及
npm config set cache "C:\Program Files\nodejs\node_cache"

之类的东西,可是后来不想要了,想要恢复默认值,怎么办呢?

方法是删除C:\Users\Administrator\.npmrc这个文件。如果.npmrc不在这个目录下,就全局搜一下啦。
9月21

配置Nodejs镜像

11:18Web开发  From: 本站原创
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global

yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global


执行下面的指令就可以使用cnpm利用国内镜像服务了:

npm install -g cnpm --registry=https://registry.npm.taobao.org;
9月14
SELECT COUNT(*) 

FROM (SELECT 分组字dao段 FROM 表 

GROUP BY 分组字段 

)别名 

或者 

SELECT COUNT(*) 

FROM (SELECT distinct 分组字段 FROM 表)别名

扩展资料:
SQL分组查询

在SQL Server中使用的分组查询是ORDER BY子句,使用ORDER BY子句要同聚合函数配合使用才能完成分组查询,在SELECT查询的字段中如果字段没有使用聚合函数就必须出现在ORDER BY子句中(即SELECT后边的字段名要么出现在聚合函数中,要么在ORDER BY子句中使用)

在分组查询中还可以配合使用HAVING子句,定义查询条件。

使用group by进行分组查询

在使用group by关键字时,在select列表中可以指定的项目是有限制的,select语句中仅许以下几项:

1、被分组的列

2、为每个分组返回一个值得表达式,例如用一个列名作为参数的聚合函数

3、group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面


要得到每组的合计可以用下面的,要总计用上面的,想一次性得到分组合计以内及总计,可以这么写:

SELECT 分组容字段 FROM 表
GROUP BY 分组字段
compute sum(COUNT(*))


那就这样
SELECT COUNT(*)
FROM (SELECT 分组字段 FROM 表
GROUP BY 分组字段
)别名

或者

SELECT COUNT(*)
FROM (SELECT distinct 分组字段 FROM 表)别名
9月14

  location / {
      proxy_http_version 1.1;    
      proxy_set_header Upgrade $http_upgrade;    
      proxy_set_header Connection "Upgrade";    
      proxy_set_header X-real-ip $remote_addr;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_pass http://localhost:6633/;
    }
9月3
最近在做项目时,需要要工具类中对属性进行赋值,里面有appID和appsecret,因为这两个都是相对固定不会变动的东西,所以配在配置文件 或者数据库配置表最好,这边使用的是配置文件(application.yml),然后通过@Value()属性注入到对应的属性中。
刚开始在做的时候,启动项目后发现通过使用@Value注解对这两个属性进行赋值,结果两个都注不进去。

这个让我很苦恼,通过查找资料。找到了通过set的办法进行注入,并成功。

解决办法:

   1.将这两个私有属性的set方法从私有变成公开(private -->>> public);

   2.生成这两个静态属性的set方法;

   3.将原来在静态属性上的@Value() 注解改到设在 set方法上;

   4.去除这两个静态属性set方法的static关键字

类上面的@Compoent 注解一定要有,一定要注意set方法是没有static的,否则取不到值的。
8月19
Tess4j Issue in Windows: java.lang.UnsatisfiedLinkError: The specified module could not be found in instance.doOCR(imageFile)

Tess4j在本地跑的时候没有问题,放到windows server2008 r2服务器上的时候就报下面找不到模块的错误:

java.lang.UnsatisfiedLinkError: The specified module could not be found.

       at com.sun.jna.Native.open(Native Method) ~[jna.jar:4.2.1 (b0)]
       at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:263) ~[jna.jar:4.2.1 (b0)]
       at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:403) ~[jna.jar:4.2.1 (b0)]
       at com.sun.jna.Library$Handler.<init>(Library.java:147) ~[jna.jar:4.2.1 (b0)]
       at com.sun.jna.Native.loadLibrary(Native.java:502) ~[jna.jar:4.2.1 (b0)]
       at com.sun.jna.Native.loadLibrary(Native.java:481) ~[jna.jar:4.2.1 (b0)]
       at net.sourceforge.tess4j.util.LoadLibs.getTessAPIInstance(Unknown Source) ~[tess4j-3.0.jar:na]
       at net.sourceforge.tess4j.TessAPI.<clinit>(Unknown Source) ~[tess4j-3.0.jar:na]
       at net.sourceforge.tess4j.Tesseract.init(Unknown Source) ~[tess4j-3.0.jar:na]
       at net.sourceforge.tess4j.Tesseract.doOCR(Unknown Source) ~[tess4j-3.0.jar:na]
       at net.sourceforge.tess4j.Tesseract.doOCR(Unknown Source) ~[tess4j-3.0.jar:na]
       at net.sourceforge.tess4j.Tesseract.doOCR(Unknown Source) ~[tess4j-3.0.jar:na]
       at ocr.OCRController.handleFileUpload(OCRController.java:109) ~[classes/:na]
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_51]
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_51]
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_51]
       at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]

我搜索并发现人们建议更新Visual VisualC++可重分发软件包,我做了Visual Studio 2013,但结果却没有帮助,我仍然得到同样的问题。我不知道我做错了什么,下面是我的代码。

ITesseract instance = new Tesseract(); // JNA Interface Mapping

instance.setDatapath(new File(datapath).getPath());
instance.setLanguage("eng");      
try {
       String result = instance.doOCR(imageFile); //error here
} catch (TesseractException e) {
       System.err.println(e.getMessage());
}


此问题与Windows无关。
我已经把版本换回3.0
<dependency>
       <groupId>net.sourceforge.tess4j</groupId>
       <artifactId>tess4j</artifactId>
       <version>3.0.0</version>
</dependency>
替换所有以前的maven依赖项,就好了。
分页: 1/52 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]