1给定父文件夹路径,找出该文件夹中所有的内容(文件夹或文件)。
2筛选出内容中的文件夹。
总的来说,实现还是挺简单的,python的os包也提供了许多方法。具体看代码
[python] view plain copy
# -- coding: UTF-8 --
import ospath
#定义一个函数,path为你的路径
def traversalDir_FirstDir(path):
#定义一个列表,用来存储结果
list = []
#判断路径是否存在
if (ospathexists(path)):
#获取该目录下的所有文件或文件夹目录
files = oslistdir(path)
for file in files:
#得到该文件下所有目录的路径
m = ospathjoin(path,file)
#判断该路径下是否是文件夹
if (ospathisdir(m)):
h = ospathsplit(m)
print h[1]
listappend(h[1])
print list
traversalDir_FirstDir("E:\\xlrd-100")
输出结果为:
[plain] view plain copy
build
dist
scripts
tests
xlrd
xlrdegg-info
['build', 'dist', 'scripts', 'tests', 'xlrd', 'xlrdegg-info']
Python有一个方法是ospathisdir(pyth),即判断该路径下的文件下是否是文件夹,其传入的参数的参数是路径,我在想,Python要是提供一个方法,返回该文件下的所有文件路径就好,但貌似我没有找到。所以用了oslistdir(pyth),得到了路径下的所有内容名,然后又用了join()方法把其转化成路径~,额,有些麻烦了。其中split()会把路径截成一个二元组(路径,文件名)
其实有个方法,oswalk()方法可以得到该文件夹下所有文件夹和文件,但我只要求得到子一级文件夹哈。具体可参考旁边链接:点击打开链接。
下面再附上Python的 os的一些属性方法:os模块方法
因之前我学过一些Java,所以感觉Python语法跟Java差不多,不过比Java更加简练
额,发现一个函数,glob()方法可以直接得到一个文件夹下所有的路径。上面的代码可以改进如下:
[python] view plain copy
# -- coding: UTF-8 --
import glob
import ospath
def traversalDir_FirstDir(path):
list = []
if (ospathexists(path)):
#获取该目录下的所有文件或文件夹目录路径
files = globglob(path + '\\' )
print files
for file in files:
#判断该路径下是否是文件夹
if (ospathisdir(file)):
#分成路径和文件的二元元组
h = ospathsplit(file)
print h[1]
listappend(h[1])
print list
traversalDir_FirstDir("E:\\xlrd-100")接受输入设备的中断,并将原始事件的输入写入设备节点中;
作为内核和IMS的桥梁,将原始事件的数据暴露给用户空间,以便IMS可以从中读取事件;
Android系统服务,它分为java层和native层两部分;java层负责与WMS通信,native层则是InputReader和InputDispatcher两个输入系统关键组件的运行容器;
使用inotify监听输入设备的添加和移除。
使用epoll机制监听输入设备的数据变化。
读取设备文件的数据。
将原始数据(生事件)返回给InputReader。
IMS中的关键组件之一,它运行于一个独立的线程中,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过其线程循环不断地通过getEvents()函数从EventHub中将事件取出并进行处理。对于设备节点的增删事件,它会更新输入设备列表与配置。对于原始输入事件,InputReader对其进行翻译、组装、封装为包含更多信息、更具可读性的输入事件,然后交给InputDispatcher进行派发;
IMS中的另一个关键组件,它也运行于一个独立的线程中。InputDispatcher中保管了来自WMS的所有窗口的信息,其收到来自InputReader的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口;
InputChannel支持跨进程传输。
保存socketpair的FD,App进程持有一端,WMS进程持有一端。
InputChannel负责事件最终的读写。
包装了InputChannel,负责将InputChannel的FD加入到main looper并负责读写InputChannel。
将事件封装成Java层的事件对象向上派发给ViewRootImpl。
不是输入系统的一员,但它对InputDispatcher的正常工作起到重要作用。当新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道。另外,WMS还将所有窗口的信息,包括窗口的可点击区域,焦点窗口等信息,实时的更新到IMS的InputDispatcher中,使得InputDispatcher可以正确地将事件派发到指定的窗口;
对某些窗口,如壁纸窗口、SurfaceView的窗口来说,窗口就是输入事件派发的终点。而对其他的activity、对话框等使用了Android控件系统的窗口来说,输入事件的终点是控件View。ViewRootImpl将窗口所接收的输入事件沿着控件树将事件派发给感兴趣的控件;
INotify是一个Linux内核所提供的一种文件系统变化通知机制。它可以为应用程序监控文件系统的变化,如文件的新建、删除、读写等。INotify机制有两个基本对象,分别为inotify对象与watch对象,都使用文件描述符表示。
inotify对象对应了一个队列,应用程序可以向inotify对象添加多个监听。当被监听的事件发生时,可以通过read()函数从inotify对象中将事件信息读取出来。Inotify对象可以通过以下方式创建:
而watch对象则用来描述文件系统的变化事件的监听。它是一个二元组,包括监听目标和事件掩码两个元素。
当没有监听事件发生时,可以通过如下方式将一个或多个未读取的事件信息读取出来:
总结一下INotify机制的使用过程:
通过inotify_init()创建一个inotify对象。
通过inotify_add_watch将一个或多个监听添加到inotify对象中。
通过read()函数从inotify对象中读取监听事件。当没有新事件发生时,inotify对象中无任何可读数据。
Epoll可以使用一次等待监听多个描述符的可读/可写状态。等待返回时携带了可读的描述符或自定义的数据,使用者可以据此读取所需的数据后可以再次进入等待。因此不需要为每个描述符创建独立的线程进行阻塞读取,避免了资源浪费的同时又可以获得较快的响应速度。
Epoll机制的接口只有三个函数,十分简单。
epoll_create(int max_fds):创建一个epoll对象的描述符,之后对epoll的 *** 作均使用这个描述符完成。max_fds参数表示了此epoll对象可以监听的描述符的最大数量。
epoll_ctl (int epfd, int op,int fd, struct epoll_event event):用于管理注册事件的函数。这个函数可以增加/删除/修改事件的注册。
int epoll_wait(int epfd, structepoll_event events, int maxevents, int timeout):用于等待事件的到来。当此函数返回时,events数组参数中将会包含产生事件的文件描述符。
Epoll的使用步骤总结如下:
通过epoll_create()创建一个epoll对象。
为需要监听的描述符填充epoll_events结构体,并使用epoll_ctl()注册到epoll对象中。
使用epoll_wait()等待事件的发生。
根据epoll_wait()返回的epoll_events结构体数组判断事件的类型与来源并进行处理。
继续使用epoll_wait()等待新事件的发生。
IMS在SystemServer中的ServerThread线程中启动,在InputManagerService的构造函数中调用nativeInit方法,nativeInit方法创建了一个类型为NativeInputManager的对象,它是Java层与Native层互相通信的桥梁。NativeInputManager位于IMS的jni层,负责native层的组件与java层的IMS的相互通信,同时它为主要工作是为InputReader和InputDispatcher提供策略请求接口InputReaderPolicyInterface和InputDispatcherPolicyInterface,策略请求被它转发为Java层的IMS,由IMS最终确定。在NativeInputManager构造函数中创建了EventHub和InputManager。在InputManager中创建了四个对象,分别为InputDispatcher,InputReader,InputReaderThread和InputDispatcherThread。
####### InputReader总体流程
1、首先从EventHub中抽取未处理的事件列表,这些事件分为两类,一类是从设备节点读取的原始输入事件,另一类是设备事件。
2、对原始输入事件进行封装与加工将结果暂存到mQueuedListener中。
3所有事件处理完毕之后,调用mQueuedListenerflush()将所有暂存的输入事件一次性的交付给InputDispatcher
EventHub中抽取未处理的事件列表主要是调用getEvents函数,getEvents函数的本质是通过epoll_wait()获取Epoll事件到事件池,并对事件池中的事件进行消费的过程。从epoll_wait()的调用开始到事件池的最后一个时间被消费完毕的过程称为EventHub的一个监听周期。由于buffer参数的额尺寸限制,一个监听周期可能包含多个getEvents调用。
InputReader经过加工之后,输出的事件分为三种基本类型,分别为:按键类型,手势类型和开关类型。三种类型分别由NotifyKeyArgs,NotifyMotionArgs,NotifySwitchArgs三个结构体描述。可以说EventHub的EawEvent是InputReader的输入,而上述三个结构体是InputReader的输出。InputDispatcher继承了InputListenerInterface,实现了notifyKey和notifyMotion和notifySwitch等方法。创建InputReader时将InputDispatcher传给了InputReader。InputReader以InputListenerInterface类型持有InputDispatcher。然后调用mQueuedListenerflush()将三种类型事件传给InputDispatcher。
在这有个问题,为什么不直接使用InputDispatcher作为事件的接受者,而是用QueuedInputListener这个中间人?QueuedInputListener是使用mArgsQueue队列将信息保存起来,当InputReader处理完自EventHub的所有原始输入事件之后,调用flush()函数将缓存的事件信息取出,这样做的目的是,减少InputDispatcher的休眠与唤醒次数,因为InputDispatcher派发的速度快于InputReader加工一个原始输入事件的速度,就会导致InputDispatcher多次休眠与唤醒。
InputReader将处理好的事件提交给InputDispatcher之后,会将输入事件放进派发队列,但是在放进派发队列之前,需要先过滤。过滤之后将事件封装成EventEntry的子类,然后调用enqueueInboundEventLocked()将事件注入mInboundQueue的队尾,并且根据mInboundQueue是否为空来是否唤醒派发线程。
真正的派发是调用dispatchOnceInnerLocked()函数,如果派发队列为空,则会使派发线程陷入无限期休眠状态,即将被派发的事件从派发队列中取出,事件也有可能某些原因被丢弃,被丢弃的原因保存在dropReason中,然后去寻找合适的窗口,目标窗口分为两种:普通窗口和监听窗口。普通窗口通过按点查找与按焦点查找两种方式获得,而监听窗口则无条件监听所有输入事件。
Motion事件派发与按键事件派发的区别:
按键事件在正式派发给窗口之前,进行一次额外的派发策略查询,这个查询结果决定此事件是正常派发、稍后派发还是丢弃。
按键事件的派发目标仅通过焦点方式进行查找。
派发找到对应的窗口之后,然后根据window找到Connection,然后将事件加到Connection的outboundQueue, 然后从outboundQueue队头取一个消息,调用Connection的InputPublisher发送事件,InputPublisher最终会调用InputChannel,InputChannel用自己保存的FD调用socketpair的senMsg函数将事件发出。
一个window对应一个InputChannel对应一个Connection。
发完事件后,将这个消息记录到Connection的waitQueue的队尾。InputDispatcherThread再次等待在Looper上,等App窗口消费完事件并发送finish事件后,InputDispatcherThread就会被唤醒,然后根据发生消息的FD(一个窗口对应一个FD)找到Connection,再根据事件的序列号(seq)找到事件然后将事件从waitQueue移除,并继续派发属于这个Connction的消息。
InputChannel本质是一对SocketPair(非网络套接字)。SocketPair用来实现在本机内进行进程间的通信。一对SocketPair通过socketpair()函数创建,其使用者可以因此而得到两个相互连接的文件描述符。这两个描述符可以通过套接字接口send()和recv()进行写入和读取,并且向其中一个文件描述符写入的数据,可以从另一个描述符中读取。同pipe()所创建的管道不同,SocketPair的两个文件描述符是双通的,因此非常适合用来进行进程间的交互式通信;
1事件发送主要是通过InputChannel来完成;
2在wms 执行addView()时,调用openInputChannel来从native层获取inputchannels数组,一个通过ims
registerInputChannel来连接InputDispatcher,另外一个通过InputEventReceiver来连接窗口;
3InputDispatcher经过Connection最终通过InputPublisher将事件发送到目标窗口;
4NativeInputEventListener监听到事件到来时通过InputConsumer处理InputMessage后回调Java层接口;
Connection包含两个队列,分别为outboundQueue和waitQueue。还持有InputPublisher对象。
InputPublisher封装InputChannel并直接对齐进行写入和读取,也负责InputMessage结构体的封装和解析。
outboundQueue保存等待Connection进行发送事件的队列。
waitQueue已发送等待反馈的队列,得到反馈后则从队列中删除。
App进程获取到InputChannel后将之内部的socketpair的FD加入到main looper的FD监听列表中去,后续如果收到事件,事件的处理会直接发生在主线程,main looper监听到FD上有数据后回调FD绑定的回调函数,回调函数将事件读出来封装成对应的Event对象,然后层层传递到ViewRootImpl。ViewRootImpl通过一个责任链决定事件的处理顺序和方式,某些事件可能会先派发给输入法窗口进行消费,如果输入法窗口不消费就继续派发给view tree消费,派发给view tree是直接派发的,因为这时已经在主线程了,流程大致是:
ViewRootImpl -> DecorView -> Activity -> View(DecorView) -> DecorView的子View
如果App进程没有消费事件,也就是Activity、View等都没有处理这个事件,App进程发送给InputDispather的finish事件会标志这个事件的handled为false。
InputDispatcher收到handled为false的事件后会询问IMS是否备选(fallback)事件,IMS最终会经过WMS到PhoneWindowManager询问是否有备选事件,如果有就将PhoneWindowManager返回的备选事件加入到窗口对应的connection的outboundQueue的队头,在下一次窗口派发循环(注意InputDispather的mInboundQueue队列对应的大循环和connection的outboundQueue对应的窗口事件小循环)中将这个事件发给窗口。
派发循环和事件发送循环
派发循环是InputDiapatcher不断的从派发队列取出事件,寻找合适的窗口进行发送的过程,主要是InputDispatcherThread线程主要的工作。
事件发送循环是InputDispatcher通过Connection对象将事件发送到窗口,并接受反馈的过程
数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。记为:数据结构Data_Structure=(D,R)其中D是数据元素的集合,R是该集合中所有元素之间的关系的有限集合。
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。
数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。
数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种 *** 作。数据结构主要研究数据的各种逻辑结构和存储结构,以及对数据的各种 *** 作。
因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的 *** 作(或算法)。通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。
扩展资料:
一、数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关。
逻辑结构包括:
1、集合:数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;
2、线性结构:数据结构中的元素存在一对一的相互关系;
3、树形结构:数据结构中的元素存在一对多的相互关系;
4、图形结构:数据结构中的元素存在多对多的相互关系。
二、数据的物理结构:指数据的逻辑结构在计算机存储空间的存放形式。
数据的物理结构是数据结构在计算机中的表示(又称映像),它包括数据元素的机内表示和关系的机内表示。
由于具体实现的方法有顺序、链接、索引、散列等多种,所以,一种数据结构可表示成一种或多种存储结构。
数据元素的机内表示(映像方法): 用二进制位(bit)的位串表示数据元素。通常称这种位串为节点(node)。
当数据元素有若干个数据项组成时,位串中与个数据项对应的子位串称为数据域(data field)。因此,节点是数据元素的机内表示(或机内映像)。
关系的机内表示(映像方法):数据元素之间的关系的机内表示可以分为顺序映像和非顺序映像,常用两种存储结构:顺序存储结构和链式存储结构。
顺序映像借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。非顺序映像借助指示元素存储位置的指针(pointer)来表示数据元素之间的逻辑关系。
三、结构算法
算法的设计取决于数据(逻辑)结构,而算法的实现依赖于采用的存储结构。数据的存储结构实质上是它的逻辑结构在计算机存储器中的实现,为了全面的反映一个数据的逻辑结构,它在存储器中的映象包括两方面内容,即数据元素之间的信息和数据元素之间的关系。
不同数据结构有其相应的若干运算。数据的运算是在数据的逻辑结构上定义的 *** 作算法,如检索、插入、删除、更新和排序等。
参考资料来源: 百度百科---数据结构
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)