首页 文章 精选 留言 我的

精选列表

搜索[数据传输],共4253篇文章
优秀的个人博客,低调大师

Spark数据传输及ShuffleClient(源码阅读五)

我们都知道Spark的每个task运行在不同的服务器节点上,map输出的结果直接存储到map任务所在服务器的存储体系中,reduce任务有可能不在同一台机器上运行,所以需要远程将多个map任务的中间结果fetch过来。那么我们就来学习下shuffleClient。shuffleClient存在于每个exeuctor的BlockManager中,它不光是将shuffle文件上传到其他executor或者下载到本地的客户端,也提供了可以被其他exeuctor访问的shuffle服务.当有外部的(其他节点)shuffleClient时,新建ExternalShuffleClient,默认为BlockTransferService.那么真正init的实现方法在NettyBlockTransferService中。 如代码中所示,抽象类blockTransferservice继承自shuffleClient,NettyBlockTransferService实现了shuffleClient的init抽象方法(竟然是java写的)进行初始化提供服务。初始化的过程为:创建NettyBlockRpcServer,构造TransportContext上下文,同时创建了clientFactory,最终创建了Netty服务器TransportServer,可修改属性spark.blockManager.port改变TransportServer的端口。 我们会有疑问,上面那一坨,是干嘛的?我们都知道,map和reduce任务处于不同节点时,reduce任务需要从远端fetch map任务的中间结果输出,NettyBlockRpcServer提供打开,下载Block文件的功能(中间结果在backet中)。NettyBlockRpcServer为了容错,还会将数据备份到其他节点。在new 了之后会根据接收到的message消息,匹配是打开block还是上传block进行容错。如图: 在new完NettyBlockRpcServer后,开始构造传输的上下文TransportContext.构造它的主要作用是,它将既可以创建Netty服务,也可以创建Netty访问客户端,主要包含: 1、TransportConf,控制Netty框架提供的shuffle I/O交互的客户端和服务端线程数量(又发现新的参数)。 2、RpcHandler,负责shuffle的I/O服务端在接受到客户端的RPC请求后,提供打开Block或者上传Block的RPC处理,就是刚才new的NettyBlockRpcServer,可以看到receive。 3、decoder,在shuffle的I/O服务端对客户端传来的ByteBuf进行解析,防止丢包和解析错误。 4、encoder,在shuffle的I/O客户端对消息内容进行编码,防止服务端丢包和解析错误。 那么为什么需要decoder、encoder呢,这里要补习下传输原理,一般基于TCP/IP的流传输中,接收到的数据首先会被存储到一个socket缓冲区中,基于流的传输并不是一个数据包的队列,而是一个字节队列。即使发送两个独立的数据包,操作系统也不会作为2个消息处理,而作为一连串的字节。也就是说 发送的数据可能是 ABC UID GDI ,应用程序读取的时候数据很可能被分成了 AB CUID G DI,所以应该把接收到的数据整理成一个或多个有意义能让程序的逻辑更好理解的数据。 接下来,开始创建RPC客户端工程ClientFactory,它主要:1、缓存客户端列表。2、缓存客户端连接。3、节点之间取数据的连接数,通过spark.shuffle.io.numConnectionsPerPeer来配置,默认为1。4、客户端channel被创建时使用的类,可以使用属性spark.shuffle.io.mode来配置,默认为NioSocketChannel.(NIO还没仔细学习过,它的特点为所有的原始类型提供(Buffer)缓存支持,字符集编码解决方案,提供一个新的原始的I/O抽象Channel,支持锁和内存映射文件的文件访问接口;提供多路非阻塞的高伸缩性网络I/O) 最终,createServer,看不懂NIO,回头恶补下。。 那么下来,到了最重要的环节,获取远程shuffle文件,也就是fetch数据的过程。这个过程就是之前上面NettyBlockTransferService中的fetchBlocks方法(在shuffle过程中,可以通过container日志查看到fetch数据): 可以从传入的参数中看到,会传入拉取节点的IP与PORT以及blockId信息,进行数据的拉取。 那么之前,我们提到的上传shuffle文件,以便之前的拉取,也是先创建了Netty服务的客户端,同时我们可以看到它进行了serializer序列化并转化为了array()数组。随之将blockId、appId、execId等一起封装,调用Netty客户端的sendRpc方法将字节数组上传,同时毁掉函数RpcResponse-CallBack根据RPC的结果更改了上传状态。如下代码: 今天到此为止,开始敲代码~

优秀的个人博客,低调大师

iOS网络编程解析协议二:XML数据传输解析

XML两种解析方式,一种是SAX,NSXMLParser是SAX方法解析,另一种是DOM(Document Object Model); 区别: SAX: 只能读,不能修改,只能顺序访问,适合解析大型XML,解析速度快 常应用于处理大量数据的XML,实现异构系统的数据访问,实现跨平台 从文档的开始通过每一节点移动,定位一个特定的节点 DOM: 不仅能读,还能修改,而且能够实现随机访问,缺点是解析速度慢,适合解析小型文档 一般应用与小型的配置XML,方便操作 为载入到内存的文档节点建立类型描述,呈现可横向移动、潜在巨大的树型结构 在内存中生成节点树操作代价昂贵 这里我们主要介绍使用SAX方式,NSXMLParser是SAX的方法解析,NSXMLParser解析通过NSXMLParserDelegate协议代理方法来完成,解析过程如下: NSXMLParser解析过程: <1>. 创建NSXMLParser实例,并传入从服务器接收的XML数据 <2>. 定义解析器代理 <3>. 解析器解析 <4.. 通过解析代理方法完成XML数据的解析 举例一:把本机服务器上的student.xml文件中数据解析并输出到控制台上。 文件和内容截图截图如下: 具体代码如下: //创建一个学生Student类,并声明属性:姓名name、年龄age、性别sex 1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject 4 @property (copy,nonatomic)NSString *name; 5 @property (assign,nonatomic)NSInteger age; 6 @property (assign,nonatomic)char sex; 7 @end //重写输出方法 1 #import "Student.h" 2 3 @implementation Student 4 5 //重写输出方式 6 -(NSString*)description 7 { 8 return [NSString stringWithFormat:@"name:%@,age:%ld,sex:%c",_name,_age,_sex]; 9 } 10 11 @end //在ViewController类中带入头文件和设置相关的属性信息,同时实现解析协议<NSXMLParserDelegate> 1 #import "ViewController.h" 2 #import "Student.h" 3 4 @interface ViewController ()<NSXMLParserDelegate> 5 @property (strong,nonatomic)NSMutableArray *stus; //存储解析到的学生对象 6 @property (strong,nonatomic)Student *currentStudent; //解析到的当前学生对象 7 @property (strong,nonatomic)NSMutableString *elementValue; //节点值 8 9 @end //下载数据并进行解析 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 //1.从网络下载数据 6 NSURL *URL = [NSURL URLWithString:@"http://localhost/userManager/student.xml"]; 7 NSData *data = [NSData dataWithContentsOfURL:URL]; 8 9 //2.创建解析对象 10 NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; 11 12 //3.设置解析对象的代理 13 parser.delegate = self; 14 15 //4.开始解析 16 [parser parse]; 17 } //实现代理的解析方法 #pragma mark -<NSXMLParserDelegate> //文档开始 1 //文档开始 2 -(void)parserDidStartDocument:(NSXMLParser *)parser 3 { 4 //初始化数组 5 self.stus = [NSMutableArray array]; 6 } //文档结束 1 //文档结束 2 -(void)parserDidEndDocument:(NSXMLParser *)parser 3 { 4 //输出解析后得到的数据 5 [self.stus enumerateObjectsUsingBlock:^(Student *student, NSUInteger idx, BOOL *stop) { 6 NSLog(@"%@",student); 7 }]; 8 } //元素开始 1 //元素开始 2 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 3 { 4 //创建学生对象 5 if([elementName isEqualToString:@"student"]) 6 { 7 self.currentStudent = [[Student alloc]init]; 8 } 9 10 //初始化节点值 11 else if ([elementName isEqualToString:@"name"] || 12 [elementName isEqualToString:@"age"] || 13 [elementName isEqualToString:@"sex"] ) 14 { 15 self.elementValue = [[NSMutableString alloc]init]; 16 } 17 } //找到文字 1 //找到文字 2 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 3 { 4 //获取节点值 5 [self.elementValue appendString:string]; 6 } //元素结束 1 //元素结束 2 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 3 { 4 //解析得到学生对象姓名 5 if([elementName isEqualToString:@"name"]) 6 { 7 self.currentStudent.name = self.elementValue; 8 } 9 10 //解析得到学生对象年龄 11 else if([elementName isEqualToString:@"age"]) 12 { 13 self.currentStudent.age = [self.elementValue integerValue]; 14 } 15 16 //解析得到学生对象性别 17 else if([elementName isEqualToString:@"sex"]) 18 { 19 self.currentStudent.sex = [self.elementValue characterAtIndex:0]; 20 } 21 22 //将学生对象添加到数组中 23 else if ([elementName isEqualToString:@"student"]) 24 { 25 [self.stus addObject:self.currentStudent]; 26 } 27 } //解析出错 1 //解析出错 2 -(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 3 { 4 NSLog(@"解析出错:%@",parseError); 5 } 输出结果如下: 2015-09-24 19:08:34.377 XMLParser解析student.xml[3566:218809] name:kellen,age:25,sex:M 2015-09-24 19:08:34.378 XMLParser解析student.xml[3566:218809] name:jack,age:35,sex:M 举例二:把本机服务器上的cities.xml文件中数据解析并输出到控制台上,这个比较复杂一些。 文件截图和部分内容截图(内容太多,不便全部截图)如下 具体代码如下:都在ViewController类中写代码 //实现协议<NSXMLParserDelegate>并声明必要的属性 1 #import "ViewController.h" 2 3 @interface ViewController ()<NSXMLParserDelegate> 4 @property (strong,nonatomic)NSMutableDictionary *province; //存储所有的省份 5 @property (strong,nonatomic)NSMutableDictionary *city; //存放对应省份的所有城市 6 @property (strong,nonatomic)NSMutableString *keyName; //字典的键名 7 @property (strong,nonatomic)NSMutableString *elementValue; //节点的值 8 @property (strong,nonatomic)NSMutableArray *arrayTemp; //临时数组,存放省名或城市名 9 @end //下载数据并进行解析 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 //1.从网络下载数据 6 NSURL *URL = [NSURL URLWithString:@"http://localhost/userManager/cities.xml"]; 7 NSData *data = [NSData dataWithContentsOfURL:URL]; 8 9 //2.创建解析对象 10 NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data]; 11 12 //3.设置解析对象的代理 13 parser.delegate = self; 14 15 //4.开始解析 16 [parser parse]; 17 } //实现解析代理的方法 #pragma mark -<NSXMLParserDelegate> 文档开始 1 //文档开始 2 -(void)parserDidStartDocument:(NSXMLParser *)parser 3 { 4 //初始化省份字典 5 self.province = [NSMutableDictionary dictionary]; 6 } 文档结束 1 //文档结束 2 -(void)parserDidEndDocument:(NSXMLParser *)parser 3 { 4 //输出所有的城市 5 [self.province setObject:self.city forKey:@"cities"]; 6 NSLog(@"%@",self.province); 7 } 元素开始 1 //元素开始 2 -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 3 { 4 //初始化临时数组 5 if([elementName hasPrefix:@"array"]) 6 { 7 self.arrayTemp = [NSMutableArray array]; 8 } 9 10 //初始化节点值 11 else if ([elementName hasPrefix:@"key"] || [elementName hasPrefix:@"string"]) 12 { 13 self.elementValue = [[NSMutableString alloc]init]; 14 } 15 16 //初始化城市字典 17 else if ([elementName hasPrefix:@"dict"]) 18 { 19 if ([self.keyName hasPrefix:@"cities"]) 20 { 21 self.city = [NSMutableDictionary dictionary]; 22 } 23 } 24 } 找到文字 1 //找到文字 2 -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 3 { 4 [self.elementValue appendString:string]; 5 } 元素结束 1 //元素结束 2 -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 3 { 4 //取节点值 5 if([elementName hasPrefix:@"key"]) 6 { 7 self.keyName = self.elementValue; 8 } 9 10 //将省份或城市添加到临时数组 11 else if ([elementName hasPrefix:@"string"]) 12 { 13 [self.arrayTemp addObject:self.elementValue]; 14 } 15 16 //将临时数组添加到字典中 17 else if([elementName hasPrefix:@"array"]) 18 { 19 if([self.keyName hasPrefix:@"provinces"]) 20 { 21 [self.province setObject:self.arrayTemp forKey:self.keyName]; 22 } 23 else 24 { 25 [self.city setObject:self.arrayTemp forKey:self.keyName]; 26 } 27 } 28 } 解析出错 1 //解析出错 2 -(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 3 { 4 NSLog(@"解析出错:%@",parseError); 5 } 运行结果如下:(由于编码的不同,无法显示汉字,但是结果是正确的,同样内容太多,只给出部分结果) 2015-09-24 19:50:35.139 XMLParse解析cities.xml[3800:240028] { cities = { "\U4e0a\U6d77\n\t\t\n\t\t\t" = ( "\U4e0a\U6d77\n\t\t\n\t\t" ); "\U4e91\U5357\n\t\t\n\t\t\t" = ( "\U6606\U660e\n\t\t\t", "\U4fdd\U5c71\n\t\t\t", "\U695a\U96c4\n\t\t\t", "\U5927\U7406\n\t\t\t", "\U5fb7\U5b8f\n\t\t\t", "\U8fea\U5e86\n\t\t\t", "\U4e2a\U65e7\n\t\t\t", "\U4e3d\U6c5f\n\t\t\t", "\U4e34\U6ca7\n\t\t\t", "\U6012\U6c5f\n\t\t\t", "\U66f2\U9756\n\t\t\t", "\U601d\U8305\n\t\t\t", "\U6587\U5c71\n\t\t\t", "\U897f\U53cc\U7248\U7eb3\n\t\t\t", "\U7389\U6eaa\n\t\t\t", "\U662d\U901a\n\t\t\n\t\t" ); "\U5185\U8499\U53e4\n\t\t\n\t\t\t" = ( "\U547c\U548c\U6d69\U7279\n\t\t\t", "\U963f\U62c9\U5584\U76df\n\t\t\t", "\U5df4\U5f66\U6dd6\U5c14\U76df\n\t\t\t", "\U5305\U5934\n\t\t\t", "\U8d64\U5cf0\n\t\t\t", "\U9102\U5c14\U591a\U65af\n\t\t\t", "\U547c\U4f26\U8d1d\U5c14\n\t\t\t", "\U901a\U8fbd\n\t\t\t", "\U4e4c\U6d77\n\t\t\t", "\U4e4c\U5170\U5bdf\U5e03\U76df\n\t\t\t", "\U9521\U6797\U90ed\U52d2\U76df\n\t\t\t", ...................................... ...................................... 程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式! 本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4836354.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS网络编程解析协议三:JSON数据传输解析

作为一种轻量级的数据交换格式,正在逐步取代XML,成为网络数据的通用格式 基于JavaScript的一个子集 易读性略差,编码手写难度大,数据量小 JSON格式取代了XML给网络传输带来了很大的便利,但是却没有了XML的一目了然,尤其是JSON数据很长的时候,我们会陷入繁琐复杂的数据节点查找中 作为一种轻量级的数据交换格式,JSON正在逐步取代XML,成为网络数据的通用格式 从iOS 5开始,使用NSJSONSerialization对JSON解析 其他常见的三种JSON解析第三方库:SBJson、JSONKit、TouchJson 从性能上来说,NSJSONSerialization最好,JSONKit其次。SBJson使用较为广泛,API简单易用。 使用类方法+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error可以将接收到的JSON 数据反序列化为NSArray或NSDictionary等对象 使用类方法+(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error可以将NSArray或NSDictionary等Foundation对象序列化为JSON数据。 使用类方法+ (BOOL)isValidJSONObject:(id)obj来判断Foundation对象是否可以转换为JSON数据。 这是ios5中apple增加的解析JSON的api——NSJSONSerialization。网上已经有人做过测试,NSJSONSerialization在效率上完胜SBJSON、TouchJSON、YAJL、JSONKit、NextiveJson。详情见这里。既然apple为我们提供了这么良好的工具,我们没理由不用吧。 NSJSONSerialization提供了将JSON数据转换为Foundation对象(一般都是NSDictionary和NSArray)和Foundation对象转换为JSON数据(可以通过调用isValidJSONObject来判断Foundation对象是否可以转换为JSON数据)。 举例如下: 演示一:将前面演示过的cities.xml解析得到结果后将它保存到cities.json文件中; 演示二:再将cities.json文件中数据解析出来并输出在控制台上。 没解析前的文件截图如下: 解析成功后保存的文件截图: 代码如下:在ViewController类中进行操作 //将这两种演示方式封装 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 [self JSONObjectFromData]; //将cities.xml文件解析出来并保存到cities.json文件中 5 [self dataFromJSONObject]; //将cities.json文件解析输出 } //演示一:将本机服务器上的cities.xml解析得到结果后将它保存到cities.json文件中 1 -(void)dataFromJSONObject 2 { 3 //从网络数据生成字典 4 NSDictionary *dic = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:@"http://127.0.0.1/userManager/cities.xml"]]; 5 6 //将字典转换为JSON 7 NSError *error = nil; 8 NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error]; 9 10 if(!error) 11 { 12 //将JSON数据保存到文件中 13 NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 14 NSString *documentPath = [documents lastObject]; 15 16 NSString *JSONPath = [documentPath stringByAppendingPathComponent:@"cities.json"]; 17 18 [[NSFileManager defaultManager] createFileAtPath:JSONPath contents:data attributes:nil]; 19 } 20 } //演示二:再将cities.json文件中数据解析出来并输出在控制台上 1 -(void)JSONObjectFromData 2 { 3 NSURL *URL = [NSURL URLWithString:@"http://localhost/userManager/cities.json"]; 4 5 NSData *data = [NSData dataWithContentsOfURL:URL]; 6 7 //将JSON数据转化为相应的对象 8 NSError *error = nil; 9 id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error]; 10 11 12 //判断对象的类型 13 if(!error) 14 { 15 if([obj isKindOfClass:[NSDictionary class]]) 16 { 17 NSDictionary *dic = obj; 18 NSLog(@"dic:%@",dic); 19 NSArray *provinces = [dic objectForKey:@"provinces"]; 20 [provinces enumerateObjectsUsingBlock:^(NSString *province, NSUInteger idx, BOOL *stop) { 21 NSLog(@"%@",province); 22 }]; 23 } 24 else if([obj isKindOfClass:[NSArray class]]) 25 { 26 NSArray *array = obj; 27 NSLog(@"array:%@",array); 28 } 29 } 30 } 演示二结果如下:(内容太多,只给出部分) .............. .............."\U65b0\U7586", "\U4e91\U5357", "\U6d59\U6c5f" ); } 2015-09-24 20:09:55.616 04-JSON[3914:247373] 安徽 2015-09-24 20:09:55.616 04-JSON[3914:247373] 澳门 2015-09-24 20:09:55.616 04-JSON[3914:247373] 北京 2015-09-24 20:09:55.616 04-JSON[3914:247373] 重庆 2015-09-24 20:09:55.617 04-JSON[3914:247373] 福建 2015-09-24 20:09:55.617 04-JSON[3914:247373] 甘肃 2015-09-24 20:09:55.617 04-JSON[3914:247373] 广东 2015-09-24 20:09:55.617 04-JSON[3914:247373] 广西 2015-09-24 20:09:55.617 04-JSON[3914:247373] 贵州 2015-09-24 20:09:55.617 04-JSON[3914:247373] 海南 2015-09-24 20:09:55.618 04-JSON[3914:247373] 河北 2015-09-24 20:09:55.618 04-JSON[3914:247373] 河南 2015-09-24 20:09:55.618 04-JSON[3914:247373] 黑龙江 2015-09-24 20:09:55.618 04-JSON[3914:247373] 湖北 2015-09-24 20:09:55.618 04-JSON[3914:247373] 湖南 2015-09-24 20:09:55.618 04-JSON[3914:247373] 吉林 2015-09-24 20:09:55.618 04-JSON[3914:247373] 江苏 2015-09-24 20:09:55.619 04-JSON[3914:247373] 江西 2015-09-24 20:09:55.619 04-JSON[3914:247373] 辽宁 2015-09-24 20:09:55.619 04-JSON[3914:247373] 内蒙古 2015-09-24 20:09:55.619 04-JSON[3914:247373] 宁夏 2015-09-24 20:09:55.619 04-JSON[3914:247373] 青海 2015-09-24 20:09:55.619 04-JSON[3914:247373] 山东 2015-09-24 20:09:55.619 04-JSON[3914:247373] 山西 2015-09-24 20:09:55.686 04-JSON[3914:247373] 陕西 2015-09-24 20:09:55.686 04-JSON[3914:247373] 上海 2015-09-24 20:09:55.686 04-JSON[3914:247373] 四川 2015-09-24 20:09:55.686 04-JSON[3914:247373] 台湾 2015-09-24 20:09:55.687 04-JSON[3914:247373] 天津 2015-09-24 20:09:55.687 04-JSON[3914:247373] 西藏 2015-09-24 20:09:55.687 04-JSON[3914:247373] 香港 2015-09-24 20:09:55.687 04-JSON[3914:247373] 新疆 2015-09-24 20:09:55.687 04-JSON[3914:247373] 云南 2015-09-24 20:09:55.688 04-JSON[3914:247373] 浙江 程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式! 本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4836404.html,如需转载请自行联系原作者

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册