json和xml都是用来进行数据的传输和交换的,是目前用来传输数据用的最多的两种技术,下面我们分别来认识一下它们及其解析过程

一、json

1、json简介

  • JSON是一种基于文本的轻量级数据交换格式,源自JavaScript,用于Web服务和其他连接的应用程序,易于人阅读和编写, 同时也易于机器解析和生成
  • JSON是存储和交换文本信息的语法,类似XML
  • JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等),这些特性使JSON成为理想的数据交换语言

2、json语法

  JSON只定义了两个数据结构:对象和数组。对象是一组名称 - 值对,而数组是值列表。JSON定义了七种值类型:字符串,数字,对象,数组,true,false和null。

  以下示例显示包含名称 - 值对的示例对象的JSON数据。名称的值"phoneNumbers"是一个数组,其元素是两个对象。

{
"firstName": "Duke",
"lastName": "Java",
"age": 18,
"streetAddress": "100 Internet Dr",
"city": "JavaTown",
"state": "JA",
"postalCode": "12345",
"phoneNumbers": [
{ "Mobile": "111-111-1111" },
{ "Home": "222-222-2222" }
]
}

  JSON具有以下语法:

  • 对象用大括号({})括起来,它们的名称 - 值对用逗号(,)分隔,一对中的名称和值用冒号(:)分隔。对象中的名称是字符串,而值可以是七种值类型中的任何一种,包括另一个对象或数组。
  • 数组括在括号([])中,它们的值用逗号(,)分隔。数组中的每个值可以是不同的类型,包括另一个数组或对象。
  • 当对象和数组包含其他对象或数组时,数据具有树状结构

  JSON通常用作通用格式,用于序列化和反序列化通过Internet相互通信的应用程序中的数据。这些应用程序使用不同的编程语言创建,并在不同的环境中运行。JSON适用于这种情况,因为它是一个开放标准,易于读写,并且比其他表示更紧凑

3、生成和解析json数据

  为了生成和解析JSON数据,有两种编程模型,类似于用于XML文档的编程模型。

  • 对象模型创建一个表示内存中JSON数据的树。然后可以导航,分析或修改树。这种方法最灵活,允许进行需要访问树的完整内容的处理。但是,它通常比流模型慢,需要更多内存。对象模型通过一次导航整个树来生成JSON输出。

  • 流模型使用基于事件的解析器,一次读取一个元素的JSON数据。当对象或数组开始或结束,找到键或找到值时,解析器生成事件并停止处理。应用程序代码可以处理或丢弃每个元素,然后解析器继续执行下一个事件。这种方法适用于本地处理,其中元素的处理不需要来自其余数据的信息。流模型通过一次使用一个元素进行函数调用来生成给定流的JSON输出。

  3.1使用解析器读取JSON数据

  流API是解析JSON文本的最有效方法。以下代码演示了如何创建JsonParser对象以及如何使用事件解析JSON数据:

import javax.json.Json;
import javax.json.stream.JsonParser;
...
JsonParser parser = Json.createParser(new StringReader(jsonData));
while (parser.hasNext()) {
JsonParser.Event event = parser.next();
switch(event) {
case START_ARRAY:
case END_ARRAY:
case START_OBJECT:
case END_OBJECT:
case VALUE_FALSE:
case VALUE_NULL:
case VALUE_TRUE:
System.out.println(event.toString());
break;
case KEY_NAME:
System.out.print(event.toString() + " " +
parser.getString() + " - ");
break;
case VALUE_STRING:
case VALUE_NUMBER:
System.out.println(event.toString() + " " +
parser.getString());
break;
}
}

  此示例包含三个步骤。

    1. 通过调用Json.createParser静态方法获取解析器实例。

    2. 使用JsonParser.hasNext和 JsonParser.next方法迭代解析器事件。

    3. 对每个元素执行本地处理。

  该示例显示了解析器中的十种可能的事件类型。解析器的next方法将其推进到下一个事件。对于事件类型KEY_NAMEVALUE_STRINGVALUE_NUMBER,您可以通过调用方法获取元素的内容 JsonParser.getString。对于 VALUE_NUMBER事件,您还可以使用以下方法:JsonParser.isIntegralNumber

  • JsonParser.getInt
  • JsonParser.getLong
  • JsonParser.getBigDecimal

  有关javax.json.stream.JsonParser 更多信息,请参阅该接口的Java EE API参考。

  此示例的输出如下:

START_OBJECT
KEY_NAME firstName - VALUE_STRING Duke
KEY_NAME lastName - VALUE_STRING Java
KEY_NAME age - VALUE_NUMBER 18
KEY_NAME streetAddress - VALUE_STRING 100 Internet Dr
KEY_NAME city - VALUE_STRING JavaTown
KEY_NAME state - VALUE_STRING JA
KEY_NAME postalCode - VALUE_STRING 12345
KEY_NAME phoneNumbers - START_ARRAY
START_OBJECT
KEY_NAME type - VALUE_STRING mobile
KEY_NAME number - VALUE_STRING 111-111-1111
END_OBJECT
START_OBJECT
KEY_NAME type - VALUE_STRING home
KEY_NAME number - VALUE_STRING 222-222-2222
END_OBJECT
END_ARRAY
END_OBJECT

3.2使用生成器编写JSON数据

  以下代码演示了如何使用流API将JSON数据写入文件:

FileWriter writer = new FileWriter("test.txt");
JsonGenerator gen = Json.createGenerator(writer);
gen.writeStartObject()
.write("firstName", "Duke")
.write("lastName", "Java")
.write("age", 18)
.write("streetAddress", "100 Internet Dr")
.write("city", "JavaTown")
.write("state", "JA")
.write("postalCode", "12345")
.writeStartArray("phoneNumbers")
.writeStartObject()
.write("type", "mobile")
.write("number", "111-111-1111")
.writeEnd()
.writeStartObject()
.write("type", "home")
.write("number", "222-222-2222")
.writeEnd()
.writeEnd()
.writeEnd();
gen.close();

  此示例通过调用Json.createGenerator静态方法获取JSON生成器,该 方法将writer或输出流作为参数。该示例JSON数据写入到test.txt 通过嵌套的调用文件writewriteStartArray, writeStartObject,和writeEnd方法。该JsonGenerator.close 方法关闭底层的编写器或输出流。

二、xml

1、xml简介

  • XML是一种可扩展标记语言,很类似HTML,通过此种标记,计算机之间可以处理包含各种信息的文章等
  • XML的设计宗旨是传输数据,而非显示数据,所以它也是数据传输常用的常用工具
  • XML标签没有被预定义。您需要自行定义标签。
  • XML被设计为具有自我描述性
  • XML不是HTML的替代,XML用于传输数据,而HTML用于格式化并显示数据

2、xml语法

  总的来说就是语法比json繁杂多了,这里就不详细介绍了,有兴趣可以自行学习(暴露了我更偏爱json,●ˇ∀ˇ●)

3、xml解析

  xml的三种原生解析方式:

  • DOM:内存消耗大但是便于遍历.打开文档,将其转化为节点树,然后在其用循环的方式,遍历节点一一查找
  • SAX:速度快,战内存少.但是文件结构信息会丢失,采用的是流的处理方式.从起始标签开始一一往下逐个查找.起始标签与结尾标签作为标记来将一组数据存入一个集合中,想水流一样一直到最尾,然后最后返回集合,集合中就存下了所有的数据(这也应该就是所谓的流处理方式吧).
  • PULL:是Android内置,推荐的一种,相对来说有点类似SAX,也是从上往下,但是它还是已文档开始与结尾为条件,在其中间进行查找处理,然后分为不同标签开始逐一查找.

  下面 以网上借鉴的项目为例,展示如何解析xml文件

 3.1 XML文件是一棵树,首先需要找到对应的节点,然后从节点开始解析,比如搜索找到的就是result/weights/weight 和result/weights/weight 2个节点,分别从这个开始解析:

public ResultInfo onParser(Element rootElement) {
int resp = -1;
try {
String elName = "header/respcode";
resp = Integer.parseInt(selectNodeString(rootElement, elName));
} catch (NumberFormatException e) {
e.printStackTrace();
} Log.d(TAG, "resp= " + resp); if (resp != 0) {
return null;
} ResultInfo searchResultInfo = new ResultInfo(); // Parse Search Weight
@SuppressWarnings("rawtypes")
final List <span id="17_nwp" style="float: none; width: auto; height: auto;"><a id="17_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=weight&k0=weight&kdi0=0&luki=5&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">weight</span></a>s = rootElement.selectNodes(rootElement.getPath() + "/"
+ "result/weights/weight"); ResultInfo[] resultFilterInfos = parseVideos(weights);
if (resultFilterInfos != null) {
ResultInfo weight = new ResultInfo();
weight.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultFilterInfos);
searchResultInfo.putResultInfo(ResultInfo.KEY_WEIGHT, weight);
} // Parse Albums
@SuppressWarnings("rawtypes")
final List albums = rootElement.selectNodes(rootElement.getPath() + "/"
+ "result/albums/album"); ResultInfo[] resultInfos = parseVideos(albums);
if (resultInfos != null) {
ResultInfo album = new ResultInfo();
album.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultInfos);
searchResultInfo.putResultInfo(ResultInfo.KEY_SEARCH, album);
} return searchResultInfo;
}</span>

 3.2 找到了对应的Node,即从对应的Node开始递归的查找,直到找到最小的节点,也就是最基本的单元Element。再对每一个Element进行解析:

private ResultInfo[] parseVideos(final List nodes) {
if (nodes != null && nodes.size() > 0) {
final int size = nodes.size();
final ResultInfo[] vis = new ResultInfo[size];
int i = 0;
for (Object o : nodes) {
if (o instanceof Element) {
final Element <span id="16_nwp" style="float: none; width: auto; height: auto;"><a id="16_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element = (Element) o;
ResultInfo vi = parseVideo(videoElement);
vis[i] = vi;
}
i++;
}
return vis;
}
return null;
}</span>

 3.3 针对获取到的Element,解析出对应的String将数据传递给VideoInfo这个类:

private ResultInfo parseVideo(final Element <span id="13_nwp" style="float: none; width: auto; height: auto;"><a id="13_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element) {
final String id = videoElement.elementText("album_id");
final String title = videoElement.elementText("title");
final String categoryId = videoElement.elementText("category_id");
final String categoryName = videoElement.elementText("category_name");
final String count = videoElement.elementText("count");
final String imgUrl = videoElement.elementText("img180236");
final String duration = <span id="14_nwp" style="float: none; width: auto; height: auto;"><a id="14_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element.elementText("duration");
final String mainactors = videoElement.elementText("mainactors");
final String sitename = videoElement.elementText("site_name");
final String videourl = videoElement.elementText("vedio_url");
final String sort = videoElement.elementText("sort");
final String tv_id = videoElement.elementText("tv_id");
ResultInfo vi = new ResultInfo();
vi.putString(VideoInfo.ID, id);
vi.putString(VideoInfo.TITLE, title);
vi.putString(VideoInfo.CATEGORY_ID, categoryId);
vi.putString(VideoInfo.CATEGORY_NAME, categoryName);
vi.putString(VideoInfo.COUNT, count);
vi.putString(VideoInfo.IMG_URL, imgUrl);
vi.putString(VideoInfo.DURATION, duration);
vi.putString(VideoInfo.MAINACTORS, mainactors);
vi.putString(VideoInfo.SITENAME, sitename);
vi.putString(VideoInfo.VIDEOURL, <span id="15_nwp" style="float: none; width: auto; height: auto;"><a id="15_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>url);
vi.putString(VideoInfo.SORT, sort);
vi.putString(VideoInfo.TV_ID, tv_id);
return vi;
}</span></span></span>

 3.4 当使用XML解析器将XML数据解析出来之后。需要将这些数据提取出来,也是通过连续2层提取,将数据定位到每个video, 将每个video里的数据传递给SearchVideoInfo这个ArrayList,然后将ArrayList中的数据和对应的Adapter数据关联起来:

public static ArrayList<SearchVideoInfo> getSearchVideoInfo(ResultInfo searchResultInfo) {

    ResultInfo resultInfo = null;
ResultInfo[] <span id="9_nwp" style="float: none; width: auto; height: auto;"><a id="9_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>s = null;
ArrayList<SearchVideoInfo> searchVideoInfos = null; if (searchResultInfo != null) {
resultInfo = searchResultInfo.getResultInfo(ResultInfo.KEY_SEARCH);
} if (resultInfo != null) {
videos = resultInfo.getResultInfoArray(ResultInfo.KEY_VIDEOS);
} if (videos != null && videos.length > 0) { searchVideoInfos = new ArrayList<SearchVideoInfo>(<span id="10_nwp" style="float: none; width: auto; height: auto;"><a id="10_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>s.length); for (ResultInfo video : videos) {
SearchVideoInfo searchInfo = new SearchVideoInfo(); searchInfo.setAlbum_id(video.getString(VideoInfo.ID));
searchInfo.setTitle(video.getString(VideoInfo.TITLE));
searchInfo.setChannel_id(video.getString(VideoInfo.CATEGORY_ID));
searchInfo.setImgUrl(video.getString(VideoInfo.IMG_URL));
searchInfo.setDuration(<span id="11_nwp" style="float: none; width: auto; height: auto;"><a id="11_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>.getString(VideoInfo.DURATION));
searchInfo.setMainActors(video.getString(VideoInfo.MAINACTORS));
searchInfo.setSiteName(video.getString(VideoInfo.SITENAME));
searchInfo.setVideo_url(video.getString(VideoInfo.VIDEOURL));
searchInfo.setOrder(video.getString(VideoInfo.SORT));
searchInfo.setTv_id(video.getString(VideoInfo.TV_ID));
// searchInfo.setContinueType(<span id="12_nwp" style="float: none; width: auto; height: auto;"><a id="12_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>.getString(VideoInfo.CONTINUETYPE)); searchVideoInfos.add(searchInfo);
}
} if (searchVideoInfos == null) {
MyLog.e(TAG, "error, getSearchVideoInfo, can not get info");
} return searchVideoInfos;
}</span></span></span></span>

参考链接:https://www.cnblogs.com/ranzige/p/4600006.html

分析Json/Xml的解析过程的更多相关文章

  1. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  2. MyBatis 源码分析 - 配置文件解析过程

    * 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...

  3. Spring源码阅读笔记04:默认xml标签解析

    上文我们主要学习了Spring是如何获取xml配置文件并且将其转换成Document,我们知道xml文件是由各种标签组成,Spring需要将其解析成对应的配置信息.之前提到过Spring中的标签包括默 ...

  4. Spring源码阅读笔记05:自定义xml标签解析

    在上篇文章中,提到了在Spring中存在默认标签与自定义标签两种,并且详细分析了默认标签的解析,本文就来分析自定义标签的解析,像Spring中的AOP就是通过自定义标签来进行配置的,这里也是为后面学习 ...

  5. iOS - 分析JSON、XML的区别和解析方式的底层是如何实现的(延伸实现原理)

    <分析JSON.XML的区别,JSON.XML解析方式的底层是如何实现的(延伸实现原理)> (一)JSON与XML的区别: (1)可读性方面:基本相同,XML的可读性比较好: (2)可扩展 ...

  6. 从LayoutInflater分析XML布局解析成View的树形结构的过程

    上一篇博客分析了XML布局怎么载入到Activity上.不了解的能够參考 从setContentView方法分析Android载入布局流程 上一篇博客仅仅是分析了怎么讲XML布局加入到 Activit ...

  7. ios之json,xml解析

    JSON解析步骤: 1.获取json文件路径 NSString*path = [[NSBundle mainBundle] pathForResource:@"Teacher"of ...

  8. 玩转iOS开发 - JSON 和 Xml 数据解析

    前言 Json 和xml是网络开发中经常使用的数据格式,JSON轻量级.xml相对较复杂.所以如今用JSON的比例很大.基本上从server获取的返回数据都是JSON格式的,作为iOS开发人员,解析J ...

  9. Duilib源码分析(三)XML解析器—CMarkup

    上一节介绍了控件构造器CDialogBuilder,接下来将分析其XML解析器CMarkup: CMarkup:xml解析器,目前内置支持三种编码格式:UTF8.UNICODE.ASNI,默认为UTF ...

随机推荐

  1. springboot整合redis(简单整理)

    Redis安装与开启 我这里是在windows上练习,所以这里的安装是指在windows上的安装,操作非常简单,点击https://github.com/MicrosoftArchive/redis/ ...

  2. js判断终端以及APP应用判断

    **第一种:通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如下:** <script type="text/javascript"& ...

  3. 硬件笔记之MacMini开启HiDPI

    0x00 概述 先科普一下,有关retina和HiDPI那点事 ,Macmini在2k显示器的显示太小了,看起来费眼,没办法,苹果原生HiDPI是支持4k显示器的,所以以后买显示器,直接买4k的一步到 ...

  4. [c/c++] programming之路(26)、结构体

    一.初始化字符串 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include&l ...

  5. bzoj 4770 图样 - 概率与期望 - 动态规划

    题目传送门 传送门I 传送门II 题目大意 有一个$n$个点的完全图,每个点的权值是$[0, 2^{m})$中的随机整数,两点间的边的权值是两点点权的异或和,问它的最小异或生成树的边权和的期望. 考虑 ...

  6. Bootstrap3基础 栅格系统 页面布局随 浏览器大小的变化而变化

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  7. npm 是node.js下带的一个包管理工具

    npm 是node.js下带的一个包管理工具          npm install -g webpack webpack是一个打包工具 gulp是一个基于流的构建工具,相对其他构件工具来说,更简洁 ...

  8. C# Winform 中DataGridView 实现单元格输入下拉框功能

    https://blog.csdn.net/ad13adsa/article/details/82108969 private void dataGridViewX1_EditingControlSh ...

  9. linux下自动获取并安装软件包 apt-get 的命令介绍

    apt-cache search package    搜索包 apt-cache show package    获取包的相关信息,如说明.大小.版本等 sudo apt-get install p ...

  10. 解决macOS因为它来自身份不明的开发者,不显示允许任何来源 –安装文件下载损坏问题

    打开时提示"已损坏,打不开.您应该将它移到废纸篓"或身份验证,因为它来自身份不明的开发者,和不显示允许任何来源,图片解锁和应用程序问题(如图片/application应用程序损坏, ...