android网络编程之数据格式处理,上传下载

     这几天由于实训结束,正式上课。  不得不抽出一些时间处理杂事。 有段时间没整理android了。这里接着上次把网络编程的内容整理整理。

一.数据传输:

     数据传输格式之前在学习java 与前端的时候,已经接触过了xml 与 json。   但是xml没有实际用于传输过,主要用于配置文件。 因此xml的解析相对来说比较弱,有点印象的就是 内置tomcat中依赖的 dom4j 产品有关于xml的解析。  json则用的很多了。  相关的理论背景不需回顾。     

     android中,解析xml的方式有:  SAX,DOM,PULL。  各自优缺点:

             SAX流式解析,解析速度快,占用内存少; 但是使用相对比较麻烦。  非常适合移动设备。

             DOM消耗内存,使用简单;不建议Android使用。

             PULL为Android默认解析器,使用简单。

     json相比较xml而言,具有节省流量,书写简单特点,所有现在传输很多都用json。 (但是它的描述性能不如xml,因为它是名值对的方式,就算勉强能描述,直观性也不强)。  

     在之前整理java知识的时候,已经了解到: 目前市面上比较多的用于解析json主要有四款产品:  分别是 Google的Gson,Apache基金会的Json-lib,阿里巴巴的FastJson, 以及 spring官方推荐使用的 Jackson。

     让我感到惊讶的是,android用的是自己的json解析包。  我还以为它会用 Gson呢,毕竟都是Google的产品。  不过相对而言,那些倒成了第三方json 解析库。  话说,我在上学期也弄了一个json解析来着,一是因为json-lib 的操作给我惹怒了,二是因为我当时想要实现一套与dao层自动拆封箱(功能是为了简化service的操作)的功能。 不过还存在一些问题,性能上面不知道怎么样,稳定性也没有测试过。  后来由于很多其它的事情,比如新技术,其它课业。。。。

二.Android文件上传

     首先,文件的上传下载,都是基于流(序列,二进制,线性,非线段)的。不只是上传,在电脑内部也是这样的。  流通的方式有且仅有一种,二进制流。

     基于“流”,这里的流 代表的是 资源实体。   但是负责连接,以及寻路,差错控制等等等很多复杂的物理问题,都是基于 tcp/ip 协议处理的。  如果我没记错的话,以前曾经纠结了一个问题,协议,java,操作系统三者就网络连接是如何协作的。  虽然现在任然有一些纠结,不过要好很多。 

    这里给个设想:     我们知道操作系统用于与电脑的接口, 操作系统的作用之一就是管理硬件资源。  其中有一个硬件叫做 网卡,也叫网络适配器,又分为有无线网卡和有线网卡。  网卡是客观存在的,我们可以看到的实体。 它的内部有复杂的晶体管及集成电路,具有它本身的物理特性。。。     cpu能够识别它的一些参数,网卡的设计者在设计之初就已经想好了这一切的问题。   最终结果就是,cpu能够通过电信号与网卡交互了。     这里的交互遵循的就是tcp/ip协议。   至于网卡,那自然是将以比特流的形势传给网线,或者是以电磁波的形式传给接入端路由。  在这整个过程也是要遵循tcp/ip协议的,这个过程极快极快,这与电子本身的物理特性有关。    另外,对于cpu而言,除了寄存器外,所有的外界包括缓存 和 内存,都可以看作是远端。  它本身并无法判断是从远端,还是一个更远端来的数据,只不过通过识别进入的硬件设备可以生硬的识别。。   

       此时,硬件条件已经满足,当然这是在其它一些基础设施已经具备的情况下。    这个时候,需要知道现代操作系统的设计思路。   由于cpu很快很快很快,内存很快很快,操作系统本质就是一个在内存中与cpu中跑的实体,它就很快很快。   但是它相对于cpu来说,还是要慢的多的多。    我们人类对于它们而言,则是要慢的多的多的多的多.......。    因此为了有效的利用这些时间碎片,出现了多任务操作系统,并行操作系统,多线程并发,多线程并行等等技术。   其中有个叫做缓存的技术,被广范应用。   我们长听的一级缓存,二级缓存等等,是由于缓和cpu内部 与 内存之间的尴尬。  但是我们自己也可以实现一个缓存,它的本质就是队列。。  先进先出的队列,之所以要出现这个,是因为速度的不匹配,或者说提高效率。  这是操作系统层面。

        java层面,算是一个比较高的层面了。  java是面向对象语言,语言的思路是模仿物理世界,对物理世界进行抽象。  但是现代计算机的本质决定,他只能以二进制流的形式进行传输。  此外,补充一点就是,计算机内部,本地的数据要快于网络的数据,原因很简单,一个是从长度考虑虽然这个因素微乎其微,一个是从所要处理的干扰,转换,噪声影响等等方面考虑。。。  所以  从 java 到 操作系统,为了解决这中时间上的不平衡,采用了缓存。。 它的实现方式是通过 jni ,表现的方式是通过socket。  java只负责将它的数据丢给操作系统的缓存,什么时候发由操作系统根据Tcp/ip协议自动,“智能”的进行发送。  

      以上就是设想的整个过程。

   android关于文件上传的方式,通常是采用第三方库,常见的有:android-async-http,okhttp,七牛;此外还有原生的 httpConnection。。。。。   另外,如果应用层不是http协议的话,则要采用其它的库了。。。

趁火打劫,接着看看文件下载吧,因为文件下载接触的比较少,相对比较薄弱。

      下载分为单线程下载和多线程下载。  与线程相关,瞬间就多了很多乐趣!!!

      首先明确,下载也是基于流的。因此,流可以不用关心对象是什么类型,文本或者是多媒体,或者是二进制代码或者是其它的什么。。

      单线程的下载通过 Url实例对象的一个openStream()方法。 这个方法应该是要与操作系统联动的。 单线程的操作既然已经得到了流,那么后面就没有继续分析的必要了。

       突然想到一个问题:就是为什么java在进行io操作的时候需要手动关闭流对象?

         这里试着回答一下:        在io操作正在进行的期间,在操作系统中的io缓冲是没有固定大小的。  也就是说,此时可能一个资源的部分在本地,另一部分在远程,就一次传输操作而言。  如果某次传输发生了阻塞,这个流的分布可能会出现这种情况:  一部分在输入缓冲中,一部分在内存中,一部分在文件系统中,一部分在传输道路上,一部分在远端电脑的缓冲中,一部分在远端电脑的内存中,一部分在远端电脑的文件系统中。。。    8中可能的分布(这里面的缓冲 可能就在内存中,那样的话就是六种)。。    当我们传输io传输完成后,java中的 流对象可以被jvm的垃圾回收机制回收没有问题。。  但是我们要知道,流的实现可是通过jni,这个时候是占有了操作系统的一部分缓存的。  操作系统可能没有jvm 这种针对内存的垃圾回收机制。。   所以,我们之所以要管理流对象,实际上释放的并不是java相关的内存资源,而是释放的操作系统缓存相关的内存资源。。。 

下面查看一下多线程下载:

      步骤: 获取连接--> 创建相同大小的空文件 ---> 计算每条线程从哪个部分下载及结束 ---> 依次创建线程

      核心类:  RandomAccessFile;   

      核心方法:HttpURLConnection.setRequestProperty("Range",""xxxxx);

 此外,android官方自带了一个  DownManager 可以 用来下载更新APK,然后覆盖实现。

多线程端点续传思路:

        基于多线程的传输;

        需要记录相关的信息;

        代码在菜鸟

今天已经比较晚了,就改天再继续整理了。。。

猜你喜欢

转载自blog.csdn.net/qq_36285943/article/details/82670174