java程序员自己的图片转文字OCR识图工具分享

目录
  • 图片转文字OCR识图工具
  • 只需三个文件

图片转文字OCR识图工具

图片文字识别,只支持在windows上运行,语言自动识别,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key。

打包成jar文件放桌面可以自己用也可以给亲人朋友用。

只需三个文件

即可自己开发一个OCR工具软件:

App.java

package translate.image;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 图片文字识别,只支持在windows上运行,语言自动识别,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key
 *
 * @author tang
 */
public class App {
    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(com.sun.java.swing.plaf.windows.WindowsLookAndFeel.class.getName());
        UIManager.put("ScrollBarUI", "com.sun.java.swing.plaf.windows.WindowsScrollBarUI");// 设置滚动条样式为window风格的滚动条样式
        // 设置文件夹在swing中所显示的图标
        UIManager.put("FileView.directoryIcon", FileSystemView.getFileSystemView().getSystemIcon(new File(System.getProperty("user.dir"))));

        String oldApiKey = "";
        String oldSecretKey = "";
        final File keyFile = new File(System.getProperty("user.dir") + "/百度OCR应用密钥.txt");
        if (keyFile.exists()) {
            try {
                List<String> keyTextList = Files.readAllLines(keyFile.toPath());
                if (keyTextList != null && keyTextList.size() >= 2) {
                    oldApiKey = keyTextList.get(0);
                    oldSecretKey = keyTextList.get(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        final JFrame jFrame = new JFrame();
        JPanel contentPane = new JPanel();
        jFrame.setContentPane(contentPane);
        contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
        contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 20));
        JPanel jp1 = new JPanel();
        jp1.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        jp1.setBorder(new EmptyBorder(0, 0, 0, 0));
        jp1.setPreferredSize(new Dimension(400, 30));
        JLabel apiKeyLabel = new JLabel("   API Key : ");

        jp1.add(apiKeyLabel);
        final JTextField apiKeyTextField = new JTextField("", 40);
        apiKeyTextField.setText(oldApiKey);
        jp1.add(apiKeyTextField);
        contentPane.add(jp1);

        JPanel jp2 = new JPanel();
        jp2.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        jp2.setBorder(new EmptyBorder(0, 0, 0, 0));
        jp2.setPreferredSize(new Dimension(400, 30));
        JLabel secretKeyLabel = new JLabel("Secret Key : ");

        jp2.add(secretKeyLabel);
        final JTextField secretKeyTextField = new JTextField("", 40);
        secretKeyTextField.setText(oldSecretKey);
        jp2.add(secretKeyTextField);
        contentPane.add(jp2);

        JPanel jp3 = new JPanel();
        jp3.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        jp3.setBorder(new EmptyBorder(0, 0, 0, 0));
        jp2.setPreferredSize(new Dimension(400, 30));
        JLabel imageLabel = new JLabel(" Image : ");
        jp3.add(imageLabel);

        final JTextField imageTextField = new JTextField("", 40);
        jp3.add(imageTextField);

        JButton selFileBtn = new JButton("...");
        jp3.add(selFileBtn);
        final JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File(System.getProperty("user.home") + "/Desktop"));
        chooser.setFileFilter(new FileFilter() {
            public boolean accept(File f) {
                if (f.isDirectory()) {
                    return true;
                }
                if (f.getName().endsWith(".png") || f.getName().endsWith(".jpg") || f.getName().endsWith(".jpeg") || f.getName().endsWith(".bmp")) {
                    return true;
                }
                return false;
            }

            public String getDescription() {
                return "png/jpg/bmp";
            }
        });
        selFileBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int i = chooser.showOpenDialog(jFrame);
                if (JFileChooser.APPROVE_OPTION == i) {
                    File selectedFile = chooser.getSelectedFile();
                    if (selectedFile != null && selectedFile.getAbsolutePath() != null) {
                        imageTextField.setText(selectedFile.getAbsolutePath());
                        return;
                    }
                }
                imageTextField.setText("");
            }
        });

        contentPane.add(jp3);

        JPanel jp4 = new JPanel();
        jp4.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        jp4.setBorder(new EmptyBorder(0, 0, 0, 0));
        jp4.setPreferredSize(new Dimension(400, 30));

        JButton saveKeyBtn = new JButton("保存密钥");
        jp4.add(saveKeyBtn);
        contentPane.add(jp4);

        JButton okBtn = new JButton("识别文字");
        jp4.add(okBtn);

        JPanel jp5 = new JPanel();
        jp5.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        jp5.setBorder(new EmptyBorder(0, 0, 0, 0));
        jp5.setPreferredSize(new Dimension(400, 500));
        final JTextArea textArea = new JTextArea(30, 40);
        textArea.setSize(new Dimension(380, 500));
        textArea.setText("1,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key。\r\n" +
                "\t1.1,进入百度智能云服务列表:https://console.bce.baidu.com/ai/#/ai/ocr/overview/index 。\r\n" +
                "\t1.2,点击'通用场景OCR',然后找到'通用文字识别(高精度版)'后点击开通。\r\n" +
                "\t1.3,进入创建应用页面:https://console.bce.baidu.com/ai/#/ai/ocr/app/create。\r\n" +
                "\t1.4,填写应用名称,应用归属选择'个人',随便填写应用描述,然后点击'立即创建'。\r\n" +
                "\t1.5,进入应用列表页面:https://console.bce.baidu.com/ai/#/ai/ocr/app/list。\r\n" +
                "\t1.6,复制出API Key和Secret Key。\r\n" +
                "\t1.7,该接口每天只能免费调用500次,超出部分百度要收费。\r\n" +
                "2,语言可以自动识别。\r\n" +
                "3,只支持png/jpg/bmp格式图片。");
        textArea.setWrapStyleWord(true);
        textArea.setAutoscrolls(true);
        textArea.setLineWrap(true);

        JScrollPane jsp = new JScrollPane(textArea);
        jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

        jp5.add(jsp);
        contentPane.add(jp5);

        saveKeyBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                if (BaiduCloudApiUtil.appApiKey.trim().isEmpty() || BaiduCloudApiUtil.appSecretKey.trim().isEmpty()) {
                    textArea.setText("请先调用接口,成功后才能保存密钥!");
                    return;
                }
                List<String> list = new ArrayList<>(2);
                list.add(BaiduCloudApiUtil.appApiKey);
                list.add(BaiduCloudApiUtil.appSecretKey);
                try {
                    Files.write(keyFile.toPath(), list, Charset.forName("UTF-8"), StandardOpenOption.CREATE);
                    textArea.setText("保存密钥成功!");
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        });

        okBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (apiKeyTextField.getText().trim().isEmpty()) {
                    textArea.setText("请输入API Key!");
                    return;
                }
                if (secretKeyTextField.getText().trim().isEmpty()) {
                    textArea.setText("请输入Secret Key!");
                    return;
                }
                BaiduCloudApiUtil.appApiKey = apiKeyTextField.getText().trim();
                BaiduCloudApiUtil.appSecretKey = secretKeyTextField.getText().trim();
                if (!"".equals(imageTextField.getText().trim())) {
                    try {
                        byte[] bytes = Files.readAllBytes(chooser.getSelectedFile().toPath());
                        Map<String, Object> map = BaiduCloudApiUtil.queryOcrResult(bytes);
                        if (map != null && !map.isEmpty()) {
                            Boolean success = (Boolean) map.get("success");
                            if (success) {
                                String data = (String) map.get("data");
                                if (data != null && !data.trim().isEmpty()) {
                                    textArea.setText(data);
                                } else {
                                    textArea.setText("");
                                }
                            } else {
                                String message = (String) map.get("message");
                                textArea.setText(message);
                            }
                            return;
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                    textArea.setText("转化文字失败!");
                } else {
                    textArea.setText("没有选择文件!");
                }
            }
        });

        jFrame.setSize(500, 800);
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }
}

BaiduCloudApiUtil.java

package translate.image;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

public class BaiduCloudApiUtil {

    static String appApiKey = "";
    static String appSecretKey = "";

    private static volatile String accessToken;
    private static volatile long accessTokenTime;// 获取凭证时的时间,单位:毫秒数,System.currentTimeMillis
    private static volatile int expireTime;// 凭证有效时间,单位:秒

    private static void clearToken() {
        accessToken = "";
        expireTime = 0;
        accessTokenTime = 0;
    }

    public static String getAccessToken() {
        if (!(accessToken == null || accessToken.trim().isEmpty()) && accessTokenTime > 0 && expireTime > 0) {
            long extime = accessTokenTime + (expireTime * 1000);
            long nowTime = System.currentTimeMillis();
            if (extime - nowTime > 1000) {// 仍然有效
                return accessToken;
            }
        }

        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost + "grant_type=client_credentials" + "&client_id=" + appApiKey + "&client_secret=" + appSecretKey;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                String result = "";
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
                JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
                expireTime = jsonObject.getInteger("expires_in");
                accessToken = jsonObject.getString("access_token");
                accessTokenTime = System.currentTimeMillis();
            } catch (Throwable e) {
                e.printStackTrace();
                clearToken();
            }

        } catch (Throwable e) {
            e.printStackTrace();
            clearToken();
        }
        return accessToken;
    }

    public static Map<String, Object> parse(JSONObject jsonObject) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("success", false);
        if (jsonObject == null) {
            map.put("message", "空的调用结果");
            return map;
        }
        try {
            Integer words_result_num = jsonObject.getInteger("words_result_num");
            if (words_result_num == null || words_result_num.intValue() <= 0) {
                map.put("message", "未解析到结果");
                return map;
            }
            JSONArray words_result = jsonObject.getJSONArray("words_result");
            StringBuffer sb = new StringBuffer();
            for (Object obj : words_result) {
                JSONObject jo = (JSONObject) obj;
                String words = jo.getString("words");
                sb.append(words + "\r\n");
            }
            System.out.println(sb);
            map.put("data", sb.toString());
            map.put("success", true);
        } catch (Exception e) {
            map.put("message", "无法解析调用结果");
        }
        return map;
    }

    public static JSONObject ocr(String httpUrl, String httpArg) {
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("apikey", appApiKey);
            connection.setDoOutput(true);
            connection.getOutputStream().write(httpArg.getBytes("UTF-8"));
            connection.connect();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
                StringBuffer sbf = new StringBuffer();
                String strRead = null;
                while ((strRead = reader.readLine()) != null) {
                    sbf.append(strRead);
                    sbf.append("\r\n");
                }
                String result = sbf.toString();
                JSONObject jsonObject = (JSONObject) JSONObject.parse(result);
                return jsonObject;
            } catch (Throwable e) {
                e.printStackTrace();
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String encodeBase64(byte[] input) throws Exception {
        Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
        Method mainMethod = clazz.getMethod("encode", byte[].class);
        mainMethod.setAccessible(true);
        Object retObj = mainMethod.invoke(null, new Object[]{input});
        return (String) retObj;
    }

    public static Map<String, Object> queryOcrResult(byte[] fileBytes) {
        try {
            String imageBase = encodeBase64(fileBytes);
            imageBase = URLEncoder.encode(imageBase, "UTF-8");
            String httpUrl = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken();
            String httpArg = "language_type=auto_detect&image=" + imageBase;

            JSONObject jsonObject = ocr(httpUrl, httpArg);
            if (jsonObject == null) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("success", false);
                map.put("message", "系统错误,请稍后重试");
                return map;
            }
            Map<String, Object> map = parse(jsonObject);
            return map;
        } catch (Exception e) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("success", false);
            map.put("message", "系统错误,请稍后重试");
            return map;
        }
    }

    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\tang8\\Desktop\\2022-07-21_070822.png");
        byte[] data = Files.readAllBytes(file.toPath());
        Map<String, Object> map = queryOcrResult(data);
        System.out.println(map.get("data"));
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>translate.image</groupId>
    <artifactId>TranslateImage</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>TranslateImage</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.29</version>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.1.1</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>translate.image.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
           <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • java实现图片文字识别ocr

    最近在开发的时候需要识别图片中的一些文字,网上找了相关资料之后,发现google有一个离线的工具,以下为java使用的demo 在此之前,使用这个工具需要在本地安装OCR工具: 下面一个是一定要安装的离线包,建议默认安装 上面一个是中文的语言包,如果网络可以FQ的童鞋可以在安装的时候就选择语言包在线安装,有多种语言可供选择,默认只有英文的 exe安装好之后,把上面一个文件拷到安装目录下tessdata文件夹下 如C:\Program Files (x86)\Tesseract-OCR\tessd

  • 不到十行实现javaCV图片OCR文字识别

    spring boot项目pom文件中添加以下依赖 <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.5</version&g

  • Java使用Tessdata做OCR图片文字识别的详细思路

    说到文字识别,目前除了用一些现成的api,大概就是 tessdata.canvas或者 ocrad等. 1.百度接口用过(可以自己去百度开发者申请,免费的),识别率吧,还可以,但也不是百分百的,但是次数使用有限制,虽然也是够用,但是被限制总是害怕超过不让用. 2.canvas的话是需要对图片做具体的处理,涉及到图片的翻转.置灰.文字间隔的设定等等,成功率很高,但是公司产品验证码是各式各样的,没办法用这种方法处理,所以暂时放弃了. 3.ocrad这个目前用过其.js版本,识别率还是比较低的,具体使

  • java程序员自己的图片转文字OCR识图工具分享

    目录 图片转文字OCR识图工具 只需三个文件 图片转文字OCR识图工具 图片文字识别,只支持在windows上运行,语言自动识别,调用的是百度OCR-API,需要提供百度智能云管理后台的应用的API Key和Secret Key. 打包成jar文件放桌面可以自己用也可以给亲人朋友用. 只需三个文件 即可自己开发一个OCR工具软件: App.java package translate.image; import javax.swing.*; import javax.swing.border.E

  • 小米Java程序员第二轮面试10个问题 你是否会被刷掉?

    近日,开发者头条上分享了一篇"小米java第二轮面经",有很多的java程序员表示非常有兴趣. 下面就和各位分享小米java第二轮面经: 0.谈谈对Spring的认识 1.java集合的继承关系 相关文章: java集合继承关系图分享 Java集合类的组织结构和继承.实现关系详解 Java集合继承体系详解 Java中集合关系图及常见操作详解 2.你知道CLOSE_WAIT这个状态吗? 3.谈谈你对jvm.java内存模型的认识? 4.Java里的红黑树是怎么实现的? 相关文章: jav

  • Java程序员需要掌握的英语词组

    本文为大家分享了Java程序员必须掌握的英语词组,供大家参考,具体内容如下 抽象类(abstract class):抽象类不能创建对象,主要用来创建子类.Java中的抽象类使用 abstract 修饰符定义. 抽象数据类型(abstract data type ADT):抽象数据类型指明了可能的类型和允许进行的操作,但是没有提供实现. 访问标识符(access specifier):用于方法或变量定义,限定了哪些类可以访问该方法或变量.Java中的访问标识符有 public.protected

  • Java程序员常犯的五个错误

    下面针对每一个错误用文字说明结合代码详解的方式展示给大家,具体内容如下: 1. Null 的过度使用 避免过度使用 null 值是一个最佳实践.例如,更好的做法是让方法返回空的 array 或者 collection 而不是 null 值,因为这样可以防止程序抛出 NullPointerException.下面代码片段会从另一个方法获得一个集合: List<String> accountIds = person.getAccountIds(); for (String accountId :

  • 最有价值的50道java面试题 适用于准入职Java程序员

    下面的内容是对网上原有的Java面试题集及答案进行了全面修订之后给出的负责任的题目和答案,原来的题目中有很多重复题目和无价值的题目,还有不少的参考答案也是错误的,修改后的Java面试题集参照了JDK最新版本,去掉了EJB 2.x等无用内容,补充了数据结构和算法相关的题目.经典面试编程题.大型网站技术架构.操作系统.数据库.软件测试.设计模式.UML等内容,同时还对很多知识点进行了深入的剖析,例如hashCode方法的设计.垃圾收集的堆和代.Java新的并发编程.NIO.2等,相信对准备入职的Ja

  • Java 程序员容易犯的10个SQL错误

    Java程序员编程时需要混合面向对象思维和一般命令式编程的方法,能否完美的将两者结合起来完全得依靠编程人员的水准: 技能(任何人都能容易学会命令式编程) 模式(有些人用"模式-模式",举个例子,模式可以应用到任何地方,而且都可以归为某一类模式) 心境(首先,要写个好的面向对象程序是比命令式程序难的多,你得花费一些功夫) 但当Java程序员写SQL语句时,一切都不一样了.SQL是说明性语言而非面向对象或是命令式编程语言.在SQL中要写个查询语句是很简单的.但在Java里类似的语句却不容易

  • 10个Java程序员熟悉的面向对象设计原则

    面向对象设计原则是OOPS编程的核心, 但我见过的大多数Java程序员热心于像Singleton (单例) . Decorator(装饰器).Observer(观察者) 等设计模式,而没有把足够多的注意力放在学习面向对象的分析和设计上面.学习面向对象编程像"抽象"."封装"."多态"."继承" 等基础知识是重要的,但同时为了创建简洁.模块化的设计,了解这些设计原则也同等重要.我经常看到不同经验水平的java程序员,他们有的不知

  • Java程序员应该遵守的10条纪律

    有哪些"纪律"是Java程序员所要遵守的? 1. 为代码添加注释(Add comments to your code). – 每个人都知道这一点,但不是每个人都会这么做.你有多少次"忘记"添加注释了?确实,注释不会为你的程序增加任何函数功能.但是,有多少次,看到2周前写的代码,你都记不起它是干什么的?你很幸运,那些未注释的代码是你自己写的,你脑海中还会有残存的印象.非常不幸,大多时候,代码是别人写的,并且那个人很可能已经离开公司了.有句谚语说的好:"有来有

  • 作为Java程序员应该掌握的10项技能

    本文详细罗列了作为Java程序员应该掌握的10项技能.分享给大家供大家参考.具体如下: 1.语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误并且知道任何修正. 2.命令:必须熟悉JDK带的一些常用命令及其常用选项,命令至少需要熟悉:appletviewer.HtmlConverter.jar.java.javac.javadoc.javap.javaw.native2ascii.serialver,如果这些命令你没有全部使用过,那么你对jav

  • Java程序员转Android开发必读经验一份

    啰哩啰嗦的说说Java和Android程序的区别: Android是主流智能手机的操作系统,Java是一种开发语言,两者没有好坏优劣之分,只是两种职业岗位的选择.学安卓从事移动互联方向开发,学Java从事软件.网站开发.而安卓上的应用大多是Java编写的,所以建议在安卓前期的Java学习阶段中,要用心学好. 言简意赅的说说"转"前的准备: 其实Java程序员要自学安卓开发的基础知识还是没有什么难度的,毕竟语言相通,特性相似,阅读安卓源代码的门槛以比较低一些,作为能够考虑"转&

随机推荐