.NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)

Standard

工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为 ASP.NET 开发者介绍一些高效实用的工具,包括 SQL 管理,VS插件,内存管理,诊断工具等,涉及开发过程的各个环节,让开发效率翻倍。当然,吾乐吧软件站认为.NET神器第一名的绝对是ReSharper,有了这个,基本上其他工具都可以忽略!

.NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)

.NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)

Visual Studio

  • Jetbrains ReSharper Ultimate:VS最强的插件,没有之一,支持:C#, VB.NET, ASP.NET, XML, XAML, C++, JavaScript,CSS,Razor视图引擎等等~~
  • Visual Studio Productivity Power tool: VS 专业版的效率工具。
  • Web Essentials: 提高开发效率,能够有效的帮助开发人员编写CSS, JavaScript, HTML 等代码。
  • MSVSMON: 远程Debug 监控器 (msvsmon.exe) 是一种轻量级的应用程序,能够远程控制VS来调试程序。在远程调试期间,VS 在调试主机运行,MSVSMON 在远程机器中运行。
  • WIX toolset: 可以将XML 源代码文件编译成Windows 安装包。
  • Code digger: Code Digger 是VS 2012/2013 的扩展插件,能够帮助开发人员分析代码。
  • CodeMaid: CodeMaid 是一款开源的VS2012/2013/2015 插件,提供代码分析,清理,简化代码的功能。
  • OzCode: 非常强大的VS 调试工具。
  • CodeRush: 是VS的提高代码重构和提升效率的VS插件。
  • T4 Text Template:VS中T4 文本模板是生成代码文件最常用的模板文件,这种模板文件是通过编写文本块和控制逻辑来实现的。
  • Indent Guides:  快速添加缩进行。
  • PowerShell Tools:支持开发和调试PowerShell 脚本和VS2015代码块的工具包。
  • Visual Studio Code: 免费的跨平台编辑器,可以编译和调试现代的Web和云应用。

ASP.NET

  • Fiddler: 能够捕获 http 请求/响应来模拟请求行为。
  • AutoMapper: 自动生成对象到对象的映射代码,比如,能够生成从实体对象映射到域对象,而不是手动编写映射代码。Object to object mapping. Like, the tool can be used to map entity objects to domain objects instead of writing manual mapping code.
  • Unity/Ninject/Castle Windsor/StructureMap/Spring.Net: 依赖性映射框架,提供很多可用的DI 框架。
  • .NET Reflector: .NET 程序反编译器。
  • dotPeek: .NET 程序反编译器。
  • ILSpy: .NET 程序反编译器。
  • memprofiler: 非常强大的查找内存泄露和优化内存使用的工具。
  • PostSharp: 去除重复编码和避免由于交叉引用产生的代码冗余。
  • ASPhere: Web.config 图形化编辑器
  • ComponentOne Studio for ASP.NET 一整套完备的开发工具包

WCF

  • SOAP UI: API 测试工具,支持所有标准的协议和技术。
  • WireShark:UNIX和Windows系统的网络协议分析器。用于捕获TCP 层的拥塞状况,还能帮你过滤无效信息。
  • Svc TraceViewer: 提供文件追踪视图,是由WFO提供的。
  • Svc Config Editor: 用于管理WCF相关配置的图形化界面工具。

MSMQ

  • QueueExplorer 3.4: 提供消息操作功能,如复制,删除,移动消息,保存和加载,强压测试,浏览编辑等

LINQ

  • LINQ Pad: LINQPad 是一个轻量级工具,用来测试Linq查询。 可以测试由不同语言写的.Net 语言脚本。
  • LINQ Insight: LINQ Insight Express 可嵌入 Visual Studio 中,能够分析设计时的LINQ查询 。

RegEx

  • RegEx tester: 正则表达式插件。
  • regexr: 在线正则表达式开发和测试工具。
  • regexpal: 在线正则表达式开发和测试工具。
  • Expresso: 桌面版的正则表达式工具。
  • RegexMagic : 能够根据文本模式自动生成正则表达式的工具。

Javascript/JQuery/AngularJS

  • JSHint: JavaScript代码质量监控工具,定义了很多非常严格的规则。
  • JSFiddle: 提供了浏览器内部的开发环境,能够测试HTML,CSS,Javascript/JQuery代码
  • Protractor: 端到端的框架,能够测试Angular应用。

SQL Server

  • SQL Profiler: SQL 跟踪监控工具。
  • ExpressProfiler: ExpressProfiler (aka SqlExpress Profiler) 是一个小型快速的SQL Server Profiler的替换工具,自带GUI界面。能够用于企业版和非企业版 的SQL Server。
  • SQL Sentry Plan explorer: 提供了SQL 查询执行计划的很好的物理视图。
  • SQL Complete: 为 SQL Server Management Studio and Visual Studio 提供非常智能的,优化SQL 格式的管理工具。
  • NimbleText:文本操作和代码生成工具。
  • Query Express: 轻量级的SQL 查询分析器。
  • IO Meter: 提供IO 子系统的一些访问具体情况
  • sqldecryptor: 可以解密SQL Server 中的加密对象,如存储过程,方法,触发器,视图。
  • SpatialViewer: 可以预览和创建空间数据。
  • ClearTrace: 导入跟踪和分析文件,并显示汇总信息。
  • Internals Viewer for SQL Server: Internals Viewer 用来在SQL Server 的存储引擎中的查找工具,以及获取数据在物理层是如何分配,组织和存储的。

NHibernate

Tally

Tally ERP 9

  • Tally dll: .net 的动态链接库,能够将Tally Accounting 软件集成到应用程序中 ,通过代码对数据进行push或pull操作。

代码Review

  • StyleCop: StyleCop 是静态代码分析工具,能够统一设置代码样式和规范。 可以在Visual Studio 中使用,也可以集成到 MSBuild 项目。
  • FxCop: FxCop 是静态代码分析工具,能够通过分析.Net 程序集保证开发标准。

运行状况捕获

  • WireShark: It is a network protocol analyzer for Unix and Windows. It can capture traffic at TCP level.
  • HTTP Monitor: enables the developer to view all the HTTP traffic between your computer and the Internet. This includes the request data (such as HTTP headers and form GET and POST data) and the response data (including the HTTP headers and body).

诊断工具

  • Glimpse:提供服务器端诊断数据。如 在ASP.NET MVC 项目,可以通过NuGet添加。

性能

  • PerfMon: 使用 性能计数器监控系统性能。

代码转换器

  • Telerik Code Converter: C# 到 VB 及 VB 到C# 代码转换器. I是一个在线编辑工具,可以选择 ‘Batch Converter’ ,并使用压缩包上传文件。

屏幕记录工具

  • Wink: Using Wink, 可以轻松截图,并为截图添加描述等,也可以录制Demo。

文本编辑器

文档工具

  • GhostDoc: GhostDoc 是 Visual Studio 扩展项,能够自动生成 方法或属性的 文档注释,包括它们的类型,名称,其他上下文信息。
  • helpndoc: helpndoc 用于创建帮助文档工具,能够根据文档源生成多种格式。
  • 其他
  • FileZilla: FileZilla 是开源的FTP 工具. 通过FileZilla 客户端可以将文件上传到FTP 服务器上。
  • TreeTrim: TreeTrim 是调整代码的工具,能够删除一些无效的debug文件和临时文件等。
  • BrowserStack: 支持跨浏览器测试的工具。
  • BugShooting: 屏幕截图软件,能够铺货和附加工作项,bug,问题跟踪项等。
  • Postman: REST 客户端,能够发送http请求,分析REST 应用程序发出的响应。
  • Web developer checklist: checklist可用来管理开发计划
  • PowerGUI: 能够快接收和使用PowerShell 来有效管理 Windows 开发环境。
  • Beyond Compare: 提供文件对比功能。
  • PostMan: REST Chrome 器扩展项
  • Devart Codecompare: 文件区分工具,能够读取 C#, C++,VB 代码结构 。包括:文件夹对比工具,独立App 比较合并文件夹和文件,代码review 支持。

C++文件操作详解

Standard

原文:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551662.html

C++ 通过以下几个类支持文件的输入输出:

ofstream: 写操作(输出)的文件类 (由ostream引申而来)
ifstream: 读操作(输入)的文件类(由istream引申而来)
fstream: 可同时读写操作的文件类 (由iostream引申而来)
打开文件(Open a file)
对这些类的一个对象所做的第一个操作通常就是将它和一个真正的文件联系起来,也就是说打开一个文件。被打开的文件在程序中由一个流对象(stream object)来表示 (这些类的一个实例) ,而对这个流对象所做的任何输入输出操作实际就是对该文件所做的操作。

要通过一个流对象打开一个文件,我们使用它的成员函数open():void open (const char * filename, openmode mode);

这里filename 是一个字符串,代表要打开的文件名,mode 是以下标志符的一个组合: ios::in 为输入(读)而打开文件
ios::out 为输出(写)而打开文件
ios::ate 初始位置:文件尾
ios::app 所有输出附加在文件末尾
ios::trunc 如果文件已存在则先删除该文件
ios::binary 二进制方式
这些标识符可以被组合使用,中间以”或”操作符(|)间隔。例如,如果我们想要以二进制方式打开文件”example.bin” 来写入一些数据,我们可以通过以下方式调用成员函数open()来实现:ofstream file;
file.open (“example.bin”, ios::out | ios::app | ios::binary);

ofstream, ifstream 和 fstream所有这些类的成员函数open 都包含了一个默认打开文件的方式,这三个类的默认方式各不相同: 类 参数的默认方式
ofstream ios::out | ios::trunc
ifstream ios::in
fstream ios::in | ios::out
只有当函数被调用时没有声明方式参数的情况下,默认值才会被采用。如果函数被调用时声明了任何参数,默认值将被完全改写,而不会与调用参数组合。

由 于对类ofstream, ifstream 和 fstream 的对象所进行的第一个操作通常都是打开文件,这些类都有一个构造函数可以直接调用open 函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:ofstream file (“example.bin”, ios::out | ios::app | ios::binary);

两种打开文件的方式都是正确的。

你可以通过调用成员函数is_open()来检查一个文件是否已经被顺利的打开了:bool is_open();

它返回一个布尔(bool)值,为真(true)代表文件已经被顺利打开,假( false )则相反。

关闭文件(Closing a file)
当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据排放出来并关闭文件。它的格式很简单:void close ();

这个函数一旦被调用,原先的流对象(stream object)就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程(process)所有访问了。

为防止流对象被销毁时还联系着打开的文件,析构函数(destructor)将会自动调用关闭函数close。

文本文件(Text mode files)
类ofstream, ifstream 和fstream 是分别从ostream, istream 和iostream 中引申而来的。这就是为什么 fstream 的对象可以使用其父类的成员来访问数据。

一般来说,我们将使用这些类与同控制台(console)交互同样的成员函数(cin 和 cout)来进行输入输出。如下面的例题所示,我们使用重载的插入操作符<<:

// writing on a text file
#include &lt;fstream&gt;
using namespace std;

int main()
{
    ofstream examplefile("example.txt");
    if (examplefile.is_open())
    {
        examplefile &lt;&lt; "This is a line.\n";
        examplefile &lt;&lt; "This is another line.\n";
        examplefile.close();
    }
    return 0;
}

从文件中读入数据也可以用与 cin的使用同样的方法:

// reading a text file
#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;cstdlib&gt;
using namespace std;
int main ()
{
    char buffer[256];
    ifstream examplefile("example.txt");
    if (! examplefile.is_open())
    {
        cout &lt;&lt; "Error opening file"; exit (1);
    }
    while (!examplefile.eof())
    {
        examplefile.getline(buffer,100);
        cout&lt;&lt;buffer&lt;&lt; endl;
    }
    return 0;
}
//This is a line.
//This is another line.

上面的例子读入一个文本文件的内容,然后将它打印到屏幕上。注意我们使用了一个新的成员函数叫做eof ,它是ifstream 从类 ios 中继承过来的,当到达文件末尾时返回true 。

状态标志符的验证(Verification of state flags)
除了eof()以外,还有一些验证流的状态的成员函数(所有都返回bool型返回值):

bad()
如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

fail()
除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

eof()
如果读文件到达文件末尾,返回true。

good()
这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

要想重置以上成员函数所检查的状态标志,你可以使用成员函数clear(),没有参数。

获得和设置流指针(get and put stream pointers)
所有输入/输出流对象(i/o streams objects)都有至少一个流指针:

ifstream, 类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
ofstream, 类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
fstream, 类似 iostream, 同时继承了get 和 put
我们可以通过使用以下成员函数来读出或配置这些指向流中读写位置的流指针:

tellg() 和 tellp()
这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前get 流指针的位置 (用tellg) 或 put 流指针的位置(用tellp).

seekg() 和seekp()
这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:
seekg ( pos_type position );
seekp ( pos_type position );
使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。
seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );
使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。它可以是: ios::beg 从流开始位置计算的位移
ios::cur 从流指针当前位置开始计算的位移
ios::end 从流末尾处开始计算的位移
流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。

以下例子使用这些函数来获得一个二进制文件的大小:

// obtaining file size
#include &lt;iostream&gt;
#include &lt;fstream&gt;
using namespace std;

int main ()
{
    const char * filename = "example.txt";
    long l,m;
    ifstream file(filename, ios::in|ios::binary);
    l = file.tellg();
    file.seekg(0, ios::end);
    m = file.tellg();
    file.close();
    cout &lt;&lt;"size of "&lt;&lt; filename;
    cout &lt;&lt;" is "&lt;&lt; (m-l)&lt;&lt;" bytes.\n";
    return 0;
}
//size of example.txt is 40 bytes.

二进制文件(Binary files)
在二进制文件中,使用<< 和>>,以及函数(如getline)来操作符输入和输出数据,没有什么实际意义,虽然它们是符合语法的。

文 件流包括两个为顺序读写数据特殊设计的成员函数:write 和 read。第一个函数 (write) 是ostream 的一个成员函数,都是被ofstream所继承。而read 是istream 的一个成员函数,被ifstream 所继承。类 fstream 的对象同时拥有这两个函数。它们的原型是:
write ( char * buffer, streamsize size );
read ( char * buffer, streamsize size );
这里 buffer 是一块内存的地址,用来存储或读出数据。参数size 是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。

// reading binary file
#include &lt;iostream&gt;
#include &lt;fstream&gt;
using namespace std;
int main ()
{
    const char * filename = "example.txt";
    char * buffer;
    long size;
    ifstream file(filename, ios::in|ios::binary|ios::ate);
    size = file.tellg();
    file.seekg(0, ios::beg);
    buffer = new char [size];
    file.read(buffer, size);
    file.close();
    cout &lt;&lt;"the complete file is in a buffer";
    delete[] buffer;
    return 0;
}
//The complete file is in a buffer

缓存和同步(Buffers and Synchronization)
当我们对文件流进行操作的时候,它们与一个streambuf 类型的缓存(buffer)联系在一起。这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。例如,对于一个输出流, 每次成员函数put (写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。

当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:

当文件被关闭时: 在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。
当缓存buffer 满时:缓存Buffers 有一定的空间限制。当缓存满时,它会被自动同步。
控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush 和endl。
明确调用函数sync(): 调用成员函数sync() (无参数)可以引发立即同步。这个函数返回一个int 值,等于-1 表示流没有联系的缓存或操作失败。
在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:

1、插入器(<<)
向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<“Write Stdout”<<‘n’;就表示把字符串”Write Stdout”和换行字符(‘n’)输出到标准输出流。

2、析取器(>>)
从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。

在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。

一、打开文件
在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:

void open(const char* filename,int mode,int access);

参数:

filename: 要打开的文件名
mode: 要打开文件的方式
access: 打开文件的属性
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:

ios::app: 以追加的方式打开文件
ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性
ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
ios::in: 文件以输入方式打开
ios::out: 文件以输出方式打开
ios::nocreate: 不建立文件,所以文件不存在时打开失败
ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
ios::trunc: 如果文件存在,把文件长度设为0
可以用“或”把以上属性连接起来,如ios::out|ios::binary

打开文件的属性取值是:

0:普通文件,打开访问
1:只读文件
2:隐含文件
4:系统文件
可以用“或”或者“+”把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打开文件。

例如:以二进制输入方式打开文件c:config.sys

fstream file1;
file1.open("c:config.sys",ios::binary|ios::in,0);

如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:

file1.open("c:config.sys");&lt;=&gt;file1.open("c:config.sys",ios::in|ios::out,0);

另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:

fstream file1("c:config.sys");

特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。

ifstream file2("c:pdos.def");//以输入方式打开文件
ofstream file3("c:x.123");//以输出方式打开文件

所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。

二、关闭文件
打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。

三、读写文件
读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式

1、文本文件的读写
文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:

file2&lt;&lt;"I Love You";//向文件写入字符串"I Love You"
int i;
file1&gt;&gt;i;//从文件输入一个整数值。

这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些

操纵符 功能 输入/输出
dec 格式化为十进制数值数据 输入和输出
endl 输出一个换行符并刷新此流 输出
ends 输出一个空字符 输出
hex 格式化为十六进制数值数据 输入和输出
oct 格式化为八进制数值数据 输入和输出
setpxecision(int p) 设置浮点数的精度位数 输出

比如要把123当作十六进制输出:file1<<hex<<123;要把3.1415926以5位精度输出:file1<<setpxecision(5)<<3.1415926。

2、二进制文件的读写
①put()
put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put(‘c’);就是向流写一个字符’c’。

②get()
get()函数比较灵活,有3种常用的重载形式:

一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。

另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。

还 有一种形式的原型是:ifstream &get(char *buf,int num,char delim=’n’);这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符’n’。例如:

file2.get(str1,127,’A’);//从文件中读取字符到字符串str1,当遇到字符’A’或读取了127个字符时终止。

③读写数据块
要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:

read(unsigned char *buf,int num);
write(const unsigned char *buf,int num);

read() 从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。

例:

unsigned char str1[]="I Love You";
int n[5];
ifstream in("xxx.xxx");
ofstream out("yyy.yyy");
out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数,注意类型转换
in.close();out.close();

四、检测EOF
成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();

例:

if(in.eof())ShowMessage("已经到达文件尾!");

五、文件定位
和 C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时, 相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是 seekg()和 seekp(),seekg()是设置读位置,seekp是设置写位置。它们最通用的形式如下:

istream &amp;seekg(streamoff offset,seek_dir origin);
ostream &amp;seekp(streamoff offset,seek_dir origin);

streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:

ios::beg: 文件开头
ios::cur: 文件当前位置
ios::end: 文件结尾
这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。

例:

file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节
file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节

pandasql: Make python speak SQL

Standard

http://blog.yhat.com/posts/pandasql-intro.html

Introduction

One of my favorite things about Python is that users get the benefit of observing the R community and then emulating the best parts of it. I’m a big believer that a language is only as helpful as its libraries and tools.

This post is about pandasql, a Python package we (Yhat) wrote that emulates the R package sqldf. It’s a small but mighty library comprised of just 358 lines of code. The idea of pandasql is to make Python speak SQL. For those of you who come from a SQL-first background or still “think in SQL”, pandasql is a nice way to take advantage of the strengths of both languages.

In this introduction, we’ll show you to get up and running with pandasql inside of Rodeo, the integrated development environment (IDE) we built for data exploration and analysis. Rodeo is an open source and completely free tool. If you’re an R user, its a comparable tool with a similar feel to RStudio. As of today, Rodeo can only run Python code, but last week we added syntax highlighting for a bunch of other languages to the editor (markdown, JSON, julia, SQL, markdown). As you may have read or guessed, we’ve got big plans for Rodeo, including adding SQL support so that you can run your SQL queries right inside of Rodeo, even without our handy little pandasql. More on that in the next week or two!

Downloading Rodeo

Start by downloading Rodeo for Mac, Windows or Linux from the Rodeo page on the Yhat website.

ps If you download Rodeo and encounter a problem or simply have a question, we monitor our discourse forum 24/7 (okay, almost).

A bit of background, if you’re curious

Behind the scenes, pandasql uses the pandas.io.sql module to transfer data between DataFrame and SQLite databases. Operations are performed in SQL, the results returned, and the database is then torn down. The library makes heavy use of pandas write_frame and frame_query, two functions which let you read and write to/from pandas and (most) any SQL database.

Install pandasql

Install pandasql using the package manager pane in Rodeo. Simply search for pandasql and click Install Package.

You can also run ! pip install pandasql from the text editor if you prefer to install that way.

Check out the datasets

pandasql has two built-in datasets which we’ll use for the examples below.

  • meat: Dataset from the U.S. Dept. of Agriculture containing metrics on livestock, dairy, and poultry outlook and production
  • births: Dataset from the United Nations Statistics Division containing demographic statistics on live births by month

Run the following code to check out the data sets.

<code>#Checking out meat and birth data
from pandasql import sqldf
from pandasql import load_meat, load_births

meat = load_meat()
births = load_births()

#You can inspect the dataframes directly if you're using Rodeo
#These print statements are here just in case you want to check out your data in the editor, too
print meat.head()
print births.head()
</code>

Inside Rodeo, you really don’t even need the print.variable.head() statements, since you can actually just examine the dataframes directly.

An odd graph

<code># Let's make a graph to visualize the data
# Bet you haven't had a title quite like this before
import matplotlib.pyplot as plt
from pandasql import *
import pandas as pd

pysqldf = lambda q: sqldf(q, globals())

q  = """
SELECT
  m.date
  , m.beef
  , b.births
FROM
  meat m
LEFT JOIN
  births b
    ON m.date = b.date
WHERE
    m.date &gt; '1974-12-31';
"""

meat = load_meat()
births = load_births()

df = pysqldf(q)
df.births = df.births.fillna(method='backfill')

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.rolling_mean(df['beef'], 12), color='b')
ax1.set_xlabel('months since 1975')
ax1.set_ylabel('cattle slaughtered', color='b')

ax2 = ax1.twinx()
ax2.plot(pd.rolling_mean(df['births'], 12), color='r')
ax2.set_ylabel('babies born', color='r')
plt.title("Beef Consumption and the Birth Rate")
plt.show()
</code>

Notice that the plot appears both in the console and the plot tab (bottom right tab).

Tip: You can “pop out” your plot by clicking the arrows at the top of the pane. This is handy if you’re working on multiple monitors and want to dedicate one just to your data visualzations.

Usage

To keep this post concise and easy to read, we’ve just given the code snippets and a few lines of results for most of the queries below.

If you’re following along in Rodeo, a few tips as you’re getting started:

  • Run Script will indeed run everything you have written in the text editor
  • You can highlight a code chunk and run it by clicking Run Line or pressing Command + Enter
  • You can resize the panes (when I’m not making plots I shrink down the bottom right pane)

Basics

Write some SQL and execute it against your pandas DataFrame by substituting DataFrames for tables.

<code>q = """
    SELECT
        *
    FROM
        meat
    LIMIT 10;"""

print sqldf(q, locals())

#                   date  beef  veal  pork  lamb_and_mutton broilers other_chicken turkey
# 0  1944-01-01 00:00:00   751    85  1280               89     None          None   None
# 1  1944-02-01 00:00:00   713    77  1169               72     None          None   None
# 2  1944-03-01 00:00:00   741    90  1128               75     None          None   None
# 3  1944-04-01 00:00:00   650    89   978               66     None          None   None
</code>

pandasql creates a DB, schema and all, loads your data, and runs your SQL.

Aggregation

pandasql supports aggregation. You can use aliased column names or column numbers in your group byclause.

<code># births per year
q = """
    SELECT
        strftime("%Y", date)
        , SUM(births)
    FROM births
    GROUP BY 1
    ORDER BY 1;
            """

print sqldf(q, locals())

#    strftime("%Y", date)  SUM(births)
# 0                  1975      3136965
# 1                  1976      6304156
# 2                  1979      3333279
# 3                  1982      3612258
</code>

locals() vs. globals()

pandasql needs to have access to other variables in your session/environment. You can pass locals() to pandasql when executing a SQL statement, but if you’re running a lot of queries that might be a pain. To avoid passing locals all the time, you can add this helper function to your script to set globals() like so:

<code>def pysqldf(q):
    return sqldf(q, globals())

q = """
    SELECT
        *
    FROM
        births
    LIMIT 10;"""

print pysqldf(q)
# 0  1975-01-01 00:00:00  265775
# 1  1975-02-01 00:00:00  241045
# 2  1975-03-01 00:00:00  268849
</code>

joins

You can join dataframes using normal SQL syntax.

<code># joining meats + births on date
q = """
    SELECT
        m.date
        , b.births
        , m.beef
    FROM
        meat m
    INNER JOIN
        births b
            on m.date = b.date
    ORDER BY
        m.date
    LIMIT 100;
    """

joined = pysqldf(q)
print joined.head()
#date  births    beef
#0  1975-01-01 00:00:00.000000  265775  2106.0
#1  1975-02-01 00:00:00.000000  241045  1845.0
#2  1975-03-01 00:00:00.000000  268849  1891.0
</code>

WHERE conditions

Here’s a WHERE clause.

<code>q = """
    SELECT
        date
        , beef
        , veal
        , pork
        , lamb_and_mutton
    FROM
        meat
    WHERE
        lamb_and_mutton &gt;= veal
    ORDER BY date DESC
    LIMIT 10;
    """

print pysqldf(q)
#                   date    beef  veal    pork  lamb_and_mutton
# 0  2012-11-01 00:00:00  2206.6  10.1  2078.7             12.4
# 1  2012-10-01 00:00:00  2343.7  10.3  2210.4             14.2
# 2  2012-09-01 00:00:00  2016.0   8.8  1911.0             12.5
# 3  2012-08-01 00:00:00  2367.5  10.1  1997.9             14.2
</code>

It’s just SQL

Since pandasql is powered by SQLite3, you can do most anything you can do in SQL. Here are some examples using common SQL features such as subqueries, order by, functions, and unions.

<code>#################################################
# SQL FUNCTIONS
# e.g. `RANDOM()`
#################################################
q = """SELECT
    *
    FROM
        meat
    ORDER BY RANDOM()
    LIMIT 10;"""
print pysqldf(q)
#                   date  beef  veal  pork  lamb_and_mutton  broilers other_chicken  turkey
# 0  1967-03-01 00:00:00  1693    65  1136               61     472.0          None    26.5
# 1  1944-12-01 00:00:00   764   146  1013               91       NaN          None     NaN
# 2  1969-06-01 00:00:00  1666    50   964               42     573.9          None    85.4
# 3  1983-03-01 00:00:00  1892    37  1303               36    1106.2          None   182.7

#################################################
# UNION ALL
#################################################
q = """
        SELECT
            date
            , 'beef' AS meat_type
            , beef AS value
        FROM meat
        UNION ALL
        SELECT
            date
            , 'veal' AS meat_type
            , veal AS value
        FROM meat

        UNION ALL

        SELECT
            date
            , 'pork' AS meat_type
            , pork AS value
        FROM meat
        UNION ALL
        SELECT
            date
            , 'lamb_and_mutton' AS meat_type
            , lamb_and_mutton AS value
        FROM meat
        ORDER BY 1
    """
print pysqldf(q).head(20)
#                    date        meat_type  value
# 0   1944-01-01 00:00:00             beef    751
# 1   1944-01-01 00:00:00             veal     85
# 2   1944-01-01 00:00:00             pork   1280
# 3   1944-01-01 00:00:00  lamb_and_mutton     89


#################################################
# subqueries
# fancy!
#################################################
q = """
    SELECT
        m1.date
        , m1.beef
    FROM
        meat m1
    WHERE m1.date IN
        (SELECT
            date
        FROM meat
        WHERE
            beef &gt;= broilers
        ORDER BY date)
"""

more_beef_than_broilers = pysqldf(q)
print more_beef_than_broilers.head(10)
#                   date  beef
# 0  1960-01-01 00:00:00  1196
# 1  1960-02-01 00:00:00  1089
# 2  1960-03-01 00:00:00  1201
# 3  1960-04-01 00:00:00  1066
</code>

Final thoughts

pandas is an incredible tool for data analysis in large part, we think, because it is extremely digestible, succinct, and expressive. Ultimately, there are tons of reasons to learn the nuances of mergejoinconcatenatemelt and other native pandas features for slicing and dicing data. Check out the docs for some examples.

Our hope is that pandasql will be a helpful learning tool for folks new to Python and pandas. In my own personal experience learning R, sqldf was a familiar interface helping me become highly productive with a new tool as quickly as possible.

关于python文件操作

Standard

python中对文件、文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块。

得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()

返回指定目录下的所有文件和目录名:os.listdir()

函数用来删除一个文件:os.remove()

删除多个目录:os.removedirs(r“c:\python”)

检验给出的路径是否是一个文件:os.path.isfile()

检验给出的路径是否是一个目录:os.path.isdir()

判断是否是绝对路径:os.path.isabs()

检验给出的路径是否真地存:os.path.exists()

返回一个路径的目录名和文件名:os.path.split()     eg os.path.split(‘/home/swaroop/byte/code/poem.txt’) 结果:(‘/home/swaroop/byte/code’, ‘poem.txt’)

分离扩展名:os.path.splitext()

获取路径名:os.path.dirname()

获取文件名:os.path.basename()

运行shell命令: os.system()

读取和设置环境变量:os.getenv() 与os.putenv()

给出当前平台使用的行终止符:os.linesep    Windows使用’\r\n’,Linux使用’\n’而Mac使用’\r’

指示你正在使用的平台:os.name       对于Windows,它是’nt’,而对于Linux/Unix用户,它是’posix’

重命名:os.rename(old, new)

创建多级目录:os.makedirs(r“c:\python\test”)

创建单个目录:os.mkdir(“test”)

获取文件属性:os.stat(file)

修改文件权限与时间戳:os.chmod(file)

终止当前进程:os.exit()

获取文件大小:os.path.getsize(filename)
文件操作:
os.mknod(“test.txt”)        创建空文件
fp = open(“test.txt”,w)     直接打开一个文件,如果文件不存在则创建文件

关于open 模式:

w     以写方式打开,
a     以追加模式打开 (从 EOF 开始, 必要时创建新文件)
r+     以读写模式打开
w+     以读写模式打开 (参见 w )
a+     以读写模式打开 (参见 a )
rb     以二进制读模式打开
wb     以二进制写模式打开 (参见 w )
ab     以二进制追加模式打开 (参见 a )
rb+    以二进制读写模式打开 (参见 r+ )
wb+    以二进制读写模式打开 (参见 w+ )
ab+    以二进制读写模式打开 (参见 a+ )

 

fp.read([size])                     #size为读取的长度,以byte为单位

fp.readline([size])                 #读一行,如果定义了size,有可能返回的只是一行的一部分

fp.readlines([size])                #把文件每一行作为一个list的一个成员,并返回这个list。其实它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。

fp.write(str)                      #把str写到文件中,write()并不会在str后加上一个换行符

fp.writelines(seq)            #把seq的内容全部写到文件中(多行一次性写入)。这个函数也只是忠实地写入,不会在每行后面加上任何东西。

fp.close()                        #关闭文件。python会在一个文件不用后自动关闭文件,不过这一功能没有保证,最好还是养成自己关闭的习惯。  如果一个文件在关闭后还对其进行操作会产生ValueError

fp.flush()                                      #把缓冲区的内容写入硬盘

fp.fileno()                                      #返回一个长整型的”文件标签“

fp.isatty()                                      #文件是否是一个终端设备文件(unix系统中的)

fp.tell()                                         #返回文件操作标记的当前位置,以文件的开头为原点

fp.next()                                       #返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。

fp.seek(offset[,whence])              #将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了,whence可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。

fp.truncate([size])                       #把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。如果size比文件的大小还要大,依据系统的不同可能是不改变文件,也可能是用0把文件补到相应的大小,也可能是以一些随机的内容加上去。

 

目录操作:
os.mkdir(“file”)                   创建目录
复制文件:
shutil.copyfile(“oldfile”,”newfile”)       oldfile和newfile都只能是文件
shutil.copy(“oldfile”,”newfile”)            oldfile只能是文件夹,newfile可以是文件,也可以是目标目录
复制文件夹:
shutil.copytree(“olddir”,”newdir”)        olddir和newdir都只能是目录,且newdir必须不存在
重命名文件(目录)
os.rename(“oldname”,”newname”)       文件或目录都是使用这条命令
移动文件(目录)
shutil.move(“oldpos”,”newpos”)   
删除文件
os.remove(“file”)
删除目录
os.rmdir(“dir”)只能删除空目录
shutil.rmtree(“dir”)    空目录、有内容的目录都可以删
转换目录
os.chdir(“path”)   换路径

 

相关例子 

 1 将文件夹下所有图片名称加上’_fc’

python代码:

# -*- coding:utf-8 -*-
import re
import os
import time
#str.split(string)分割字符串
#’连接符’.join(list) 将列表组成字符串
def change_name(path):
global i
if not os.path.isdir(path) and not os.path.isfile(path):
return False
if os.path.isfile(path):
file_path = os.path.split(path) #分割出目录与文件
lists = file_path[1].split(‘.’) #分割出文件与文件扩展名
file_ext = lists[-1] #取出后缀名(列表切片操作)
img_ext = [‘bmp’,’jpeg’,’gif’,’psd’,’png’,’jpg’]
if file_ext in img_ext:
os.rename(path,file_path[0]+’/’+lists[0]+’_fc.’+file_ext)
i+=1 #注意这里的i是一个陷阱
#或者
#img_ext = ‘bmp|jpeg|gif|psd|png|jpg’
#if file_ext in img_ext:
#    print(‘ok—‘+file_ext)
elif os.path.isdir(path):
for x in os.listdir(path):
change_name(os.path.join(path,x)) #os.path.join()在路径处理上很有用
img_dir = ‘D:\\xx\\xx\\images’
img_dir = img_dir.replace(‘\\’,’/’)
start = time.time()
i = 0
change_name(img_dir)
c = time.time() – start
print(‘程序运行耗时:%0.2f’%(c))
print(‘总共处理了 %s 张图片’%(i))

输出结果:

程序运行耗时:0.11
总共处理了 109 张图片

对ASP.NET程序员都非常有用的85个工具

Standard

介绍

这篇文章列出了针对ASP.NET开发人员的有用工具。

工具

1.Visual Studio

  1. Visual Studio Productivity Power tool:Visual Studio专业版(及以上)的扩展,具有丰富的功能,如快速查找,导航解决方案,可搜索的附加参考对话框等
  2. ReSharper:提高.NET开发人员生产力的工具,提高代码质量,通过提供快速修复消除错误,等等
  3. MZ-Tools:它可以在方法、文件、项目、解决方案或项目组、选定的文本,文件组合或项目组合中找到字符串。结果示于下面的结果窗口中,比由Microsoft IDE提供的要更方便。
  4. Web Essentials:提高生产力和帮助高效编写CSS,JavaScript,HTML等
  5. MSVSMON:远程调试监视器(msvsmon.exe)是一个Visual Studio连接进行远程调试的小型应用程序。在远程调试时,Visual Studio运行在一台计算机(调试器主机)上,远程调试监视器运行与你正在调试的应用程序运行在一台远程计算机上。
  6. WIX toolset:从XML源代码构建Windows安装程序包。
  7. Code digger::Code Digger是Visual Studio 2012/2013扩展程序,它可以帮助你了解你的代码行为。
  8. CodeMaid:CodeMaid是一个开源的Visual Studio 2012/2013/2015扩展程序,用于清理,挖掘和简化你的代码。
  9. OzCode:强大的Visual Studio调试器可视化工具。
  10. CodeRush:这是一个Visual Studio的重构和生产率插件。
  11. T4 Text Template::在Visual Studio中,T4 Text Template用作生成代码文件的模板。模板可以通过编写文本块和控制逻辑来定义。
  12. Indent Guides:在每个缩进级别添加垂直线。
  13. PowerShell Tools:一套用于开发和调试PowerShell脚本以及Visual Studio 2015中模块的工具。
  14. Visual Studio Code:免费的跨平台编辑器,用来构建和调试现代web和云的应用程序。 [由Cheung Tat Ming提供]
  15. AutoPoco:AutoPoco是一个高度可配置的框架,用于流畅构建可读的来自于Plain Old CLRObjects的测试数据。
  16. Supercharger:这是一个旨在显著改善Visual Studio开发体验的扩展程序。它建立在并增强了先前的VS10x产品,如CodeMAP、Editor View Enhancer、Comments Extender,同时还增加了新的高品质工具。

2.ASP.NET

  1. Fiddler:捕捉HTTP请求/响应以及模拟请求行为。
  2. AutoMapper:对象到对象的映射。例如,该工具可用于映射实体对象到领域对象,而不是写手动映射代码。
  3. Unity/Ninject/Castle Windsor/StructureMap/Spring.Net:依赖注入框架。有很多可用的DI框架。
  4. .NET Reflector:.NET程序集反编译器。
  5. dotPeek:.NET程序集反编译器。
  6. ILSpy::.NET程序集反编译器。
  7. memprofiler:查找内存泄漏并优化内存使用的强大工具。
  8. PostSharp:删除重复编码,并防止由于横切关注点以及面向方面编程而造成的代码膨胀。
  9. ASPhere:有GUI的web.config编辑器。

3.REST API

  1. Swagger UI:API测试和文档工具。[视频]
  2. PostMan:REST客户端Chrom扩展程序。 [由 Cheung Tat Ming提供]

4.WCF

  1. SOAP UI:API测试工具,支持所有标准协议和技术。
  2. WireShark:这是一个针对Unix和Windows的网络协议分析仪。它可以在TCP层捕获流量,帮助你发现soap封套。
  3. Svc TraceViewer:可以更好地查看由WCF产出的巨大跟踪文件。
  4. Svc Config Editor:用于管理WCF相关配置的GUI工具。

5.MSMQ

  1. QueueExplorer 3.4:复制,移动或删除邮件,保存和加载,压力测试,查看和编辑完整的邮件主体(通过.NET序列化对象的特殊支持),以及更多可对MSMQ做的。

6.LINQ

  1. LINQ Pad?:LINQPad是一个轻量级的工具,用于测试对SQL Server数据库的LINQ查询。它也可以测试用不同的.NET语言,如C#,VB等写的代码片断。
  2. LINQ Insight:LINQ Insight Express是一个Visual Studio插件,它允许你在设计时分析你的LINQ查询,并简化了编写和调试LINQ查询。

7.RegEx

  1. RegEx tester:用于正则表达式测试的Visual Studio扩展程序。
  2. regexr:在线RegEx开发和测试工具。
  3. regexpal:在线RegEx开发和测试工具。
  4. Expresso:Expresso是一个用于RegEx开发和测试的桌面工具。
  5. RegexMagic :用于自动生成来自于文本模式的正则表达式的工具。用户需要通过标记字串和选择不同的选项来培养模式。在此基础上,将自动生成正则表达式。这些工具还可以生成不同语言所需的代码。 [由: Samuel Christison提供]

8.Javascript / JQuery/ AngularJS

  1. JSHint:JavaScript代码质量的工具。还有一个工具,JSLine,它执行更严格的规则。
  2. JSFiddle:提供在浏览器中的一个环境,用来测试HTML,CSS和Javascript / JQuery。
  3. Protractor:端到端的框架用来测试angular应用程序。
  4. Batarang:添加工具用于调试和分析AngularJS应用程序。

9.SQL服务器

  1. SQL Profiler:SQL跟踪用来监测数据库引擎实例。
  2. ExpressProfiler:ExpressProfiler(又名SqlExpress Profiler)是有着基本GUI和集成的SQL Server Profiler简单又快捷的替代品。这可以与Express 和SQL Server 2005/2008 / 2008R2 / 2012/2014的non-Express 版本一起使用。 [由RickZeeland提供]
  3. SQL Sentry Plan explorer:工具提供SQL查询执行计划更好的图形视图。
  4. SQL Complete:提供SQL Server Management Studio和Visual Studio智能感知功能和改进的SQL格式器。
  5. NimbleText:文本操作和代码生成工具。
  6. Query Express:轻量级SQL查询分析器。
  7. IO Meter:提供IO子系统的细节。
  8. sqldecryptor:破译SQL Server对象,如存储过程,函数,触发器,视图,通过加密选项加密。
  9. SpatialViewer:查看和创建空间数据。
  10. ClearTrace:导入跟踪和探查文件到SQL Server并显示汇总性能信息。
  11. Internals Viewer for SQL Server:Internals Viewer是一个查看SQL Server存储引擎,查阅数据如何物理分配,组织和存储的工具。
  12. PAL:在性能日志读取,使用已知阈值分析。
  13. sqlquerystress:用T-SQL查询和程序的性能压力测试助攻。

10.NHibernate

  1. NHibernate Mapping Generator:生成NHibernate映射文件和对应于现有DB表的实体类。

11.Tally

  1. Tally ERP 9
  2. Tally dll:.NET的一个动态链接库,用于集成Tally Accounting软件以便于用编程的方式push和pull数据。

12.代码审查

  1. StyleCop:StyleCop是静态的代码分析工具,它强制你的C#源代码执行配置风格和一致性规则设置。它可以从Visual Studio内部运行或集成到MSBuild项目。
  2. FxCop?:FxCop是一个静态代码分析工具,它通过分析.NET程序集强制开发标准。

13.流量捕获

  1. WireShark:这是一个用于Unix和Windows的网络协议分析仪。它可以捕获TCP层的流量。
  2. HTTP Monitor:使开发人员可以查看你的计算机和互联网之间的所有HTTP流量。这包括请求数据(例如HTTP响应头和表单GET和POST数据)和响应数据(包括HTTP响应头和正文)。

14.诊断

  1. Glimpse:提供服务器端诊断数据。如,对于ASP.NET MVC项目,你需要从NuGet添加它。Glimpse的数据可以告诉你不同层面的延迟,真正表明你可以优化代码/解决方案以提高性能的区域。

15.性能

  1. PerfMon:使用性能计数器监控系统性能。
  2. yslow:YSlow分析web页面,并基于Yahoo!高性能网站的规则指出它们为什么这么缓慢。

16.代码转换器

  1. Telerik Code Converter:C#到VB以及VB到C#的代码转换器。这是一个在线编辑器。但是你可以选择“批量转换”以及zip格式上传文件。

17.数据提取和加载

  1. FileHelpers:.NET库,导入/导出文件、字符串或流中固定长度或有分隔记录的数据。
  2. LogParser:你可以写SQL到查询来应对各种日志文件,以及导出数据到各种目的地,如SQL表、CSV文件。

18.屏幕录制

  1. Wink:演示文稿制作软件。使用Wink,你可以捕捉截图,添加说明,注释等,以及创建演示。

19.文本编辑器

  1. Notepad++:源代码编辑器。
  2. Notepad2:轻量级又功能丰富的记事本般的文本编辑器。
  3. sublimetext:一个功能丰富的文本编辑器。

20.文档

  1. GhostDoc:GhostDoc是一个Visual Studio扩展程序,自动生成类型、参数、名称及其他相关信息方法和属性的XML文档注释。
  2. helpndoc:helpndoc是一个创建帮助文件的工具。它可以从单个源生成不同格式的文件。

21.其他

  1. FileZilla:FileZilla是一个免费的FTP解决方案。FileZilla Client用于FTP文件上传,FileZilla Server用于文件共享。
  2. TreeTrim:TreeTrim是用于修整源代码树的工具。它消除了调试文件,源代码控制绑定和临时文件。
  3. BrowserStack:跨浏览器测试网站。
  4. Firebug:功能丰富的针对于CSS,HTML和JavaScript开发关于生成网页的Firefox插件。
  5. BugShooting:屏幕截图软件,截屏并放到工作项,bug,问题跟踪项等。
  6. Web developer checklist:确保web开发最佳实践。
  7. XRAY:Firefox插件。功能丰富的书签。提供有关网页元素的信息。
  8. PowerGUI:有助于快速接纳和使用PowerShell来高效管理完整的Windows环境。
  9. Beyond Compare:它允许比较目录树和单个文件的内容。适应强,有流行语言的插件。 [由Ron Matuszek提供]
  10. Devart Codecompare:文件diff工具,读取C#,C ++,VB代码的结构。包括:文件夹比较工具,比较和合并文件和文件夹的独立app,代码审查支持。 [由Cheung Tat Ming提供]

警告

使用之前请验证工具。

许可证

这篇文章以及任何相关的源代码和文件,遵循 The Code Project Open License (CPOL)。

 

译文链接:http://www.codeceo.com/article/85-aspnet-tools.html
英文原文:Useful Tools for ASP.NET Developers

知道这20个正则表达式,能让你少写1,000行代码

Standard

知道这20个正则表达式,能让你少写1,000行代码

正则表达式,一个十分古老而又强大的文本处理工具,仅仅用一段非常简短的表达式语句,便能够快速实现一个非常复杂的业务逻辑。熟练地掌握正则表达式的话,能够使你的开发效率得到极大的提升。

正则表达式经常被用于字段或任意字符串的校验,如下面这段校验基本日期格式的JavaScript代码:

<code class="scala"><span class="hljs-keyword">var</span> reg = /^(\\d{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>})(-|\\/)(\\d{<span class="hljs-number">1</span>,<span class="hljs-number">2</span>})\\<span class="hljs-number">2</span>(\\d{<span class="hljs-number">1</span>,<span class="hljs-number">2</span>})$/; 
<span class="hljs-keyword">var</span> r = fieldValue.<span class="hljs-keyword">match</span>(reg);             
<span class="hljs-keyword">if</span>(r==<span class="hljs-literal">null</span>)alert(<span class="hljs-symbol">'Date</span> format error!');</code>

下面是技匠整理的,在前端开发中经常使用到的20个正则表达式。


1 . 校验密码强度

密码的强度必须是包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间。

<code class="cpp">^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{<span class="hljs-number">8</span>,<span class="hljs-number">10</span>}$</code>

2. 校验中文

字符串仅能是中文。

<code class="tex">^<span class="hljs-special">[</span><span class="hljs-command">\\</span>u4e00-<span class="hljs-command">\\</span>u9fa5<span class="hljs-special">]</span><span class="hljs-special">{</span>0,<span class="hljs-special">}</span><span class="hljs-formula">$</span></code>

3. 由数字、26个英文字母或下划线组成的字符串

<code class="tex">^<span class="hljs-command">\\</span>w+<span class="hljs-formula">$</span></code>

4. 校验E-Mail 地址

同密码一样,下面是E-mail地址合规性的正则检查语句。

<code class="markdown">[<span class="hljs-link_label">\\w!#$%&amp;'*+/=?^_`{|}~-</span>]+(?:\\.[<span class="hljs-link_label">\\w!#$%&amp;'*+/=?^_`{|}~-</span>]+)<span class="hljs-emphasis">*@(?:[\\w](?:[\\w-]*</span>[<span class="hljs-link_label">\\w</span>])?\\.)+[<span class="hljs-link_label">\\w</span>](<span class="hljs-link_url">?:[\\w-]*[\\w]</span>)?</code>

5. 校验身份证号码

下面是身份证号码的正则校验。15 或 18位。

15位:

<code class="cpp">^[<span class="hljs-number">1</span>-<span class="hljs-number">9</span>]\\d{<span class="hljs-number">7</span>}((<span class="hljs-number">0</span>\\d)|(<span class="hljs-number">1</span>[<span class="hljs-number">0</span>-<span class="hljs-number">2</span>]))(([<span class="hljs-number">0</span>|<span class="hljs-number">1</span>|<span class="hljs-number">2</span>]\\d)|<span class="hljs-number">3</span>[<span class="hljs-number">0</span>-<span class="hljs-number">1</span>])\\d{<span class="hljs-number">3</span>}$</code>

18位:

<code class="cpp">^[<span class="hljs-number">1</span>-<span class="hljs-number">9</span>]\\d{<span class="hljs-number">5</span>}[<span class="hljs-number">1</span>-<span class="hljs-number">9</span>]\\d{<span class="hljs-number">3</span>}((<span class="hljs-number">0</span>\\d)|(<span class="hljs-number">1</span>[<span class="hljs-number">0</span>-<span class="hljs-number">2</span>]))(([<span class="hljs-number">0</span>|<span class="hljs-number">1</span>|<span class="hljs-number">2</span>]\\d)|<span class="hljs-number">3</span>[<span class="hljs-number">0</span>-<span class="hljs-number">1</span>])\\d{<span class="hljs-number">3</span>}([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]|X)$</code>

6. 校验日期

“yyyy-mm-dd“ 格式的日期校验,已考虑平闰年。

<code class="markdown">^(?:(?!0000)[<span class="hljs-link_label">0-9</span>]{4}-(?:(?:0[<span class="hljs-link_label">1-9</span>]|1[<span class="hljs-link_label">0-2</span>])-(?:0[<span class="hljs-link_label">1-9</span>]|1[<span class="hljs-link_label">0-9</span>]|2[<span class="hljs-link_label">0-8</span>])|(?:0[<span class="hljs-link_label">13-9</span>]|1[<span class="hljs-link_label">0-2</span>])-(?:29|30)|(?:0[<span class="hljs-link_label">13578</span>]|1[<span class="hljs-link_label">02</span>])-31)|(?:[<span class="hljs-link_label">0-9</span>]{2}(?:0[<span class="hljs-link_label">48</span>]|[<span class="hljs-link_label">2468</span>][<span class="hljs-link_reference">048</span>]|[<span class="hljs-link_label">13579</span>][<span class="hljs-link_reference">26</span>])|(?:0[<span class="hljs-link_label">48</span>]|[<span class="hljs-link_label">2468</span>][<span class="hljs-link_reference">048</span>]|[<span class="hljs-link_label">13579</span>][<span class="hljs-link_reference">26</span>])00)-02-29)$</code>

7. 校验金额

金额校验,精确到2位小数。

<code class="cpp">^[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]+(.[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]{<span class="hljs-number">2</span>})?$</code>

8. 校验手机号

下面是国内 13、15、18开头的手机号正则表达式。(可根据目前国内收集号扩展前两位开头号码)

<code class="cpp">^(<span class="hljs-number">13</span>[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]|<span class="hljs-number">14</span>[<span class="hljs-number">5</span>|<span class="hljs-number">7</span>]|<span class="hljs-number">15</span>[<span class="hljs-number">0</span>|<span class="hljs-number">1</span>|<span class="hljs-number">2</span>|<span class="hljs-number">3</span>|<span class="hljs-number">5</span>|<span class="hljs-number">6</span>|<span class="hljs-number">7</span>|<span class="hljs-number">8</span>|<span class="hljs-number">9</span>]|<span class="hljs-number">18</span>[<span class="hljs-number">0</span>|<span class="hljs-number">1</span>|<span class="hljs-number">2</span>|<span class="hljs-number">3</span>|<span class="hljs-number">5</span>|<span class="hljs-number">6</span>|<span class="hljs-number">7</span>|<span class="hljs-number">8</span>|<span class="hljs-number">9</span>])\\d{<span class="hljs-number">8</span>}$</code>

9. 判断IE的版本

IE目前还没被完全取代,很多页面还是需要做版本兼容,下面是IE版本检查的表达式。

<code class="cpp">^.*MSIE [<span class="hljs-number">5</span>-<span class="hljs-number">8</span>](?:\\.[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]+)?(?!.*Trident\\/[<span class="hljs-number">5</span>-<span class="hljs-number">9</span>]\\<span class="hljs-number">.0</span>).*$</code>

10. 校验IP-v4地址

IP4 正则语句。

<code class="markdown">\\b(?:(?:25[<span class="hljs-link_label">0-5</span>]|2[<span class="hljs-link_label">0-4</span>][<span class="hljs-link_reference">0-9</span>]|[<span class="hljs-link_label">01</span>]?[<span class="hljs-link_label">0-9</span>][<span class="hljs-link_reference">0-9</span>]?)\\.){3}(?:25[<span class="hljs-link_label">0-5</span>]|2[<span class="hljs-link_label">0-4</span>][<span class="hljs-link_reference">0-9</span>]|[<span class="hljs-link_label">01</span>]?[<span class="hljs-link_label">0-9</span>][<span class="hljs-link_reference">0-9</span>]?)\\b</code>

11. 校验IP-v6地址

IP6 正则语句。

<code class="cpp">(([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">7</span>,<span class="hljs-number">7</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">7</span>}:|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">6</span>}:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">5</span>}(:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">2</span>}|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}(:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">3</span>}|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">3</span>}(:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">2</span>}(:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">5</span>}|[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:((:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">6</span>})|:((:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">1</span>,<span class="hljs-number">7</span>}|:)|fe80:(:[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">0</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">0</span>,<span class="hljs-number">4</span>}%[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-zA-Z]{<span class="hljs-number">1</span>,}|::(ffff(:<span class="hljs-number">0</span>{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}:){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}((<span class="hljs-number">25</span>[<span class="hljs-number">0</span>-<span class="hljs-number">5</span>]|(<span class="hljs-number">2</span>[<span class="hljs-number">0</span>-<span class="hljs-number">4</span>]|<span class="hljs-number">1</span>{<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>])\\.){<span class="hljs-number">3</span>,<span class="hljs-number">3</span>}(<span class="hljs-number">25</span>[<span class="hljs-number">0</span>-<span class="hljs-number">5</span>]|(<span class="hljs-number">2</span>[<span class="hljs-number">0</span>-<span class="hljs-number">4</span>]|<span class="hljs-number">1</span>{<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>])|([<span class="hljs-number">0</span>-<span class="hljs-number">9</span>a-fA-F]{<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:){<span class="hljs-number">1</span>,<span class="hljs-number">4</span>}:((<span class="hljs-number">25</span>[<span class="hljs-number">0</span>-<span class="hljs-number">5</span>]|(<span class="hljs-number">2</span>[<span class="hljs-number">0</span>-<span class="hljs-number">4</span>]|<span class="hljs-number">1</span>{<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>])\\.){<span class="hljs-number">3</span>,<span class="hljs-number">3</span>}(<span class="hljs-number">25</span>[<span class="hljs-number">0</span>-<span class="hljs-number">5</span>]|(<span class="hljs-number">2</span>[<span class="hljs-number">0</span>-<span class="hljs-number">4</span>]|<span class="hljs-number">1</span>{<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]){<span class="hljs-number">0</span>,<span class="hljs-number">1</span>}[<span class="hljs-number">0</span>-<span class="hljs-number">9</span>]))</code>

12. 检查URL的前缀

应用开发中很多时候需要区分请求是HTTPS还是HTTP,通过下面的表达式可以取出一个url的前缀然后再逻辑判断。

<code class="scala"><span class="hljs-keyword">if</span> (!s.<span class="hljs-keyword">match</span>(/^[a-zA-<span class="hljs-type">Z</span>]+:\\/\\<span class="hljs-comment">//))</span>
{
    s = <span class="hljs-symbol">'http</span>:<span class="hljs-comment">//' + s;</span>
}</code>

13. 提取URL链接

下面的这个表达式可以筛选出一段文本中的URL。

<code class="tex">^(f|ht)<span class="hljs-special">{</span>1<span class="hljs-special">}</span>(tp|tps):<span class="hljs-command">\\</span>/<span class="hljs-command">\\</span>/(<span class="hljs-special">[</span><span class="hljs-command">\\</span>w-<span class="hljs-special">]</span>+<span class="hljs-command">\\</span>.)+<span class="hljs-special">[</span><span class="hljs-command">\\</span>w-<span class="hljs-special">]</span>+(<span class="hljs-command">\\</span>/<span class="hljs-special">[</span><span class="hljs-command">\\</span>w- ./?<span class="hljs-comment">%&amp;=]*)?</span></code>

14. 文件路径及扩展名校验

验证windows下文件路径和扩展名(下面的例子中为.txt文件)

<code class="tex">^(<span class="hljs-special">[</span>a-zA-Z<span class="hljs-special">]</span><span class="hljs-command">\\</span>:|<span class="hljs-command">\\</span><span class="hljs-command">\\</span>)<span class="hljs-command">\\</span><span class="hljs-command">\\</span>(<span class="hljs-special">[</span>^<span class="hljs-command">\\</span><span class="hljs-command">\\</span><span class="hljs-special">]</span>+<span class="hljs-command">\\</span><span class="hljs-command">\\</span>)*<span class="hljs-special">[</span>^<span class="hljs-command">\\</span>/:*?"&lt;&gt;|<span class="hljs-special">]</span>+<span class="hljs-command">\\</span>.txt(l)?<span class="hljs-formula">$</span></code>

15. 提取Color Hex Codes

有时需要抽取网页中的颜色代码,可以使用下面的表达式。

<code class="cpp">^<span class="hljs-preprocessor">#([A-Fa-f0-<span class="hljs-number">9</span>]{<span class="hljs-number">6</span>}|[A-Fa-f0-<span class="hljs-number">9</span>]{<span class="hljs-number">3</span>})$</span></code>

16. 提取网页图片

假若你想提取网页中所有图片信息,可以利用下面的表达式。

<code class="tex"><span class="hljs-command">\\</span>&lt; *<span class="hljs-special">[</span>img<span class="hljs-special">]</span><span class="hljs-special">[</span>^<span class="hljs-command">\\</span><span class="hljs-command">\\</span>&gt;<span class="hljs-special">]</span>*<span class="hljs-special">[</span>src<span class="hljs-special">]</span> *= *<span class="hljs-special">[</span><span class="hljs-command">\\</span>"<span class="hljs-command">\\</span>'<span class="hljs-special">]</span><span class="hljs-special">{</span>0,1<span class="hljs-special">}</span>(<span class="hljs-special">[</span>^<span class="hljs-command">\\</span>"<span class="hljs-command">\\</span>'<span class="hljs-command">\\</span> &gt;<span class="hljs-special">]</span>*)</code>

17. 提取页面超链接

提取html中的超链接。

<code class="tex">(&lt;a<span class="hljs-command">\\</span>s*(?!.*<span class="hljs-command">\\</span>brel=)<span class="hljs-special">[</span>^&gt;<span class="hljs-special">]</span>*)(href="https?:<span class="hljs-command">\\</span>/<span class="hljs-command">\\</span>/)((?!(?:(?:www<span class="hljs-command">\\</span>.)?'.implode('|(?:www<span class="hljs-command">\\</span>.)?', <span class="hljs-formula">$follow_list).'))<span class="hljs-special">[</span>^"<span class="hljs-special">]</span>+)"((?!.*<span class="hljs-command">\\</span>brel=)<span class="hljs-special">[</span>^&gt;<span class="hljs-special">]</span>*)(?:<span class="hljs-special">[</span>^&gt;<span class="hljs-special">]</span>*)&gt;</span></code>

18. 查找CSS属性

通过下面的表达式,可以搜索到相匹配的CSS属性。

<code class="tex">^<span class="hljs-command">\\</span>s*<span class="hljs-special">[</span>a-zA-Z<span class="hljs-command">\\</span>-<span class="hljs-special">]</span>+<span class="hljs-command">\\</span>s*<span class="hljs-special">[</span>:<span class="hljs-special">]</span><span class="hljs-special">{</span>1<span class="hljs-special">}</span><span class="hljs-command">\\</span>s<span class="hljs-special">[</span>a-zA-Z0-9<span class="hljs-command">\\</span>s.<span class="hljs-special">#</span><span class="hljs-special">]</span>+<span class="hljs-special">[</span>;<span class="hljs-special">]</span><span class="hljs-special">{</span>1<span class="hljs-special">}</span></code>

19. 抽取注释

如果你需要移除HMTL中的注释,可以使用如下的表达式。

<code class="xml"><span class="hljs-comment">&lt;!--(.*?)--&gt;</span></code>

20. 匹配HTML标签

通过下面的表达式可以匹配出HTML中的标签属性。

<code class="tex">&lt;<span class="hljs-command">\\</span>/?<span class="hljs-command">\\</span>w+((<span class="hljs-command">\\</span>s+<span class="hljs-command">\\</span>w+(<span class="hljs-command">\\</span>s*=<span class="hljs-command">\\</span>s*(?:".*?"|'.*?'|<span class="hljs-special">[</span><span class="hljs-command">\\</span>^'"&gt;<span class="hljs-command">\\</span>s<span class="hljs-special">]</span>+))?)+<span class="hljs-command">\\</span>s*|<span class="hljs-command">\\</span>s*)<span class="hljs-command">\\</span>/?&gt;</code>

正则表达式的相关语法

下面是我找到的一张非常不错的正则表达式 Cheat Sheet,可以用来快速查找相关语法。


学习正则表达式

我在网上看到了一篇相当不错的正则表达式快速学习指南,有兴趣继续深入学习的同学可以参考。


正则表达式在线测试工具

regex101是一个非常不错的正则表达式在线测试工具,你可以直接在线测试你的正则表达式哦。


转:http://www.jianshu.com/p/e7bb97218946

10个惊艳的Swift单行代码

Standard

http://www.codeceo.com/article/10-swift-oneline-code.html

1 数组中的每个元素乘以2

特别简单,尤其是使用map解决的话。

(1...1024).map{$0 * 2}

2 数组中的元素求和

虽然这里使用reduce和加号运算符,借助了加号运算符是函数这样一个事实,但解决办法是显而易见的,我们可以看到 reduce更具创意的用法。

(1...1024).reduce(0,combine: +)

3 验证在字符串中是否存在指定单词

让我们使用 filter来验证tweet中是否包含选定的若干关键字中的一个:

let words = ["Swift","iOS","cocoa","OSX","tvOS"]
let tweet = "This is an example tweet larking about Swift"

let valid = !words.filter({tweet.containsString($0)}).isEmpty
valid //true

更新:@oisdk提出一些更好的选择:

words.contains(tweet.containsString)

方式更简洁,还有这一个:

tweet.characters
  .split(" ")
  .lazy
  .map(String.init)
  .contains(Set(words).contains)

4 读取文件

像其他语言一样,通过简单的内置来读取文件到数组中是不可能,但我们可以结合使用 split 和 map创造一些不需要for循环的简短代码:

let path = NSBundle.mainBundle().pathForResource("test", ofType: "txt")

let lines = try? String(contentsOfFile: path!).characters.split{$0 == "\n"}.map(String.init)
if let lines=lines {
    lines[0] // O! for a Muse of fire, that would ascend
    lines[1] // The brightest heaven of invention!
    lines[2] // A kingdom for a stage, princes to act
    lines[3] // And monarchs to behold the swelling scene.
}

map和字符串构造函数的最后一步把我们的数组字符转换为字符串。

5 祝你生日快乐!

这将显示生日快乐歌到控制台,通过map以及范围和三元运算符的简单使用。

let name = "uraimo"
(1...4).forEach{print("Happy Birthday " + (($0 == 3) ? "dear \(name)":"to You"))}

6 过滤数组中的数字

在这种情况下,我们需要使用提供的过滤函数分区一个序列。许多语言除了拥有常用的map、flatMap、reduce、filter等,还有正好能做这件事的 partitionBy 函数,Swift如你所知没有类似的东西(NSPredicate提供的可以过滤的NSArray函数在这里不是我们所需要的)。

因此,我们可以用 partitionBy 函数扩展 SequenceType 来解决这个问题,我们将使用 partitionBy 函数来分区整型数组:

extension SequenceType{
    typealias Element = Self.Generator.Element

    func partitionBy(fu: (Element)-&gt;Bool)-&gt;([Element],[Element]){
        var first=[Element]()
        var second=[Element]()
        for el in self {
            if fu(el) {
                first.append(el)
            }else{
                second.append(el)
            }
        }
        return (first,second)
    }
}

let part = [82, 58, 76, 49, 88, 90].partitionBy{$0 &lt; 60}
part // ([58, 49], [82, 76, 88, 90])

不是真正的单行代码。那么,我们是否可以使用过滤器来改善它?

extension SequenceType{

    func anotherPartitionBy(fu: (Self.Generator.Element)-&gt;Bool)-&gt;([Self.Generator.Element],[Self.Generator.Element]){
        return (self.filter(fu),self.filter({!fu($0)}))
    }
}

let part2 = [82, 58, 76, 49, 88, 90].anotherPartitionBy{$0 &lt; 60}
part2 // ([58, 49], [82, 76, 88, 90])

稍微好了一点,但它遍历了序列两次,并且试图把它变成单行代码删除闭包功能将会导致太多重复的东西(过滤函数和数组会在两个地方使用)。

我们是否使用单个数据流建立一些能够将初始序列转换为分区元组的东西?是的,我们可以用 reduce

var part3 = [82, 58, 76, 49, 88, 90].reduce( ([],[]), combine: {
	(a:([Int],[Int]),n:Int) -&gt; ([Int],[Int]) in
	(n&lt;60) ? (a.0+[n],a.1) : (a.0,a.1+[n]) 
})
part3 // ([58, 49], [82, 76, 88, 90])

我们在这里构建了包含两个分区的结果元组,一次一个元素,使用过滤函数测试初始序列中的每个元素,并根据过滤结果追加该元素到第一或第二分区数组中。

最后得到真正的单行代码,但要注意这样一个事实,即分区数组通过追加被构建,实际上会使其比前两个实施方式要慢。

7 获取并解析XML Web服务

上面的有些语言不依赖外部库,并默认提供多个选项来处理XML(例如Scala虽然笨拙但“本地”地支持XML解析成对象),但Foundation只提供了SAX解析器NSXMLParser,并且正如你可能已经猜到的那样,我们不打算使用它。

有几个替代的开源库,我们可以在这种情况下使用,其中一些用C或Objective-C编写,其他为纯Swift。

这次,我们打算使用纯Swift的AEXML:

let xmlDoc = try? AEXMLDocument(xmlData: NSData(contentsOfURL: NSURL(string:"https://www.ibiblio.org/xml/examples/shakespeare/hen_v.xml")!)!)

if let xmlDoc=xmlDoc {
    var prologue = xmlDoc.root.children[6]["PROLOGUE"]["SPEECH"]
    prologue.children[1].stringValue // Now all the youth of England are on fire,
    prologue.children[2].stringValue // And silken dalliance in the wardrobe lies:
    prologue.children[3].stringValue // Now thrive the armourers, and honour's thought
    prologue.children[4].stringValue // Reigns solely in the breast of every man:
    prologue.children[5].stringValue // They sell the pasture now to buy the horse,
}

8 在数组中查找最小(或最大)值

我们有各种方法来找到序列中的最小和最大值,其中有 minElement 和maxElement 函数:

//Find the minimum of an array of Ints
[10,-22,753,55,137,-1,-279,1034,77].sort().first
[10,-22,753,55,137,-1,-279,1034,77].reduce(Int.max, combine: min)
[10,-22,753,55,137,-1,-279,1034,77].minElement()

//Find the maximum of an array of Ints
[10,-22,753,55,137,-1,-279,1034,77].sort().last
[10,-22,753,55,137,-1,-279,1034,77].reduce(Int.min, combine: max)
[10,-22,753,55,137,-1,-279,1034,77].maxElement()

9 并行处理

某些语言允许用一种简单和透明的方式启用数组对功能,例如map和flatMap的并行处理,以加快顺序和独立操作的执行。

此功能Swift中还不可用,但可以使用GCD构建:http://moreindirection.blogspot.it/2015/07/gcd-and-parallel-collections-in-swift.html

10 埃拉托斯特尼筛法

埃拉托斯特尼筛法用于查找所有的素数直到给定的上限n。

从小于n的所有整数序列开始,算法删除所有整数的倍数,直到只剩下素数。并且为了加快执行速度,我们实际上并不需要检查每个整数的倍数,我们止步于n的平方根就可以了。

根据这一定义首次执行可能是这样的:

var n = 50
var primes = Set(2...n)

(2...Int(sqrt(Double(n)))).forEach{primes.subtractInPlace((2*$0).stride(through:n, by:$0))}
primes.sort()

我们使用外部范围来迭代我们要检查的整数,并且对于每一个整数我们使用 stride(through:Int by:Int)计算出数字的倍数的序列。那些序列然后从Set中减去,Set用所有从2到n的整数初始化。

但正如你所看到的,为了实际移除倍数,我们使用外部可变Set,导致了附带后果。

为了消除附带后果,正如我们通常应该做的那样,我们会先计算所有序列,用倍数的单一数组来flatMap它们,并从初始Set中删除这些整数。

var sameprimes = Set(2...n)

sameprimes.subtractInPlace((2...Int(sqrt(Double(n))))
						   .flatMap{ (2*$0).stride(through:n, by:$0)})
sameprimes.sort()

方式更清洁,使用flatMap的一个很好的例子以生成扁平化的嵌套数组。

11其他:通过解构元组交换

最后一点,并非每个人都知道的是,和其他有tuple类型的语言一样,元组可以用来执行紧凑的变量交换:

var a=1,b=2

(a,b) = (b,a)
a //2
b //1

好了,正如所料,Swift和其他语言一样富有表现力。

JavaScript 10分钟入门

Standard

以下为译文,原文地址:http://www.codeproject.com/Articles/1006192/JavaScript-Summary


简介

JavaScript是一门面向对象的动态语言,他一般用来处理以下任务:

  1. 修饰网页
    • 生成HTML和CSS
    • 生成动态HTML内容
    • 生成一些特效
  2. 提供用户交互接口
    • 生成用户交互组件
    • 验证用户输入
    • 自动填充表单
  3. 能够读取本地或者远程数据的前端应用程序,例如http://web-engineering.info/JsFrontendApp-Book
  4. 通过Nodejs实现像JAVA,C#,C++一样的服务端程序
  5. 实现分布式WEB程序,包括前端和服务端

当前浏览器所支持的JavaScript的版本被称为“ECMAScript的5.1”,或简单的“ES5”,但接下来的两个版本,称为“ES6”和“ES7”(或“ES2015”和“ES2016”,新版以本年命名),有很多的附加功能和改进的语法,是非常值得期待的(并已部分被当前的浏览器和后端JS的环境支持)。

此篇博文,引自《Building Front-End Web Apps with Plain JavaScript》一书。

JavaScript类型和常量

JS有3个值类型:string,number和boolean,我们可以用一个变量v保存不同类型的值用来和typeof(v)比较, typeof(v)===”number”。

JS有5个引用类型:Object, Array, Function, Date 和 RegExp。数组,函数,日期和正则表达式是特殊类型的对象,但在概念上,日期和正则表达式是值类型,被包装成对象形式体现。

变量,数组,函数的参数和返回值都可以不声明,它们通常不会被JavaScript引擎检查,会被自动进行类型转换。

变量值可能为:

  1. 数据,如string,number,boolean
  2. 对象的引用:如普通对象,数组,函数,日期,正则表达式
  3. 特殊值null,其通常用作用于初始化的对象变量的默认值
  4. 特殊值undefined,已经声明但没有初始化的初始值

string是Unicode字符序列。字符串常量会被单引号或双引号包裹着,如“Hello world!”,“A3F0’,或者空字符串””。两个字符串表达式可以用+操作符连接,并可通过全等于比较:

<code class="hljs lisp"> if (<span class="hljs-name">firstName</span> + lastName === <span class="hljs-string">"James Bond"</span>) </code>

字符串的字符数量可以通过length属性获得:

<code class="hljs cpp">console.<span class="hljs-built_in">log</span>( <span class="hljs-string">"Hello world!"</span>.length);  <span class="hljs-comment">// 12</span></code>

所有的数字值都是在64位浮点数字。整数和浮点数之间没有明确的类型区别。如果一个数字常量不是数字,可以将其值设置为NaN(“not a number”),它可以用isNaN方法来判断。

不幸的是,直到ES6才有Number.isInteger方法,用于测试一个数是不是一个整数。因此在还不支持它的浏览器中,为确保一个数字值是一个整数,或者一个数字的字符串被转换为一个整数,就必须使用parseInt函数。类似地,包含小数的字符串可用与parseFloat方法转换。将一个数子n转换成字符串,最好的方法是使用String(n)。

就像Java,我们也有两个预先定义好的布尔型值,true与false,以及布尔运算符符号: ! (非),&&(与),||(或)。当非布尔型值与布尔型值比较时,非布尔型值会被隐式转换。空字符串,数字0,以及undefined和null,会被转换为false,其他所有值会转换为true。

通常我们需要使用全等符号符号(===和!==)而不是==和!=。否则,数字2是等于的字符串“2”的, (2 == “2”) is true

VAR= [] 和var a = new Array() 都可以定义一个空数组。(二胡:推荐前者)

VAR O ={} 和 var o = new Obejct() 都可以定义个空对象(二胡:还是推荐前者)。注意,一个空对象{}不是真的空的,因为它包含的Object.prototype继承属性。所以,一个真正的空对象必须以Null为原型, var o = Object.create(null)。

表1 类型测试和转换

变量作用域

在JavaScript的当前版本ES5,有两种范围变量:全局作用域和函数作用域,没有块作用域。因此,应该避免声明在块内声明变量。

<code class="hljs matlab"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span><span class="hljs-params">()</span> {</span>
  <span class="hljs-keyword">for</span> (var <span class="hljs-built_in">i</span>=<span class="hljs-number">0</span>; <span class="hljs-built_in">i</span> &lt; <span class="hljs-number">10</span>; <span class="hljs-built_in">i</span>++) {
    ...  // do something with i
  }
}</code>

我们应该这样写

<code class="hljs matlab"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span><span class="hljs-params">()</span> {</span>
  var <span class="hljs-built_in">i</span>=<span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-built_in">i</span>=<span class="hljs-number">0</span>; <span class="hljs-built_in">i</span> &lt; <span class="hljs-number">10</span>; <span class="hljs-built_in">i</span>++) {
    ...  // do something with i
  }
}</code>

所有变量应在函数的开始声明。只有在JavaScript的下一个版本ES6中,我们可以用let关键词声明一个块级变量。

严格模式

从ES5开始,我们可以使用严格模式,获得更多的运行时错误检查。例如,在严格模式下,所有变量都必须进行声明。给未声明的变量赋值抛出异常。

我们可以通过键入下面的语句作为一个JavaScript文件或script元素中的第一行开启严格模式:’use strict’;

通常建议您使用严格模式,除非你的代码依赖于与严格的模式不兼容的库。

不同类型的对象

JS对象与传统的OO/UML对象不同。它们可以不通过类实例化而来。它们有属性、方法、键值对三种扩展。

JS对象可以直接通过JSON产生,而不用实例化一个类。

<code class="hljs javascript"><span class="hljs-keyword">var</span> person1 = { lastName:<span class="hljs-string">"Smith"</span>, firstName:<span class="hljs-string">"Tom"</span>};
<span class="hljs-keyword">var</span> o1 = <span class="hljs-built_in">Object</span>.create( <span class="hljs-literal">null</span>);  <span class="hljs-comment">// an empty object with no slots</span></code>

对象属性可以以两种方式获得:

  1. 使用点符号(如在C ++/ Java的):

    person1.lastName = “Smith”

  2. 使用MAP方式

    person1[“lastName”] = “Smith”

JS对象有不同的使用方式。这里有五个例子:

  1. 记录,例如,

    var myRecord = {firstName:”Tom”, lastName:”Smith”, age:26}

  2. MAP(也称为“关联数组”,“词典”或其他语言的“哈希表”)

    var numeral2number = {“one”:”1″, “two”:”2″, “three”:”3″}

  3. 非类型化对象

    var person1 = { lastName: "Smith", firstName: "Tom", getFullName: function () { return this.firstName +" "+ this.lastName; } };

  4. 命名空间

    var myApp = { model:{}, view:{}, ctrl:{} };

可以由一个全局变量形式来定义,它的名称代表一个命名空间前缀。例如,上面的对象变量提供了基于模型 – 视图 – 控制器(MVC)架构模式,我们有相应的MVC应用程序的三个部分。

  1. 正常的类

数组

可以用一个JavaScript数组文本进行初始化变量:
var a = [1,2,3];

因为它们是数组列表,JS数组可动态增长:我们可以使用比数组的长度更大的索引。例如,上面的数组变量初始化后,数组长度为3,但我们仍然可以操作第5个元素 a[4] = 7;

我们可以通过数组的length属性得到数组长度:

<code class="hljs coffeescript">`<span class="javascript"><span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i &lt; a.length; i++) { <span class="hljs-built_in">console</span>.log(a[i]);} <span class="hljs-comment">//1 2 3 undefined 7 </span></span>` </code>

我们可以通过 Array.isArray(a) 来检测一个变量是不是数组。

通过push方法给数组追加元素:a.push( newElement);

通过splice方法,删除指定位置的元素:a.splice( i, 1);

通过indexOf查找数组,返回位置或者-1:if (a.indexOf(v) > -1) …

通过for或者forEach(性能弱)遍历数组:

<code class="hljs matlab">var <span class="hljs-built_in">i</span>=<span class="hljs-number">0</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-built_in">i</span>=<span class="hljs-number">0</span>; <span class="hljs-built_in">i</span> &lt; a.<span class="hljs-built_in">length</span>; <span class="hljs-built_in">i</span>++) {
  console.log( a[i]);
}
a.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(elem)</span> {</span>
  console.<span class="hljs-built_in">log</span>( elem);
}) </code>

通过slice复制数组:var clone = a.slice(0);

Maps

map(也称为“散列映射”或“关联数组’)提供了从键及其相关值的映射。一个JS map的键是可以包含空格的字符串:

<code class="hljs swift"><span class="hljs-keyword">var</span> myTranslation = { 
<span class="hljs-string">"my house"</span>: <span class="hljs-string">"mein Haus"</span>, 
<span class="hljs-string">"my boat"</span>: <span class="hljs-string">"mein Boot"</span>, 
<span class="hljs-string">"my horse"</span>: <span class="hljs-string">"mein Pferd"</span>
}</code>

通过Object.keys(m)可以获得map中所有的键:

<code class="hljs perl">var i=<span class="hljs-number">0</span>, key=<span class="hljs-string">""</span>, <span class="hljs-keyword">keys</span>=[];
<span class="hljs-keyword">keys</span> = Object.<span class="hljs-keyword">keys</span>( myTranslation);
<span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i &lt; <span class="hljs-keyword">keys</span>.<span class="hljs-keyword">length</span>; i++) {
  key = <span class="hljs-keyword">keys</span>[i];
  alert(<span class="hljs-string">'The translation of '</span>+ key +<span class="hljs-string">' is '</span>+ myTranslation[key]);
}</code>

通过直接给不存在的键赋值来新增元素:

<code class="hljs prolog">myTranslation[<span class="hljs-string">"my car"</span>] = <span class="hljs-string">"mein Auto"</span>;</code>

通过delete删除元素:

<code class="hljs sql"><span class="hljs-keyword">delete</span> myTranslation[<span class="hljs-string">"my boat"</span>];</code>

通过in搜索map:

<code class="hljs coffeescript">`<span class="javascript"><span class="hljs-keyword">if</span> (<span class="hljs-string">"my bike"</span> <span class="hljs-keyword">in</span> myTranslation)  ...</span>`</code>

通过for或者forEach(性能弱)和Object.keys()遍历map:

<code class="hljs perl">var i=<span class="hljs-number">0</span>, key=<span class="hljs-string">""</span>, <span class="hljs-keyword">keys</span>=[];
<span class="hljs-keyword">keys</span> = Object.<span class="hljs-keyword">keys</span>( <span class="hljs-keyword">m</span>);
<span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i &lt; <span class="hljs-keyword">keys</span>.<span class="hljs-keyword">length</span>; i++) {
  key = <span class="hljs-keyword">keys</span>[i];
  console.<span class="hljs-keyword">log</span>( <span class="hljs-keyword">m</span>[key]);
}
Object.<span class="hljs-keyword">keys</span>( <span class="hljs-keyword">m</span>).forEach( function (key) {
  console.<span class="hljs-keyword">log</span>( <span class="hljs-keyword">m</span>[key]);
}) </code>

通过 JSON.stringify 将map序列化为JSON字符串,再JSON.parse将其反序列化为MAP对象 来实现复制:

<code class="hljs javascript"><span class="hljs-keyword">var</span> clone = <span class="hljs-built_in">JSON</span>.parse( <span class="hljs-built_in">JSON</span>.stringify( m)) </code>

请注意,如果map上只包含简单数据类型或(可能嵌套)数组/map,这种方法效果很好。在其他情况下,如果map包含Date对象,我们必须写我们自己的clone方法。

Functions

JS函数是特殊的JS的对象,它具有一个可选的名字属性和一个长度属性(参数的数目)。我们可以这样知道一个变量是不是一个函数:

<code class="hljs javascript"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>( v) === <span class="hljs-string">"function"</span>) {...}</code>

JS函数可以保存在变量里、被当作参数传给其他函数,也可以被其他函数作为返回值返回。JS可以被看成一个函数式语言,函数在里面可以说是一等公民。

正常的定义函数方法是用一个函数表达式给一个变量赋值:

<code class="hljs javascript"><span class="hljs-keyword">var</span> myFunction = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">theNameOfMyFunction</span> () </span>{...}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">theNameOfMyFunction</span> () </span>{...}</code>

其中函数名(theNameOfMyFunction)是可选的。如果省略它,其就是一个匿名函数。函数可以通过引用其的变量调用。在上述情况下,这意味着该函数通过myFunction()被调用,而不是通过theNameOfMyFunction()调用。

JS函数,可以嵌套内部函数。闭包机制允许在函数外部访问函数内部变量,并且创建闭包的函数会记住它们。

当执行一个函数时,我们可以通过使用内置的arguments参数,它类似一个参数数组,我们可以遍历它们,但由于它不是常规数组,forEach无法遍历它。arguments参数包含所有传递给函数的参数。我们可以这样定义一个不带参数的函数,并用任意数量的参数调用它,就像这样:

<code class="hljs javascript"><span class="hljs-keyword">var</span> sum = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
  <span class="hljs-keyword">var</span> result = <span class="hljs-number">0</span>, i=<span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">arguments</span>.length; i++) {
    result = result + <span class="hljs-built_in">arguments</span>[i];
  }
  <span class="hljs-keyword">return</span> result;
};
<span class="hljs-built_in">console</span>.log( sum(<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">5</span>,<span class="hljs-number">8</span>));  <span class="hljs-comment">// 20</span></code>

prototype原型链可以访问函数中的每一个元素,如Array.prototype.forEach(其中Array代表原型链中的数组的构造函数)。

<code class="hljs javascript"><span class="hljs-keyword">var</span> numbers = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>];  <span class="hljs-comment">// create an instance of Array</span>
numbers.forEach( <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">n</span>) </span>{
  <span class="hljs-built_in">console</span>.log( n);
});</code>

我们还可以通过原型链中的prototype.call方法来处理:

<code class="hljs javascript"><span class="hljs-keyword">var</span> sum = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
  <span class="hljs-keyword">var</span> result = <span class="hljs-number">0</span>;
  <span class="hljs-built_in">Array</span>.prototype.forEach.call( <span class="hljs-built_in">arguments</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">n</span>) </span>{
    result = result + n;
  });
  <span class="hljs-keyword">return</span> result;
};</code>

Function.prototype.apply是Function.prototype.call的一个变种,其只能接受一个参数数组。

立即调用的JS函数表达式优于使用纯命名对象,它可以获得一个命名空间对象,并可以控制其变量和方法哪些可以外部访问,哪些不是。这种机制也是JS模块概念的基础。在下面的例子中,我们定义了一个应用程序,它对外暴露了指定的元素和方法:

<code class="hljs javascript">myApp.model = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
  <span class="hljs-keyword">var</span> appName = <span class="hljs-string">"My app's name"</span>;
  <span class="hljs-keyword">var</span> someNonExposedVariable = ...;
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ModelClass1</span> () </span>{...}
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ModelClass2</span> () </span>{...}
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">someNonExposedMethod</span> (<span class="hljs-params">...</span>) </span>{...}
  <span class="hljs-keyword">return</span> {
    appName: appName,
    ModelClass1: ModelClass1,
    ModelClass2: ModelClass2
  }
}();  <span class="hljs-comment">// immediately invoked</span></code>

这种模式在WebPlatform.org被当作最佳实践提及:https://docs.webplatform.org/wiki/tutorials/javascript_best_practices

定义和使用类

类是在面向对象编程的基础概念。对象由类实例化而来。一个类定义了与它创建的对象的属性和方法。

目前在JavaScript中没有明确的类的概念。JavaScript中定义类有很多不同的模式被提出,并在不同的框架中被使用。用于定义类的两个最常用的方法是:

构造函数法,它通过原型链方法来实现继承,通过new创建新对象。这是Mozilla的JavaScript指南中推荐的经典方法。

工厂方法:使用预定义的Object.create方法创建类的新实例。在这种方法中,基于构造函数继承必须通过另一种机制来代替。

当构建一个应用程序时,我们可以使用这两种方法创建类,这取决于应用程序的需求 。mODELcLASSjs是一个比较成熟的库用来实现工厂方法,它有许多优点。(基于构造的方法有一定的性能优势)

ES6中构造函数法创建类

在ES6,用于定义基于构造函数的类的语法已推出(新的关键字类的构造函数,静态类和超类)。这种新的语法可以在三个步骤定义一个简单的类。

基类Person 定义了两个属性firstName 和lastName,以及实例方法toString和静态方法checkLastName:

<code class="hljs javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">constructor</span>( first, last) {
    <span class="hljs-keyword">this</span>.firstName = first;
    <span class="hljs-keyword">this</span>.lastName = last;
  }
  toString() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.firstName + <span class="hljs-string">" "</span> +
        <span class="hljs-keyword">this</span>.lastName;
  }
  static checkLastName( ln) {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(ln)!==<span class="hljs-string">"string"</span> || 
        ln.trim()===<span class="hljs-string">""</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error: "</span> +
          <span class="hljs-string">"invalid last name!"</span>);
    }
  }
}</code>

类的静态属性如下定义:

<code class="hljs">Person.instances = {};</code>

一个子类定义的附加属性和可能会覆盖超类的方法:

<code class="hljs scala"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Person</span> </span>{
  constructor( first, last, studNo) {
    <span class="hljs-keyword">super</span>.constructor( first, last);
    <span class="hljs-keyword">this</span>.studNo = studNo; 
  }
  <span class="hljs-comment">// method overrides superclass method</span>
  toString() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.toString() + <span class="hljs-string">"("</span> +
        <span class="hljs-keyword">this</span>.studNo +<span class="hljs-string">")"</span>;
  }
}</code>

ES5中构造函数法创建类

在ES5,我们可以以构造函数的形式定义一个基于构造函数的类结构,下面是Mozilla的JavaScript指南中推荐的编码模式。此模式需要七个步骤来定义一个简单的类结构。由于这种复杂的模式可能很难记住,我们可能需要使用cLASSjs之类的库来帮助我们。

首先定义构造函数是隐式创建一个新的对象,并赋予它相应的值:

<code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Person</span>(<span class="hljs-params"> first, last</span>) </span>{
  <span class="hljs-keyword">this</span>.firstName = first; 
  <span class="hljs-keyword">this</span>.lastName = last; 
}</code>

这里的this指向新创建的对象。

在原型中定义实例方法:

<code class="hljs javascript">Person.prototype.toString = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.firstName + <span class="hljs-string">" "</span> + <span class="hljs-keyword">this</span>.lastName;
}</code>

可以在构造函数中定义静态方法,也可以用.直接定义:

<code class="hljs javascript">Person.checkLastName = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">ln</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(ln)!==<span class="hljs-string">"string"</span> || ln.trim()===<span class="hljs-string">""</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error: invalid last name!"</span>);
  }
}</code>

定义静态属性:

<code class="hljs">Person.instances = {};</code>

定义子类并增加属性:

<code class="hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Student</span>(<span class="hljs-params"> first, last, studNo</span>) </span>{
  <span class="hljs-comment">// invoke superclass constructor</span>
  Person.call( <span class="hljs-keyword">this</span>, first, last);
  <span class="hljs-comment">// define and assign additional properties</span>
  <span class="hljs-keyword">this</span>.studNo = studNo;  
}</code>

通过Person.call( this, …) 来调用基类的构造函数。

将子类的原型链改为基类的原型链,以实现实例方法的继承(构造函数得改回来):

<code class="hljs delphi"><span class="hljs-comment">// Student inherits from Person</span>
Student.prototype = <span class="hljs-keyword">Object</span>.create( 
    Person.prototype);
<span class="hljs-comment">// adjust the subtype's constructor property</span>
Student.prototype.<span class="hljs-keyword">constructor</span> = Student;</code>

通过Object.create( Person.prototype) 我们基于 Person.prototype创建了一个新的对象原型。

定义覆盖基类方法的子类方法:

<code class="hljs javascript">Student.prototype.toString = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
  <span class="hljs-keyword">return</span> Person.prototype.toString.call( <span class="hljs-keyword">this</span>) +
      <span class="hljs-string">"("</span> + <span class="hljs-keyword">this</span>.studNo + <span class="hljs-string">")"</span>;
};</code>

最后通过new关键字来实例化一个类

<code class="hljs javascript"><span class="hljs-keyword">var</span> pers1 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Tom"</span>,<span class="hljs-string">"Smith"</span>);</code>

JavaScript的prototype

prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。

__proto__是一个对象拥有的内置属性(prototype是函数的内置属性。__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。

每个对象都有个constructor属性,其指向的是创建当前对象的构造函数。

工厂模式创建类

在这种方法中,我们定义了一个JS对象Person,并在其内部定义了一个create方法用来调用Object.create来创建类。

<code class="hljs javascript"><span class="hljs-keyword">var</span> Person = {
  name: <span class="hljs-string">"Person"</span>,
  properties: {
    firstName: {range:<span class="hljs-string">"NonEmptyString"</span>, label:<span class="hljs-string">"First name"</span>, 
        writable: <span class="hljs-literal">true</span>, enumerable: <span class="hljs-literal">true</span>},
    lastName: {range:<span class="hljs-string">"NonEmptyString"</span>, label:<span class="hljs-string">"Last name"</span>, 
        writable: <span class="hljs-literal">true</span>, enumerable: <span class="hljs-literal">true</span>}
  },
  methods: {
    getFullName: <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.firstName +<span class="hljs-string">" "</span>+ <span class="hljs-keyword">this</span>.lastName; 
    }
  },
  create: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">slots</span>) </span>{
    <span class="hljs-comment">// create object</span>
    <span class="hljs-keyword">var</span> obj = <span class="hljs-built_in">Object</span>.create( <span class="hljs-keyword">this</span>.methods, <span class="hljs-keyword">this</span>.properties);
    <span class="hljs-comment">// add special property for *direct type* of object</span>
    <span class="hljs-built_in">Object</span>.defineProperty( obj, <span class="hljs-string">"type"</span>, 
        {value: <span class="hljs-keyword">this</span>, writable: <span class="hljs-literal">false</span>, enumerable: <span class="hljs-literal">true</span>});
    <span class="hljs-comment">// initialize object</span>
    <span class="hljs-built_in">Object</span>.keys( slots).forEach( <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">prop</span>) </span>{
      <span class="hljs-keyword">if</span> (prop <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span>.properties) obj[prop] = slots[prop];
    })
    <span class="hljs-keyword">return</span> obj;
  }
};  </code>

这样,我们就有了一个Person的工厂类,通过调用create方法来实例化对象。

<code class="hljs groovy">var pers1 = Person.create( {<span class="hljs-string">firstName:</span><span class="hljs-string">"Tom"</span>, <span class="hljs-string">lastName:</span><span class="hljs-string">"Smith"</span>});</code>

.Net 高效开发之不可错过的实用工具

Standard

工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为各ASP.NET 开发者介绍一些高效实用的工具,涉及SQL 管理,VS插件,内存管理,诊断工具等,涉及开发过程的各个环节,让开发效率翻倍。

  1. Visual Studio
    1. Visual Studio Productivity Power tool: VS 专业版的效率工具。
    2. Web Essentials: 提高开发效率,能够有效的帮助开发人员编写CSS, JavaScript, HTML 等代码。
    3. MSVSMON: 远程Debug 监控器 (msvsmon.exe) 是一种轻量级的应用程序,能够远程控制VS来调试程序。在远程调试期间,VS 在调试主机运行,MSVSMON 在远程机器中运行。
    4. WIX toolset: 可以将XML 源代码文件编译成Windows 安装包。
    5. Code digger: Code Digger 是VS 2012/2013 的扩展插件,能够帮助开发人员分析代码。
    6. CodeMaid: CodeMaid 是一款开源的VS2012/2013/2015 插件,提供代码分析,清理,简化代码的功能。
    7. OzCode: 非常强大的VS 调试工具。
    8. CodeRush: 是VS的提高代码重构和提升效率的VS插件。
    9. T4 Text Template:VS中T4 文本模板是生成代码文件最常用的模板文件,这种模板文件是通过编写文本块和控制逻辑来实现的。
    10. Indent Guides:  快速添加缩进行。
    11. PowerShell Tools:支持开发和调试PowerShell 脚本和VS2015代码块的工具包。
    12. Visual Studio Code: 免费的跨平台编辑器,可以编译和调试现代的Web和云应用。
  2. ASP.NET
    1. Fiddler: 能够捕获 http 请求/响应来模拟请求行为。
    2. AutoMapper: 自动生成对象到对象的映射代码,比如,能够生成从实体对象映射到域对象,而不是手动编写映射代码。Object to object mapping. Like, the tool can be used to map entity objects to domain objects instead of writing manual mapping code.
    3. Unity/Ninject/Castle Windsor/StructureMap/Spring.Net: 依赖性映射框架,提供很多可用的DI 框架。
    4. .NET Reflector: .NET 程序反编译器。
    5. dotPeek: .NET 程序反编译器。
    6. ILSpy: .NET 程序反编译器。
    7. memprofiler: 非常强大的查找内存泄露和优化内存使用的工具。
    8. PostSharp: 去除重复编码和避免由于交叉引用产生的代码冗余。
    9. ASPhere: Web.config 图形化编辑器
  3. WCF
    1. SOAP UI: API 测试工具,支持所有标准的协议和技术。
    2. WireShark:UNIX和Windows系统的网络协议分析器。用于捕获TCP 层的拥塞状况,还能帮你过滤无效信息。
    3. Svc TraceViewer: 提供文件追踪视图,是由WFO提供的。
    4. Svc Config Editor: 用于管理WCF相关配置的图形化界面工具。
  4. MSMQ
    1. QueueExplorer 3.4: 提供消息操作功能,如复制,删除,移动消息,保存和加载,强压测试,浏览编辑等
  5. LINQ
    1. LINQ Pad: LINQPad 是一个轻量级工具,用来测试Linq查询。 可以测试由不同语言写的.Net 语言脚本。
    2. LINQ Insight: LINQ Insight Express 可嵌入 Visual Studio 中,能够分析设计时的LINQ查询 。
  6. RegEx
    1. RegEx tester: 正则表达式插件。
    2. regexr: 在线正则表达式开发和测试工具。
    3. regexpal: 在线正则表达式开发和测试工具。
    4. Expresso: 桌面版的正则表达式工具。
    5. RegexMagic : 能够根据文本模式自动生成正则表达式的工具。
  7. Javascript/JQuery/AngularJS
    1. JSHint: JavaScript代码质量监控工具,定义了很多非常严格的规则。
    2. JSFiddle: 提供了浏览器内部的开发环境,能够测试HTML,CSS,Javascript/JQuery代码
    3. Protractor: 端到端的框架,能够测试Angular应用。
  8. SQL Server
    1. SQL Profiler: SQL 跟踪监控工具。
    2. ExpressProfiler: ExpressProfiler (aka SqlExpress Profiler) 是一个小型快速的SQL Server Profiler的替换工具,自带GUI界面。能够用于企业版和非企业版 的SQL Server。
    3. SQL Sentry Plan explorer: 提供了SQL 查询执行计划的很好的物理视图。
    4. SQL Complete: 为 SQL Server Management Studio and Visual Studio 提供非常智能的,优化SQL 格式的管理工具。
    5. NimbleText:文本操作和代码生成工具。
    6. Query Express: 轻量级的SQL 查询分析器。
    7. IO Meter: 提供IO 子系统的一些访问具体情况
    8. sqldecryptor: 可以解密SQL Server 中的加密对象,如存储过程,方法,触发器,视图。
    9. SpatialViewer: 可以预览和创建空间数据。
    10. ClearTrace: 导入跟踪和分析文件,并显示汇总信息。
    11. Internals Viewer for SQL Server: Internals Viewer 用来在SQL Server 的存储引擎中的查找工具,以及获取数据在物理层是如何分配,组织和存储的。
  9. NHibernate
    1. NHibernate Mapping Generator : 生成 NHibernate 映射文件,并从存在的数据库表映射到领域类。
  10. ​Tally
    1. Tally ERP 9
    2. Tally dll: .net 的动态链接库,能够将Tally Accounting 软件集成到应用程序中 ,通过代码对数据进行push或pull操作。
  11. 代码Review
    1. StyleCop: StyleCop 是静态代码分析工具,能够统一设置代码样式和规范。 可以在Visual Studio 中使用,也可以集成到 MSBuild 项目。
    2. FxCop: FxCop 是静态代码分析工具,能够通过分析.Net 程序集保证开发标准。
  12. 运行状况捕获
    1. WireShark: It is a network protocol analyzer for Unix and Windows. It can capture traffic at TCP level.
    2. HTTP Monitor: enables the developer to view all the HTTP traffic between your computer and the Internet. This includes the request data (such as HTTP headers and form GET and POST data) and the response data (including the HTTP headers and body).
  13. 诊断工具
    1. Glimpse:提供服务器端诊断数据。如 在ASP.NET MVC 项目,可以通过NuGet添加。
  14. 性能
    1. PerfMon: 使用 性能计数器监控系统性能。
  15. 代码转换器
    1. Telerik Code Converter: C# 到 VB 及 VB 到C# 代码转换器. I是一个在线编辑工具,可以选择 ‘Batch Converter’ ,并使用压缩包上传文件。
  16. 屏幕记录工具
    1. Wink: Using Wink, 可以轻松截图,并为截图添加描述等,也可以录制Demo。
  17. 文本编辑器
    1. Notepad++: 源码编辑器
    2. Notepad2: 轻量级功能丰富的文本编辑器
    3. sublimetext:富文本编辑器
  18. 文档工具
    1. GhostDoc: GhostDoc 是 Visual Studio 扩展项,能够自动生成 方法或属性的 文档注释,包括它们的类型,名称,其他上下文信息。
    2. helpndoc: helpndoc 用于创建帮助文档工具,能够根据文档源生成多种格式。
  19. 其他
    1. FileZilla: FileZilla 是开源的FTP 工具. 通过FileZilla 客户端可以将文件上传到FTP 服务器上。
    2. TreeTrim: TreeTrim 是调整代码的工具,能够删除一些无效的debug文件和临时文件等。
    3. BrowserStack: 支持跨浏览器测试的工具。
    4. BugShooting: 屏幕截图软件,能够铺货和附加工作项,bug,问题跟踪项等。
    5. Postman: REST 客户端,能够发送http请求,分析REST 应用程序发出的响应。
    6. Web developer checklist: checklist可用来管理开发计划
    7. PowerGUI: 能够快接收和使用PowerShell 来有效管理 Windows 开发环境。
    8. Beyond Compare: 提供文件对比功能。
    9. PostMan: REST Chrome 器扩展项
    10. Devart Codecompare: 文件区分工具,能够读取 C#, C++,VB 代码结构 。包括:文件夹对比工具,独立App 比较合并文件夹和文件,代码review 支持。

每个程序员应该阅读的10本经典书籍

Standard

如果你是一个程序员,除了编码之外,你还需要大量的阅读。今天我要为大家介绍几本值得一读的书,包括《The Pragmatic Programmer》,《The Mythical Man-month: Essays on Software Engineering》和《Clean Code: A Handbook of Agile Software Craftsmanship》。

书籍是知识和智慧的重要来源。但不幸的是,现在很多人已经不愿意看书了。程序员更是罕见地会去读书,最常见的依靠互联网搜索结果来找寻答案。

技术向前的步伐比人类历史上的任何时候都要走得更快。用不了几个月,就会有新的编程语言和工具问世,弥补现有语言、工具和方法的缺陷。

事实上,许多伟人都已经遇到过差不多的问题,并指出了解决这些问题的最佳途径。而这些方法和解决方案都收录在一些超棒的书籍中。

下面就是在这个行业中开发人员应该阅读的一系列伟大的书籍。

《The Pragmatic Programmer》

绝对是书籍中的瑰宝!这不是常规地建议你编码,编码还是编码的编程书。事实上,它并不限定于某种特定的编程语言:在这本书中的智慧适用于所有编程语言。

这本书对许多有趣的领域都提出了真知灼见,如各种探索性编程,在代码中编码,从模型中分离的观点,昂贵的工具并不产生更好的设计,开发一个伟大的团队,管理预期,避免知识的重复等。

这本书不仅可以帮助改变编码的习惯,还可以改变你作为一个程序员的性格。它充满了关于如何改进自己和代码的实用建议。

还有一个总结了提示和检查清单的小册子。

《The Mythical Man-month》: 关于软件工程的散文集

非常经典,被奉为软件行业的圣经。第一次出版于1970年,但是里面的内容比起以前,可能更适用于现在!

有听说过这些话吗?它们均摘自于这本书!

“所有的程序员都是乐观的:一切都会顺利。”

“添加人手到一个延迟的项目中只会导致完成得更慢。”

“生一个孩子总是需要九个月的时间,不管安排多少个女性。”

“一个煎蛋,承诺在两分钟内完成,但如果两分钟后还是没有准备好,那么客户有两种选择——等待或吃半熟品,软件客户也只能这样选择。”

不幸的是,一年又一年地过去,而我们总是在软件开发中犯着相同的错误。这本书是每一个项目经理和开发人员都必须阅读的。

正从标题中所说的那样,这是一本散文集。文辞优美。这本书唯一的缺点就是引用了年迈25的古老技术。但是,这并不影响这本书的魅力。

《Clean Code》: 敏捷软件工艺的手册

有没有在看他人代码的过程中,不由自主地发出“哦,天哪,这是什么?”的经历,那么这个人肯定没有阅读过《Clean Code》。

这是一本关于软件工艺史诗般的书籍。这本书不仅会告诉你如何编写好的代码,而且还提供了软件开发的高效途径。照着去做的话,必将改变你的工作前景。

书中描述了编写干净代码的原则、模式和做法。里面一些关于整洁代码的几个案例都是开发人员宝贵的经验教训。

请注意,虽然在这本书中的所有实例都是关于Java的,但是从中学到的经验教训可以应用于任意的编程语言。

这篇文章所列出的这些书籍中,这本书出版得比较晚,所以可能更能引起年轻开发人员的共鸣。

《The Clean Coder》:专业程序员的行为守则

此列表中Rob Martin的第二本书。建议你在读了《Clean Code》后,再读这本书。《Clean Code》讲的是代码,而这本书是关于“Coder”。

该书探讨了一些程序员经常忽视的主题。

  • 成为专业的程序员意味着什么?
  • 如何打磨自己成为一个真正的软件工匠
  • 冲突和紧张的日程处理
  • 如何管理你的时间?如何扩张技能?
  • 何时说“不”
  • 避免倦怠
  • ..以及更多。

你可能并不总是同意作者的观点,但它提供了良好的精神食粮。这可能并非你所期望的,但可能正是你所需要的。

《Refactoring》:改善已有代码的设计

不管你怎么努力,除非改进它,否则,你交付的代码不会是最优化的。有时即使工作正常,也会实施重构。

这本书从重构的通用原则说起:为什么以及什么时候重构,如何处理有关重构的管理等等。然后讲述了如何实现改进的过程。

  • 代码的设计缺陷指标是什么?
  • 如何构建类、方法和其他的逻辑块?
  • 单元测试
  • 如何将功能从一个对象移动到另一个?
  • 重构工具
  • ..以及更多

这是改进现有代码必读的书。请注意,所有的代码示例用的都是Java,但现在复制起来也很方便!

《Working Effectively With Legacy Code》

我们都必须工作于一些我们痛恨的东西——对于大多数人而言,遗留代码真是令人头痛无比。

如何修改遗留代码?如何识别需要重构的代码部分?如何破坏重构代码之间的依赖关系?如何确保新的代码能完成预期的工作?如何一次一小步地重构遗留代码?

在这本杰出的书中,只是回答了一些关键的问题。如果非要用一句话总结这本书的精华,那就是“写单元测试,重构代码,确保测试都通过。”

遗留代码不是一个神话,它是一个活着的传奇!在软件行业中没有什么比遗留代码更能经受测试的考验了——Deepak Karanth

《Code Complete》:软件构建的实用手册

在一个庞大的作品中,如果你想要阅读所有关于编程结构和最佳实践的内容,那么这是本必读书。真正的百科全书式书籍——其最新版本有多达960页!不要被这本书的厚度吓倒,你可以按照自己的节奏阅读。最后,你会庆幸你阅读了这本书。

书中解释了软件开发的每个方面。从代码结构,代码格式化,到变量、方法和类的命名,再一路说到管理一个团队,对所有一切都提出了实用的建议。

提供了覆盖特定主题的丰富参考和补充材料,这些也非常值得一读。

只有一小部分的软件开发人员会读这本书,所以如果你也是他们中的一个,那么你就有了优势。通过阅读这本书,你就可以获得许多年宝贵经验。

《Head First Design Patterns》

看上去最不像技术的编程书籍!每个页面都包含涂鸦、图片以及其他一些吸引眼球的东西。可能给人的印象是一本阅读起来很轻松的书,但事实上它会讨论编程的一些核心主题——设计模式

这本书虽然没有覆盖所有存在于这个世界的模式,但是会涵盖所有你可能需要用于解决现实问题的模式。它将帮助你创建功能性的,优雅的,可重用的和灵活的软件。每个模式的优劣也被明确指出。大多数关于设计模式的书籍谈论的是如何实现模式,但这本书的作者同时还解释了为什么以及怎么样。

最新版本包括针对Java 8的更新——主要是Lambda。

《Peopleware: Productive Projects and Teams》

很棒的一部作品。这本书并非关于编程。这是一本有关管理和激励程序员的书籍。开发人员也应该阅读。很多时候,开发人员,尤其是那些没有经验的开发人员,不理解管理的思维过程。

软件开发是一个创造性的过程。但是,大多数管理人员把它当作是流水线。开发人员被视为是机器上可替换的齿轮零部件。管理人员普遍性地会给予一个紧迫的时间期限,当作促进积极性唯一途径。他们对开发人员的工作不感兴趣,甚至可悲的是,他们也不会试着去理解开发人员或他们自己的工艺。

如果你想成为一个想要的是质量,而不仅仅是数量的管理人员,那么请立刻阅读这本书!

作者解释了管理者应该如何以一种可持续的方式使他们的软件开发团队认识到他们的潜力。

《Soft Skills: The Software Developer’s Life Manual》

同样的,这也不是一本关于编程的书。但是,却是每一个程序员都应该阅读的书。

这本伟大的书着重于管理开发人员生活的“其他”方面。可以是你生活的每一个方面——事业、生活、身体、头脑,以及不管你相信与否——还有灵魂。

作者他自己也遵循这些技术,并且获得了成功。他的网站上说,他能够在他30出头的时候放弃他的日常工作。该作者将他的生活经验整理成整齐的,主题内容为Career、Marketing yourself、Learning、Productivity、Finances, Fitness和Spirit的短章。每个篇章都很短,可以在休息时间阅读,非常方便。

你会是一个更加满意和快乐的人,如果你按照这本书的建议去做的话,那么你将成为一个更令人满意和幸福的人和程序员。