数据处理的 9 大编程语言

英文:Anna Nicolauo

译者:伯乐在线 – 胡波

链接:http://blog.jobbole.com/100732/

有关大数据的话题一直很火热。伴随着信息的爆炸式增长,大数据渗透到了各行各业,广泛应用于公司中,同时也使得传统的软件比如 Excel 看起来很笨拙。数据分析不再只是书呆子的事,同时其对高复杂性分析、实时处理的需求也比以往更加庞大。

那么筛选海量数据集最优的工具是什么呢?我们咨询了一些数据黑客关于他们在数据分析的核心工作中最喜欢的编程语言和工具包。

R 语言

这份名单如果不以 R 开头,那就是彻头彻尾的疏忽。自 1997 年起,作为一门免费的,可替代 Matlab 或 SAS 等昂贵统计软件的语言,R 被抛弃。

但是在过去的几年中,它却成了数据科学的宠儿—甚至成了统计学家、 华尔街交易员、生物学家和硅谷开发者必不可少的工具。 随着其商业价值的不断增长和传播,诸如谷歌、Facebook、 美国银行和纽约时代周刊都在使用。

R 简单易用。通过 R ,短短几行代码就可以筛选复杂的数据集,通过成熟的模型函数处理数据,制作精美的图表进行数据可视化。简直就是 Excel 的加强灵活版。

R 最大的价值就是围绕其开发的活跃的生态圈: R 社区在持续不断地向现存丰富的函数集增添新的包和特性。据估计 R 的使用者已经超过 200 万人,最近的一项调查也显示 R目前是数据科学领域最受欢迎的语言,大约 61% 的受访者使用 R(第二名是 Python, 占比39%)。

在华尔街,R 的使用比例也在不断增长。美国银行副总裁Niall O’Connor 说:“以往,分析员通常是熬夜研究 Excel 文件,但是现在 R 正被逐渐地应用于金融建模,尤其是作为可视化工具。R 促使了表格化分析的出局。”

作为一门数据建模语言, R 正在走向成熟,尽管在公司需要大规模产品的时候 R 能力有限,也有些人说它已经被其他语言替代了。

Metamarkets 公司的 CEO Michael Driscoll 说:“ R 擅长的是勾画,而不是搭建,在 Google 的 page rank 算法和 Facebook 的好友推荐算法实现的核心中是不会有 R 的。工程师会用 R 进行原型设计,再用 Java 或者 Python将其实现。”

Paul Butler 在 2010 年用 R 构建了一个著名的 Facebook 世界地图,证明了 R 在数据可视化上的强大能力。然而他并不经常使用 R。

Butler 说:“由于在处理较大数据集时缓慢且笨拙,R 在行业中已经有些沦为明日黄花了 ”

那么使用什么作为它的替代呢?看下去。

Python

如果 R 是个有点神经质的可爱的极客,那么 Python 就是它容易相处的欢快的表弟。融合了 R 快速成熟的数据挖掘能力以及更实际的产品构建能力, Python 正迅速地获得主流的呼声。 Python 更直观,且比 R 更易学,近几年其整体的生态系统发展也成长得很快,使其在统计分析上的能力超越了之前的 R 语言。

Butler 说:“Python 是行业人员正在转换发展的方向。过去两年里,很明显存在由 R 向 Python 转化的趋势”

在数据处理中,通常存在规模和技巧的权衡,Python 作为一个折中出现了。 IPython notebook 和NumPy 可以用于轻量工作的处理, 而 Python 则是中级规模数据处理的有力工具。丰富的数据交流社区也是 Python 的优势,它提供了大量的Python 工具包和特性。

美国银行利用 Python 开发新产品以及基础设施接口,同时也用于处理金融数据。O’Donnell 说:“Python 用途宽广且灵活,所以人们蜂拥而至”。

然而, Driscoll 也提到它并不是高性能的语言,偶尔才会用于装配驱动大规模的核心基础设施。

JULIA

最主流的数据科学处理语言包括 R、 Python、 Java、 Matlab和 SAS。但是这些语言仍然存在一些不足之处,而Julia 正是待以观察的新人。

对大规模商用来说, Julia 还是太晦涩了。但在谈到其取代 R 和 Python 领先地位的潜力的时候,数据极客们都会变得很激动。 Julia 是一门高级的,非常快的函数式语言。速度上比 R 快, 可能比 Python 的扩展性更高,且相对易学。

Butler 说:“Julia 正在快速上升。最终将可以用 Julia 完成任何 R 和 Python 可以完成的事”。

如今的问题是 Julia 太“年轻”了。 其数据交流社区仍处在早期发展阶段,在没有足够的包和工具之前是不足以与 R 和 Python 竞争的。

Driscoll 说:“Julia 很年轻,但正在积攒力量而且未来很可观”。

JAVA

在硅谷最大的科技公司里,Java 和基于 Java 的框架构成了其底层的技术骨架。Driscoll 说:“如果深入观察Twitter,Linkedin 或者 Facebook,你会发现 Java 是他们公司数据引擎架构的基础语言”。

Java 并没有 R 和 Python 那样的数据可视化的能力, 同时也不是最好的用于统计模型的语言。但是如果需要进行原型的基础开发和构建大规模系统, Java 往往是最好的选择。

HADOOP 和 HIVE

为了满足数据处理的巨大需求,基于 Java 的工具群涌而现。 作为基于 Java 的框架,Hadoop 在批处理领域成为热点。Hadoop 比其他处理工具速度要慢,但是它非常精确且被广泛的应用于后台分析,它很好的融合了 Hive, 一个运行在 Hadoop 上的基于查询的框架。

SCALA

Scala 是另一个基于 Java的语言,和 Java 很相似,它正在逐渐成长为大规模机器学习或高级算法的工具。它是函数式语言,也能够构建健壮的系统。

Driscoll 说:“Java 就像是直接用钢筋进行搭建, Scala 则像是在处理黏土原材料,可以将其放进窖中烧制成钢筋”。

KAFKA 和 STORM

当需要快速、实时分析时怎么办?Kafka 可以帮助你。它已经发展了大概五年时间,但最近才成为一个流处理的流行框架。

Kafka 诞生于 Linkedin 公司的内部项目,是一个快速查询系统。至于 Kafka 的缺点呢? 它太快了,实时的操作也导致了自身的错误,且偶尔还会遗失信息。

Driscoll 说:“在精度和速度之间总需要做权衡,所以硅谷所有的大公司一般都双管齐下: 用 kafka 和 Storm 进行实时处理,用 Hadoop 做批处理系统,虽然会慢一点但却十分精确”。

Storm 是另一个用 Scala 写的框架,且它在硅谷以擅长流处理而受到极大的关注。毫无疑问, Twitter, 一个对快速消息处理有着巨大兴趣的公司会收购了 Storm。

荣幸的提到:

MATLAB

MATLAB 已经存在很长时间了,尽管价格昂贵,但它仍在某些特定领域被广泛使用: 机器学习研究、信号处理、图像识别等领域。

OCTAVE

Octave 与 Matlab 非常相似,只不过它是免费的。然而除了信号处理的学术圈之外很少见到使用。

GO

GO 是另外一个获得关注的新手。它由 Google 开发,与 C 有一定渊源,且在构建稳定系统方面与 Java 和 Python 展开了竞争。

内有福利 | 做移动开发的你,真的学对了吗?

以下文稿来自RockPlayer联合创始人杨武老师的内部分享
杨武
RockPlayer联合创始人,上海改变科技有限公司CEO
编程爱好者,编写过MacRhine、iCosta、RockPlayer等
1
学习移动开发的几个成长段位
移动开发程序员,往往能够分为几个段位:
初级程序员:掌握语言模型和应用开发
中级程序员:同时掌握模块扩展
高级程序员:进而架构设计
各个段位的程序员,关注的学习重点显然也是不一样的。
第一阶段:语言模型(Spec,Memory,Object Model,Compile/Runtime)
第二阶段:应用开发(UI,Network,Storage,Threading,Engineering)
第三阶段:模块扩展(Design Patterns,Performance,Debugging,Domain) 
2
移动开发学习金字塔
学习金字塔是我长期以来一直分享给移动开发学习者的学习方式,可供参考
1.听课的同时进行阅读,如阅读苹果官方文档;
2.多进行一些视听,如观看WWDC等;
3.多和其他学习者和老师进行讨论
4.多进行实践,学习的时间和实践的时间1:3进行配比,基础薄弱的同学需要多看几遍教学视频或相关书籍;
5.注重分享,学习中得到什么收获,什么地方还可以优化,什么地方代码质量还不够高,一定需要分享,分享出来才会有思考过程;
此外,一周最少花费一小时总结自己所学,例如写博客,进行QQ交流群讨论等。
3
看书很重要
阅读的重要性不言而喻,以下是我分门别类针对移动开发学习列出的3个书单

Java 基础

《Thinking in Java》
中文版译为《Java 编程思想》,这本书受到了众多人的追捧,但也有很多人说这部书不适合初学者。很多程序员表示这本书帮助他们建立了面向对象的编程思想,非常值得一读,值得反复地读;也有人说这本书写得太过累赘,看起来好辛苦。
《Core Java》
中文版译为《Java 核心技术》,这应该称为一套书了,只需要看卷I 的基础知识就可以了。这本书可以说是与《Thinking in Java》齐名的一本书,包含了大量的案例,实践性强。

Android 开发

《Android 4 高级编程》
该书由Google Android 团队的一名Android开发倡导者所著
《Android 权威编程指南》
该书来自于美国一家专业的移动开发技术培训机构
《第一行代码:Android》
Android 初学者的入门书

iOS 开发

《iOS 7 Programming Fundamentals》——OC 语言基础
《iOS 7 Programming CookBook》——OC 语言编程
《iOS 9 Programming Fundamentals with Swift》——Swift 语言基础
《Programming iOS 9》——Swift 语言编程
《精通iOS 开发》——OC 与Swift 共用
iOS相关学习网站:
CocoaChina  http://www.cocoachina.com/
Stackoverflow  http://www.stackoverflow.com/
Github http://github.com/
学完上述这些,相信你已经收获满满!如果能与一线大牛工程师互动交流,相信你可以获得更多~

强烈推荐!Python 资源大全

英文:vinta

译文:伯乐在线 – 艾凌风

链接:http://python.jobbole.com/84464/

Awesome Python ,这又是一个 Awesome XXX 系列的资源整理,由 vinta 发起和维护。内容包括:Web框架、网络爬虫、网络内容提取、模板引擎、数据库、数据可视化、图片处理、文本处理、自然语言处理、机器学习、日志、代码分析等。

伯乐在线已在 GitHub 上发起「Python 资源大全中文版」的整理。欢迎扩散、欢迎加入。

https://github.com/jobbole/awesome-python-cn


环境管理

管理 Python 版本和环境的工具

  • p – 非常简单的交互式 python 版本管理工具。
  • pyenv – 简单的 Python 版本管理工具。
  • Vex – 可以在虚拟环境中执行命令。
  • virtualenv – 创建独立 Python 环境的工具。
  • virtualenvwrapper– virtualenv 的一组扩展。

包管理

管理包和依赖的工具。

  • pip – Python 包和依赖关系管理工具。
  • pip-tools – 保证 Python 包依赖关系更新的一组工具。
  • conda – 跨平台,Python 二进制包管理工具。
  • Curdling – 管理 Python 包的命令行工具。
  • wheel – Python 分发的新标准,意在取代 eggs。

包仓库

本地 PyPI 仓库服务和代理。

  • warehouse – 下一代 PyPI。

Warehouse bandersnatch – PyPA 提供的 PyPI 镜像工具。

  • devpi – PyPI 服务和打包/测试/分发工具。
  • localshop – 本地 PyPI 服务(自定义包并且自动对 PyPI 镜像)。

分发

打包为可执行文件以便分发。

  • PyInstaller – 将 Python 程序转换成独立的执行文件(跨平台)。
  • dh-virtualenv – 构建并将 virtualenv 虚拟环境作为一个 Debian 包来发布。
  • Nuitka – 将脚本、模块、包编译成可执行文件或扩展模块。
  • py2app – 将 Python 脚本变为独立软件包(Mac OS X)。
  • py2exe – 将 Python 脚本变为独立软件包(Windows)。
  • pynsist – 一个用来创建 Windows 安装程序的工具,可以在安装程序中打包 Python本身。

构建工具

将源码编译成软件。

  • buildout – 一个构建系统,从多个组件来创建,组装和部署应用。
  • BitBake – 针对嵌入式 Linux 的类似 make 的构建工具。
  • fabricate – 对任何语言自动找到依赖关系的构建工具。
  • PlatformIO – 多平台命令行构建工具。
  • PyBuilder – 纯 Python 实现的持续化构建工具。
  • SCons – 软件构建工具。

交互式解析器

交互式 Python 解析器。

  • IPython – 功能丰富的工具,非常有效的使用交互式 Python。
  • bpython– 界面丰富的 Python 解析器。
  • ptpython – 高级交互式Python解析器, 构建于python-prompt-toolkit 之上。

文件

文件管理和 MIME(多用途的网际邮件扩充协议)类型检测。

  • imghdr – (Python 标准库)检测图片类型。
  • mimetypes – (Python 标准库)将文件名映射为 MIME 类型。
  • path.py – 对 os.path 进行封装的模块。
  • pathlib – (Python3.4+ 标准库)跨平台的、面向对象的路径操作库。
  • python-magic– 文件类型检测的第三方库 libmagic 的 Python 接口。
  • Unipath– 用面向对象的方式操作文件和目录
  • watchdog – 管理文件系统事件的 API 和 shell 工具

日期和时间

操作日期和时间的类库。

  • arrow– 更好的 Python 日期时间操作类库。
  • Chronyk – Python 3 的类库,用于解析手写格式的时间和日期。
  • dateutil – Python datetime 模块的扩展。
  • delorean– 解决 Python 中有关日期处理的棘手问题的库。
  • moment – 一个用来处理时间和日期的Python库。灵感来自于Moment.js。
  • PyTime – 一个简单易用的Python模块,用于通过字符串来操作日期/时间。
  • pytz – 现代以及历史版本的世界时区定义。将时区数据库引入Python。
  • when.py – 提供用户友好的函数来帮助用户进行常用的日期和时间操作。

文本处理

用于解析和操作文本的库。

  • 通用

chardet – 字符编码检测器,兼容 Python2 和 Python3。

difflib – (Python 标准库)帮助我们进行差异化比较。

ftfy – 让Unicode文本更完整更连贯。

fuzzywuzzy – 模糊字符串匹配。

Levenshtein – 快速计算编辑距离以及字符串的相似度。

pangu.py – 在中日韩语字符和数字字母之间添加空格。

pyfiglet -figlet 的 Python实现。

shortuuid – 一个生成器库,用以生成简洁的,明白的,URL 安全的 UUID。

unidecode – Unicode 文本的 ASCII 转换形式 。

uniout – 打印可读的字符,而不是转义的字符串。

xpinyin – 一个用于把汉字转换为拼音的库。

  • Slug化

awesome-slugify – 一个 Python slug 化库,可以保持 Unicode。

python-slugify – Python slug 化库,可以把 unicode 转化为 ASCII。

unicode-slugify – 一个 slug 工具,可以生成 unicode slugs ,需要依赖 Django 。

  • 解析器

phonenumbers – 解析,格式化,储存,验证电话号码。

PLY – lex 和 yacc 解析工具的 Python 实现。

Pygments – 通用语法高亮工具。

pyparsing – 生成通用解析器的框架。

python-nameparser – 把一个人名分解为几个独立的部分。

python-user-agents – 浏览器 user agent 解析器。

sqlparse – 一个无验证的 SQL 解析器。

特殊文本格式处理

一些用来解析和操作特殊文本格式的库。

  • 通用

tablib – 一个用来处理中表格数据的模块。

  • Office

Marmir – 把输入的Python 数据结构转换为电子表单。

openpyxl – 一个用来读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件的库。

python-docx – 读取,查询以及修改 Microsoft Word 2007/2008 docx 文件。

unoconv – 在 LibreOffice/OpenOffice 支持的任意文件格式之间进行转换。

XlsxWriter – 一个用于创建 Excel .xlsx 文件的 Python 模块。

xlwings – 一个使得在 Excel 中方便调用 Python 的库(反之亦然),基于 BSD 协议。

xlwt / xlrd – 读写 Excel 文件的数据和格式信息。

relatorio – 模板化OpenDocument 文件。

  • PDF

PDFMiner – 一个用于从PDF文档中抽取信息的工具。

PyPDF2 – 一个可以分割,合并和转换 PDF 页面的库。

ReportLab – 快速创建富文本 PDF 文档。

  • Markdown

Mistune – 快速并且功能齐全的纯 Python 实现的 Markdown 解析器。

Python-Markdown – John Gruber’s Markdown 的 Python 版实现。

  • YAML

PyYAML – Python 版本的 YAML 解析器。

  • CSV

csvkit – 用于转换和操作 CSV 的工具。

  • Archive

unp – 一个用来方便解包归档文件的命令行工具。

自然语言处理

用来处理人类语言的库。

  • NLTK – 一个先进的平台,用以构建处理人类语言数据的 Python 程序。
  • jieba – 中文分词工具。
  • langid.py – 独立的语言识别系统。
  • Pattern – Python 网络信息挖掘模块。
  • SnowNLP – 一个用来处理中文文本的库。
  • TextBlob – 为进行普通自然语言处理任务提供一致的 API。
  • TextGrocery – 一简单高效的短文本分类工具,基于 LibLinear 和 Jieba。

文档

用以生成项目文档的库。

  • Sphinx – Python 文档生成器。

awesome-sphinxdoc

  • MkDocs – 对 Markdown 友好的文档生成器。
  • pdoc – 一个可以替换Epydoc 的库,可以自动生成 Python 库的 API 文档。
  • Pycco – 文学编程(literate-programming)风格的文档生成器。

配置

用来保存和解析配置的库。

  • config – logging 模块作者写的分级配置模块。
  • ConfigObj – INI 文件解析器,带验证功能。
  • ConfigParser – (Python 标准库) INI 文件解析器。
  • profig – 通过多种格式进行配置,具有数值转换功能。
  • python-decouple – 将设置和代码完全隔离。

命令行工具

用于创建命令行程序的库。

  • 命令行程序开发

cement – Python 的命令行程序框架。

click – 一个通过组合的方式来创建精美命令行界面的包。

cliff – 一个用于创建命令行程序的框架,可以创建具有多层命令的命令行程序。

clint – Python 命令行程序工具。

colorama – 跨平台彩色终端文本。

docopt – Python 风格的命令行参数解析器。

Gooey – 一条命令,将命令行程序变成一个 GUI 程序。

python-prompt-toolkit – 一个用于构建强大的交互式命令行程序的库。

  • 生产力工具

aws-cli – Amazon Web Services 的通用命令行界面。

bashplotlib – 在终端中进行基本绘图。

caniusepython3 – 判断是哪个项目妨碍你你移植到 Python 3。

cookiecutter – 从 cookiecutters(项目模板)创建项目的一个命令行工具。

doitlive – 一个用来在终端中进行现场演示的工具。

howdoi – 通过命令行获取即时的编程问题解答。

httpie – 一个命令行HTTP 客户端,cURL 的替代品,易用性更好。

PathPicker – 从bash输出中选出文件。

percol – 向UNIX shell 传统管道概念中加入交互式选择功能。

SAWS – 一个加强版的 AWS 命令行。

thefuck – 修正你之前的命令行指令。

mycli – 一个 MySQL 命令行客户端,具有自动补全和语法高亮功能。

pgcli – Postgres 命令行工具,具有自动补全和语法高亮功能。

下载器

用来进行下载的库.

  • s3cmd – 一个用来管理Amazon S3 和 CloudFront 的命令行工具。
  • s4cmd – 超级 S3 命令行工具,性能更加强劲。
  • you-get – 一个 YouTube/Youku/Niconico 视频下载器,使用 Python3 编写。
  • youtube-dl – 一个小巧的命令行程序,用来下载 YouTube 视频。

图像处理

用来操作图像的库.

  • pillow – Pillow 是一个更加易用版的 PIL。
  • hmap – 图像直方图映射。
  • imgSeek – 一个使用视觉相似性搜索一组图片集合的项目。
  • nude.py – 裸体检测。
  • pyBarcode – 不借助 PIL 库在 Python 程序中生成条形码。
  • pygram – 类似 Instagram 的图像滤镜。
  • python-qrcode – 一个纯 Python 实现的二维码生成器。
  • Quads – 基于四叉树的计算机艺术。
  • scikit-image – 一个用于(科学)图像处理的 Python 库。
  • thumbor – 一个小型图像服务,具有剪裁,尺寸重设和翻转功能。
  • wand – MagickWand的Python 绑定。MagickWand 是 ImageMagick的 C API 。

OCR

光学字符识别库。

  • pyocr – Tesseract 和 Cuneiform 的一个封装(wrapper)。
  • pytesseract – Google Tesseract OCR 的另一个封装(wrapper)。
  • python-tesseract – Google Tesseract OCR 的一个包装类。

音频

用来操作音频的库

  • audiolazy -Python 的数字信号处理包。
  • audioread – 交叉库 (GStreamer + Core Audio + MAD + FFmpeg) 音频解码。
  • beets – 一个音乐库管理工具及 MusicBrainz 标签添加工具
  • dejavu – 音频指纹提取和识别
  • django-elastic-transcoder – Django + Amazon Elastic Transcoder。
  • eyeD3 – 一个用来操作音频文件的工具,具体来讲就是包含 ID3 元信息的 MP3 文件。
  • id3reader – 一个用来读取 MP3 元数据的 Python 模块。
  • m3u8 – 一个用来解析 m3u8 文件的模块。
  • mutagen – 一个用来处理音频元数据的 Python 模块。
  • pydub – 通过简单、简洁的高层接口来操作音频文件。
  • pyechonest – Echo Nest API 的 Python 客户端
  • talkbox – 一个用来处理演讲/信号的 Python 库
  • TimeSide – 开源 web 音频处理框架。
  • tinytag – 一个用来读取MP3, OGG, FLAC 以及 Wave 文件音乐元数据的库。
  • mingus – 一个高级音乐理论和曲谱包,支持 MIDI 文件和回放功能。

Video

用来操作视频和GIF的库。

  • moviepy – 一个用来进行基于脚本的视频编辑模块,适用于多种格式,包括动图 GIFs。
  • scikit-video – SciPy 视频处理常用程序。

地理位置

地理编码地址以及用来处理经纬度的库。

  • GeoDjango – 世界级地理图形 web 框架。
  • GeoIP – MaxMind GeoIP Legacy 数据库的 Python API。
  • geojson – GeoJSON 的 Python 绑定及工具。
  • geopy – Python 地址编码工具箱。
  • pygeoip – 纯 Python GeoIP API。
  • django-countries – 一个 Django 应用程序,提供用于表格的国家选择功能,国旗图标静态文件以及模型中的国家字段。

HTTP

使用HTTP的库。

  • requests – 人性化的HTTP请求库。
  • grequests – requests 库 + gevent ,用于异步 HTTP 请求.
  • httplib2 – 全面的 HTTP 客户端库。
  • treq – 类似 requests 的Python API 构建于 Twisted HTTP 客户端之上。
  • urllib3 – 一个具有线程安全连接池,支持文件 post,清晰友好的 HTTP 库。

数据库

Python实现的数据库。

  • pickleDB – 一个简单,轻量级键值储存数据库。
  • PipelineDB – 流式 SQL 数据库。
  • TinyDB – 一个微型的,面向文档型数据库。
  • ZODB – 一个 Python 原生对象数据库。一个键值和对象图数据库。

数据库驱动

用来连接和操作数据库的库。

  • MySQL – awesome-mysql系列

mysql-python – Python 的 MySQL 数据库连接器。

mysqlclient – mysql-python 分支,支持 Python 3。

oursql – 一个更好的 MySQL 连接器,支持原生预编译指令和 BLOBs.

PyMySQL – 纯 Python MySQL 驱动,兼容 mysql-python。

  • PostgreSQL

psycopg2 – Python 中最流行的 PostgreSQL 适配器。

queries – psycopg2 库的封装,用来和 PostgreSQL 进行交互。

txpostgres – 基于 Twisted 的异步 PostgreSQL 驱动。

  • 其他关系型数据库

apsw – 另一个 Python SQLite封装。

dataset – 在数据库中存储Python字典 – 可以协同SQLite,MySQL,和 PostgreSQL工作。

pymssql– 一个简单的Microsoft SQL Server数据库接口。

  • NoSQL 数据库

cassandra-python-driver – Cassandra 的 Python 驱动。

HappyBase – 一个为 Apache HBase 设计的,对开发者友好的库。

Plyvel – 一个快速且功能丰富的 LevelDB 的 Python 接口。

py2neo – Neo4j restful 接口的Python 封装客户端。

pycassa – Cassandra 的 Python Thrift 驱动。

PyMongo – MongoDB 的官方 Python 客户端。

redis-py – Redis 的 Python 客户端。

telephus – 基于 Twisted 的 Cassandra 客户端。

txRedis – 基于 Twisted 的 Redis 客户端。

ORM

实现对象关系映射或数据映射技术的库。

  • 关系型数据库

Django Models – Django 的一部分。

SQLAlchemy – Python SQL 工具以及对象关系映射工具。

awesome-sqlalchemy系列

Peewee – 一个小巧,富有表达力的 ORM。

PonyORM – 提供面向生成器的 SQL 接口的 ORM。

python-sql – 编写 Python 风格的 SQL 查询。

  • NoSQL 数据库

django-mongodb-engine – Django MongoDB 后端。

PynamoDB – Amazon DynamoDB 的一个 Python 风格接口。

flywheel – Amazon DynamoDB 的对象映射工具。

MongoEngine – 一个Python 对象文档映射工具,用于 MongoDB。

hot-redis – 为 Redis 提供 Python 丰富的数据类型。

redisco – 一个 Python 库,提供可以持续存在在 Redis 中的简单模型和容器。

  • 其他

butterdb – Google Drive 电子表格的 Python ORM。

Web 框架

全栈 web 框架。

  • Django – Python 界最流行的 web 框架。

awesome-django系列

  • Flask – 一个 Python 微型框架。

awesome-flask系列

  • Pyramid – 一个小巧,快速,接地气的开源Python web 框架。

awesome-pyramid系列

  • Bottle – 一个快速小巧,轻量级的 WSGI 微型 web 框架。
  • CherryPy – 一个极简的 Python web 框架,服从 HTTP/1.1 协议且具有WSGI 线程池。
  • TurboGears – 一个可以扩展为全栈解决方案的微型框架。
  • web.py – 一个 Python 的 web 框架,既简单,又强大。
  • web2py – 一个全栈 web 框架和平台,专注于简单易用。
  • Tornado – 一个web 框架和异步网络库。

权限

允许或拒绝用户访问数据或功能的库。

  • Carteblanche – Module to align code with thoughts of users and designers. Also magically handles navigation and permissions.
  • django-guardian – Django 1.2+ 实现了单个对象权限。
  • django-rules – 一个小巧但是强大的应用,提供对象级别的权限管理,且不需要使用数据库。

CMS

内容管理系统

  • django-cms – 一个开源的,企业级 CMS,基于 Django。
  • djedi-cms – 一个轻量级但却非常强大的 Django CMS ,考虑到了插件,内联编辑以及性能。
  • FeinCMS – 基于 Django 构建的最先进的内容管理系统之一。
  • Kotti – 一个高级的,Python 范的 web 应用框架,基于 Pyramid 构建。
  • Mezzanine – 一个强大的,持续的,灵活的内容管理平台。
  • Opps – 一个为杂志,报纸网站以及大流量门户网站设计的 CMS 平台,基于 Django。
  • Plone – 一个构建于开源应用服务器 Zope 之上的 CMS。
  • Quokka – 灵活,可扩展的小型 CMS,基于 Flask 和 MongoDB。
  • Wagtail – 一个 Django 内容管理系统。
  • Widgy – 最新的 CMS 框架,基于 Django。

电子商务

用于电子商务以及支付的框架和库。

  • django-oscar – 一个用于 Django 的开源的电子商务框架。
  • django-shop – 一个基于 Django 的店铺系统。
  • Cartridge – 一个基于 Mezzanine 构建的购物车应用。
  • shoop – 一个基于 Django 的开源电子商务平台。
  • alipay – 非官方的 Python 支付宝 API。
  • merchant – 一个可以接收来自多种支付平台支付的 Django 应用。
  • money – 货币类库with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.
  • python-currencies – 显示货币格式以及它的数值。

RESTful API

用来开发RESTful APIs的库

  • Django

django-rest-framework – 一个强大灵活的工具,用来构建 web API。

django-tastypie – 为Django 应用开发API。

django-formapi – 为 Django 的表单验证,创建 JSON APIs 。

  • Flask

flask-api – 为 flask 开发的,可浏览 Web APIs 。

flask-restful – 为 flask 快速创建REST APIs 。

flask-restless – 为 SQLAlchemy 定义的数据库模型创建 RESTful APIs 。

flask-api-utils – 为 Flask 处理 API 表示和验证。

eve – REST API 框架,由 Flask, MongoDB 等驱动。

  • Pyramid

cornice – 一个Pyramid 的 REST 框架 。

  • 与框架无关的

falcon – 一个用来建立云 API 和 web app 后端的噶性能框架。

sandman – 为现存的数据库驱动系统自动创建 REST APIs 。

restless – 框架无关的 REST 框架 ,基于从 Tastypie 学到的知识。

ripozo – 快速创建 REST/HATEOAS/Hypermedia APIs。

验证

实现验证方案的库。

  • OAuth

Authomatic – 简单但是强大的框架,身份验证/授权客户端。

django-allauth – Django 的验证应用。

django-oauth-toolkit – 为 Django 用户准备的 OAuth2。

django-oauth2-provider – 为 Django 应用提供 OAuth2 接入。

Flask-OAuthlib – OAuth 1.0/a, 2.0 客户端实现,供 Flask 使用。

OAuthLib – 一个 OAuth 请求-签名逻辑通用、 完整的实现。

python-oauth2 – 一个完全测试的抽象接口。用来创建 OAuth 客户端和服务端。

python-social-auth – 一个设置简单的社会化验证方式。

rauth – OAuth 1.0/a, 2.0, 和 Ofly 的 Python 库。

sanction – 一个超级简单的OAuth2 客户端实现。

  • 其他

jose – JavaScript 对象签名和加密草案的实现。

PyJWT – JSON Web 令牌草案 01。

python-jws – JSON Web 签名草案 02 的实现。

python-jwt – 一个用来生成和验证 JSON Web 令牌的模块。

模板引擎

模板生成和词法解析的库和工具。

  • Jinja2 – 一个现代的,对设计师友好的模板引擎。
  • Chameleon – 一个 HTML/XML 模板引擎。 模仿了 ZPT(Zope Page Templates), 进行了速度上的优化。
  • Genshi – Python 模板工具,用以生成 web 感知的结果。
  • Mako – Python 平台的超高速轻量级模板。

Queue

处理事件以及任务队列的库。

  • celery – 一个异步任务队列/作业队列,基于分布式消息传递。
  • huey – 小型多线程任务队列。
  • mrq – Mr. Queue -一个 Python 的分布式 worker 任务队列, 使用 Redis 和 gevent。
  • rq – 简单的 Python 作业队列。
  • simpleq – 一个简单的,可无限扩张的,基于亚马逊 SQS 的队列。

搜索

对数据进行索引和执行搜索查询的库和软件。

  • django-haystack – Django 模块化搜索。
  • elasticsearch-py – Elasticsearch 的官方底层 Python 客户端。
  • elasticsearch-dsl-py -Elasticsearch 的官方高级 Python 客户端。
  • solrpy – solr的 Python 客户端。
  • Whoosh – 一个快速的纯 Python 搜索引擎库。

动态消息

用来创建用户活动的库。

  • django-activity-stream – 从你的站点行为中生成通用活动信息流。
  • Stream-Framework – 使用 Cassandra 和 Redis 创建动态消息和通知系统。

资源管理

管理、压缩、缩小网站资源的工具。

  • django-compressor – 将链接和内联的 JavaScript 或 CSS 压缩到一个单独的缓存文件中。
  • django-storages – 一个针对 Django 的自定义存储后端的工具集合。
  • fanstatic – 打包、优化,并且把静态文件依赖作为 Python 的包来提供。
  • File Conveyor – 一个后台驻留的程序,用来发现和同步文件到 CDNs, S3 和 FTP。
  • Flask-Assets – 帮你将 web 资源整合到你的 Flask app 中。
  • jinja-assets-compressor – 一个 Jinja 扩展,用来编译和压缩你的资源。
  • webassets – 为你的静态资源打包、优化和管理生成独一无二的缓存 URL。

电子邮件

用来发送和解析电子邮件的库。

  • django-celery-ses – 带有 AWS SES 和 Celery 的 Django email 后端。
  • envelopes – 供人类使用的电子邮件库。
  • flanker – 一个 email 地址和 Mime 解析库。
  • imbox – Python IMAP 库
  • inbox.py – Python SMTP 服务器。
  • inbox – 一个开源电子邮件工具箱。
  • lamson – Python 风格的 SMTP 应用服务器。
  • mailjet – Mailjet API 实现,用来提供批量发送邮件,统计等功能。
  • marrow.mailer – 高性能可扩展邮件分发框架。
  • modoboa – 一个邮件托管和管理平台,具有现代的、简约的 Web UI。
  • pyzmail – 创建,发送和解析电子邮件。
  • Talon – Mailgun 库,用来抽取信息和签名。

URL处理

解析URLs的库

  • furl – 一个让处理 URL 更简单小型 Python 库。
  • purl – 一个简单的,不可变的URL类,具有简洁的 API 来进行询问和处理。
  • pyshorteners – 一个纯 Python URL 缩短库。
  • shorturl– 生成短小 URL 和类似 bit.ly 短链的Python 实现。
  • webargs – 一个解析 HTTP 请求参数的库,内置对流行 web 框架的支持,包括 Flask, Django, Bottle, Tornado和 Pyramid。

HTML处理

处理 HTML和XML的库。

  • BeautifulSoup – 以 Python 风格的方式来对 HTML 或 XML 进行迭代,搜索和修改。
  • bleach – 一个基于白名单的 HTML 清理和文本链接库。
  • cssutils – 一个 Python 的 CSS 库。
  • html5lib – 一个兼容标准的 HTML 文档和片段解析及序列化库。
  • lxml – 一个非常快速,简单易用,功能齐全的库,用来处理 HTML 和 XML。
  • MarkupSafe – 为Python 实现 XML/HTML/XHTML 标记安全字符串。
  • pyquery – 一个解析 HTML 的库,类似 jQuery。
  • untangle – 将XML文档转换为Python对象,使其可以方便的访问。
  • xhtml2pdf – HTML/CSS 转 PDF 工具。
  • xmltodict – 像处理 JSON 一样处理 XML。

网络站点爬取

爬取网络站点的库

  • Scrapy – 一个快速高级的屏幕爬取及网页采集框架。
  • cola – 一个分布式爬虫框架。
  • Demiurge – 基于PyQuery 的爬虫微型框架。
  • feedparser – 通用 feed 解析器。
  • Grab – 站点爬取框架。
  • MechanicalSoup – 用于自动和网络站点交互的 Python 库。
  • portia – Scrapy 可视化爬取。
  • pyspider – 一个强大的爬虫系统。
  • RoboBrowser – 一个简单的,Python 风格的库,用来浏览网站,而不需要一个独立安装的浏览器。

网页内容提取

用于进行网页内容提取的库。

  • Haul – 一个可以扩展的图像爬取工具。
  • html2text – 将 HTML 转换为 Markdown 格式文本
  • lassie – 人性化的网页内容检索库。
  • micawber -一个小型网页内容提取库,用来从 URLs 提取富内容。
  • newspaper – 使用 Python 进行新闻提取,文章提取以及内容策展。
  • opengraph – 一个用来解析开放内容协议(Open Graph Protocol)的 Python模块。
  • python-goose – HTML内容/文章提取器。
  • python-readability– arc90 公司 readability 工具的 Python 高速端口
  • sanitize – 为杂乱的数据世界带来调理性。
  • sumy – 一个为文本文件和 HTML 页面进行自动摘要的模块。
  • textract – 从任何格式的文档中提取文本,Word,PowerPoint,PDFs 等等。

表单

进行表单操作的库。

  • Deform – Python HTML 表单生成库,受到了 formish 表单生成库的启发。
  • django-bootstrap3– 集成了 Bootstrap 3 的 Django。
  • django-crispy-forms – 一个 Django 应用,他可以让你以一种非常优雅且 DRY(Don’t repeat yourself) 的方式来创建美观的表单。
  • django-remote-forms– 一个平台独立的 Django 表单序列化工具。
  • WTForms – 一个灵活的表单验证和呈现库。
  • WTForms-JSON– 一个 WTForms 扩展,用来处理 JSON 数据。

数据验证

数据验证库。多用于表单验证。

  • Cerberus – A mappings-validator with a variety of rules, normalization-features and simple customization that uses a pythonic schema-definition.
  • colander – 一个用于对从 XML, JSON,HTML 表单获取的数据或其他同样简单的序列化数据进行验证和反序列化的系统。
  • kmatch – 一种用于匹配/验证/筛选 Python 字典的语言。
  • schema -一个用于对 Python 数据结构进行验证的库。
  • Schematics – 数据结构验证。
  • valideer – 轻量级可扩展的数据验证和适配库。
  • voluptuous – 一个 Python 数据验证库。主要是为了验证传入 Python的 JSON,YAML 等数据。

静态站点生成器

静态站点生成器是一个软件,它把文本和模板作为输入,然后输出HTML文件。

  • Pelican – 使用 Markdown 或 ReST 来处理内容, Jinja 2 来制作主题。支持 DVCS, Disqus.。AGPL 许可。
  • Cactus – 为设计师设计的静态站点生成器。
  • Hyde – 基于 Jinja2 的静态站点生成器。
  • Nikola – 一个静态网站和博客生成器。
  • Tinkerer – Tinkerer 是一个博客引擎/静态站点生成器,由Sphinx驱动。
  • Lektor – 一个简单易用的静态 CMS 和博客引擎。

更多资源

  • 由于资源过多,导致字数超过微信限制了;
  • 微信图文不支持超链接,前面提到的各资源,无法查看详情;
  • 大家点击「阅读原文」,可查看 python 大全完整版,并且查看本文提到的各资源。http://python.jobbole.com/84464/

伯乐在线已在 GitHub 上发起「Python 资源大全中文版」的整理。欢迎扩散、欢迎加入。 https://github.com/jobbole/awesome-python-cn

译者简介点击 → 加入专栏作者 )


艾凌风:尚未入职小码农;翻译组的勤务员;C/Python/在线教育/英文翻译

iOS开发经验总结(上)

来源:蝴蝶之梦天使

链接:http://www.jianshu.com/p/d333cf6ae4b0

在iOS开发中经常需要使用的或不常用的知识点的总结,几年的收藏和积累(踩过的坑)。

一、 iPhone Size

手机型号 屏幕尺寸
iPhone 4 4s 320 * 480
iPhone 5 5s 320 * 568
iPhone 6 6s 375 * 667
iphone 6 plus 6s plus 414 * 736

二、 给navigation Bar 设置 title 颜色

UIColor *whiteColor = [UIColor whiteColor];

NSDictionary *dic = [NSDictionary dictionaryWithObject:whiteColor forKey:NSForegroundColorAttributeName];

[self.navigationController.navigationBar setTitleTextAttributes:dic];

三、 如何把一个CGPoint存入数组里

CGPoint  itemSprite1position = CGPointMake(100, 200);

NSMutableArray * array  = [[NSMutableArray alloc] initWithObjects:NSStringFromCGPoint(itemSprite1position),nil];

    //    从数组中取值的过程是这样的:  

CGPoint point = CGPointFromString([array objectAtIndex:0]);

 

NSLog(@“point is %@.”, NSStringFromCGPoint(point));

谢谢@bigParis的建议,可以用NSValue进行基础数据的保存,用这个方法更加清晰明确。

CGPoint  itemSprite1position = CGPointMake(100, 200);

NSValue *originValue = [NSValue valueWithCGPoint:itemSprite1position];

NSMutableArray * array  = [[NSMutableArray alloc] initWithObjects:originValue, nil];

//    从数组中取值的过程是这样的:

NSValue *currentValue = [array objectAtIndex:0];

CGPoint point = [currentValue CGPointValue];

 

NSLog(@“point is %@.”, NSStringFromCGPoint(point));

现在Xcode7后OC支持泛型了,可以用NSMutableArray *array来保存。

四、 UIColor 获取 RGB 值

UIColor *color = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];

const CGFloat *components = CGColorGetComponents(color.CGColor);

NSLog(@“Red: %f”, components[0]);

NSLog(@“Green: %f”, components[1]);

NSLog(@“Blue: %f”, components[2]);

NSLog(@“Alpha: %f”, components[3]);

五、 修改textField的placeholder的字体颜色、大小

self.textField.placeholder = @“username is in here!”;

[self.textField setValue:[UIColor redColor] forKeyPath:@“_placeholderLabel.textColor”];

[self.textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@“_placeholderLabel.font”];

六、两点之间的距离

static __inline__ CGFloat CGPointDistanceBetweenTwoPoints(CGPoint point1, CGPoint point2) { CGFloat dx = point2.xpoint1.x; CGFloat dy = point2.ypoint1.y; return sqrt(dx*dx + dy*dy);}

七、IOS开发-关闭/收起键盘方法总结

1、点击Return按扭时收起键盘

(BOOL)textFieldShouldReturn:(UITextField *)textField

{

    return [textField resignFirstResponder];

}

2、点击背景View收起键盘(你的View必须是继承于UIControl)

[self.view endEditing:YES];

3、你可以在任何地方加上这句话,可以用来统一收起键盘

[[[UIApplication sharedApplication] keyWindow] endEditing:YES];

八、在使用 ImagesQA.xcassets 时需要注意

将图片直接拖入image到ImagesQA.xcassets中时,图片的名字会保留。

这个时候如果图片的名字过长,那么这个名字会存入到ImagesQA.xcassets中,名字过长会引起SourceTree判断异常。

九、UIPickerView 判断开始选择到选择结束

开始选择的,需要在继承UiPickerView,创建一个子类,在子类中重载

(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event

当[super hitTest:point withEvent:event]返回不是nil的时候,说明是点击中UIPickerView中了。

结束选择的, 实现UIPickerView的delegate方法

(void)pickerView:(UIPickerView*)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

当调用这个方法的时候,说明选择已经结束了。

十、iOS模拟器 键盘事件

当iOS模拟器 选择了Keybaord->Connect Hardware keyboard 后,不弹出键盘。


当代码中添加了

[[NSNotificationCenter defaultCenter] addObserver:self

                                             selector:@selector(keyboardWillHide)

                                                 name:UIKeyboardWillHideNotification

                                               object:nil];

进行键盘事件的获取。那么在此情景下将不会调用- (void)keyboardWillHide.

因为没有键盘的隐藏和显示。

十一、在ios7上使用size classes后上面下面黑色

使用了size classes后,在ios7的模拟器上出现了上面和下面部分的黑色

可以在General->App Icons and Launch Images->Launch Images Source中设置Images.xcassets来解决。

十二、设置不同size在size classes

Font中设置不同的size classes。

十三、线程中更新 UILabel的text

[self.label1 performSelectorOnMainThread:@selector(setText:)                                      withObject:textDisplay

                                   waitUntilDone:YES];

abel1 为UILabel,当在子线程中,需要进行text的更新的时候,可以使用这个方法来更新。

其他的UIView 也都是一样的。

十四、使用UIScrollViewKeyboardDismissMode实现了Message app的行为

像Messages app一样在滚动的时候可以让键盘消失是一种非常好的体验。然而,将这种行为整合到你的app很难。幸运的是,苹果给UIScrollView添加了一个很好用的属性keyboardDismissMode,这样可以方便很多。

现在仅仅只需要在Storyboard中改变一个简单的属性,或者增加一行代码,你的app可以和办到和Messages app一样的事情了。

这个属性使用了新的UIScrollViewKeyboardDismissMode enum枚举类型。这个enum枚举类型可能的值如下:

typedef NS_ENUM(NSInteger, UIScrollViewKeyboardDismissMode) {

    UIScrollViewKeyboardDismissModeNone,

    UIScrollViewKeyboardDismissModeOnDrag,      // dismisses the keyboard when a drag begins

    UIScrollViewKeyboardDismissModeInteractive, // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss

} NS_ENUM_AVAILABLE_IOS(7_0);

以下是让键盘可以在滚动的时候消失需要设置的属性:

十五、报错 “_sqlite3_bind_blob”, referenced from:

将 sqlite3.dylib加载到framework

十六、ios7 statusbar 文字颜色

iOS7上,默认status bar字体颜色是黑色的,要修改为白色的需要在infoPlist里设置UIViewControllerBasedStatusBarAppearance为NO,然后在代码里添加:

[application setStatusBarStyle:UIStatusBarStyleLightContent];

十七、获得当前硬盘空间

NSFileManager *fm = [NSFileManager defaultManager];

    NSDictionary *fattributes = [fm attributesOfFileSystemForPath:NSHomeDirectory() error:nil];

 

    NSLog(@“容量%lldG”,[[fattributes objectForKey:NSFileSystemSize] longLongValue]/1000000000);

    NSLog(@“可用%lldG”,[[fattributes objectForKey:NSFileSystemFreeSize] longLongValue]/1000000000);

十八、给UIView 设置透明度,不影响其他sub views

UIView设置了alpha值,但其中的内容也跟着变透明。有没有解决办法?

设置background color的颜色中的透明度

比如:

[self.testView setBackgroundColor:[UIColor colorWithRed:0.0 green:1.0 blue:1.0 alpha:0.5]];

设置了color的alpha, 就可以实现背景色有透明度,当其他sub views不受影响给color 添加 alpha,或修改alpha的值。

// Returns a color in the same color space as the receiver with the specified alpha component.

(UIColor *)colorWithAlphaComponent:(CGFloat)alpha;

// eg.

[view.backgroundColor colorWithAlphaComponent:0.5];

十九、将color转为UIImage

//将color转为UIImage

(UIImage *)createImageWithColor:(UIColor *)color

{

    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);

    UIGraphicsBeginImageContext(rect.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);

    CGContextFillRect(context, rect);

    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

 

    return theImage;

}

二十、NSTimer 用法

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

 

    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

在NSRunLoop 中添加定时器.

二十一、Bundle identifier 应用标示符

Bundle identifier 是应用的标示符,表明应用和其他APP的区别。

二十二、NSDate 获取几年前的时间

eg. 获取到40年前的日期

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *dateComponents = [[NSDateComponents alloc] init];

[dateComponents setYear:-40];

self.birthDate = [gregorian dateByAddingComponents:dateComponents toDate:[NSDate date] options:0];

二十三、iOS加载启动图的时候隐藏statusbar

只需需要在info.plist中加入Status bar is initially hidden 设置为YES就好

二十四、iOS 开发,工程中混合使用 ARC 和非ARC

Xcode 项目中我们可以使用 ARC 和非 ARC 的混合模式。

如果你的项目使用的非 ARC 模式,则为 ARC 模式的代码文件加入 -fobjc-arc 标签。

如果你的项目使用的是 ARC 模式,则为非 ARC 模式的代码文件加入 -fno-objc-arc 标签。

添加标签的方法:

  • 打开:你的target -> Build Phases -> Compile Sources.
  • 双击对应的 *.m 文件
  • 在弹出窗口中输入上面提到的标签 -fobjc-arc / -fno-objc-arc
  • 点击 done 保存

二十五、iOS7 中 boundingRectWithSize:options:attributes:context:计算文本尺寸的使用

之前使用了NSString类的sizeWithFont:constrainedToSize:lineBreakMode:方法,但是该方法已经被iOS7 Deprecated了,而iOS7新出了一个boudingRectWithSize:options:attributes:context方法来代替。

而具体怎么使用呢,尤其那个attribute

NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:13]};

CGSize size = [@“相关NSString” boundingRectWithSize:CGSizeMake(100, 0) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attribute context:nil].size;

二十六、NSDate使用 注意

NSDate 在保存数据,传输数据中,一般最好使用UTC时间。

在显示到界面给用户看的时候,需要转换为本地时间。

二十七、在UIViewController中property的一个UIViewController的Present问题

如果在一个UIViewController A中有一个property属性为UIViewController B,实例化后,将BVC.view 添加到主UIViewController A.view上,如果在viewB上进行 – (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion NS_AVAILABLE_IOS(5_0);的操作将会出现,“ Presenting view controllers on detached view controllers is discouraged ” 的问题。

以为BVC已经present到AVC中了,所以再一次进行会出现错误。

可以使用

[self.view.window.rootViewController presentViewController:imagePicker

                                                      animated:YES

                                                    completion:^{

                                                        NSLog(@“Finished”);

                                                    }];

来解决。

二十八、UITableViewCell indentationLevel 使用

UITableViewCell 属性 NSInteger indentationLevel 的使用, 对cell设置 indentationLevel的值,可以将cell 分级别。

还有 CGFloat indentationWidth; 属性,设置缩进的宽度。

总缩进的宽度: indentationLevel * indentationWidth

二十九、ActivityViewController 使用AirDrop分享

使用AirDrop 进行分享:

NSArray *array = @[@“test1”, @“test2”];

 

UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:array applicationActivities:nil];

 

[self presentViewController:activityVC animated:YES

                 completion:^{

                     NSLog(@“Air”);

                 }];

就可以弹出界面:

三十、获取CGRect的height

获取CGRect的height, 除了 self.createNewMessageTableView.frame.size.height 这样进行点语法获取。

还可以使用CGRectGetHeight(self.createNewMessageTableView.frame) 进行直接获取。

除了这个方法还有 func CGRectGetWidth(rect: CGRect) -> CGFloat

等等简单地方法

func CGRectGetMinX(rect: CGRect) -> CGFloat

func CGRectGetMidX(rect: CGRect) -> CGFloat

func CGRectGetMaxX(rect: CGRect) -> CGFloat

func CGRectGetMinY(rect: CGRect) -> CGFloat

三十一、打印 %

NSString *printPercentStr = [NSString stringWithFormat:@“%%”];

三十二、在工程中查看是否使用 IDFA

allentekiMac-mini:JiKaTongGit lihuaxie$ grep -r advertisingIdentifier .

grep: ./ios/Framework/AMapSearchKit.framework/Resources: No such file or directory

Binary file ./ios/Framework/MAMapKit.framework/MAMapKit matches

Binary file ./ios/Framework/MAMapKit.framework/Versions/2.4.1.e00ba6a/MAMapKit matches

Binary file ./ios/Framework/MAMapKit.framework/Versions/Current/MAMapKit matches

Binary file ./ios/JiKaTong.xcodeproj/project.xcworkspace/xcuserdata/lihuaxie.xcuserdatad/UserInterfaceState.xcuserstate matches

allentekiMac-mini:JiKaTongGit lihuaxie$

打开终端,到工程目录中, 输入:

grep -r advertisingIdentifier .

可以看到那些文件中用到了IDFA,如果用到了就会被显示出来。

三十三、APP 屏蔽 触发事件

// Disable user interaction when download finishes

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

三十四、设置Status bar颜色

status bar的颜色设置:

如果没有navigation bar, 直接设置 // make status bar background color

self.view.backgroundColor = COLOR_APP_MAIN;

如果有navigation bar, 在navigation bar 添加一个view来设置颜色。// status bar color

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, -20, ScreenWidth, 20)];
[view setBackgroundColor:COLOR_APP_MAIN];

[viewController.navigationController.navigationBar addSubview:view];

三十五、NSDictionary 转 NSString

// Start
NSDictionary *parametersDic = [NSDictionary dictionaryWithObjectsAndKeys:
self.providerStr, KEY_LOGIN_PROVIDER,
token, KEY_TOKEN,
response, KEY_RESPONSE,
nil];

NSData jsonData = parametersDic == nil ? nil : [NSJSONSerialization dataWithJSONObject:parametersDic options:0 error:nil];
NSString 
requestBody = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

将dictionary 转化为 NSData, data 转化为 string .

 

三十六、iOS7 中UIButton setImage 没有起作用

如果在iOS7 中进行设置image 没有生效。

 

那么说明UIButton的 enable 属性没有生效是NO的。 **需要设置enable 为YES。**

 

三十七、User-Agent 判断设备

UIWebView 会根据User-Agent 的值来判断需要显示哪个界面。

如果需要设置为全局,那么直接在应用启动的时候加载。

(void)appendUserAgent

{

NSString oldAgent = [self.WebView stringByEvaluatingJavaScriptFromString:@”navigator.userAgent”];

NSString newAgent = [oldAgent stringByAppendingString:@”iOS”];

NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:

newAgent, @”UserAgent”, nil];

1

newAgent, @”UserAgent”, nil];

[[NSUserDefaults standardUserDefaults] registerDefaults:dic];

}

@“iOS” 为添加的自定义。

三十八、UIPasteboard 屏蔽paste 选项

当UIpasteboard的string 设置为@“” 时,那么string会成为nil。 就不会出现paste的选项。

三十九、class_addMethod 使用

当 ARC 环境下

class_addMethod([self class], @selector(resolveThisMethodDynamically), (IMP) myMethodIMP, “v@:”);

使用的时候@selector 需要使用super的class,不然会报错。

当MRC环境下

class_addMethod([EmptyClass class], @selector(sayHello2), (IMP)sayHello, “v@:”);

可以任意定义。但是系统会出现警告,忽略警告就可以。

WEB请求处理(2):Nginx请求反向代理

陶邦仁

http://blog.jobbole.com/100526/

上一篇《WEB请求处理一:浏览器请求发起处理》,我们讲述了浏览器端请求发起过程,通过DNS域名解析服务器IP,并建立TCP连接,发送HTTP请求。本文讲述请求到达反向代理服务器的一个处理过程,比如:在Nginx中请求的处理流程,请求都是经过了哪些模块,做了哪些处理,又是如何找到应用服务器呢?

为直观明了,先上一张图,红色部分为本章所述模块:

Nginx有五大优点:模块化、事件驱动、异步、非阻塞、多进程单线程。其中,模块化设计类似于面向对象中的接口类,它增强了nginx源码的可读性、可扩充性和可维护性。

Nginx由内核和模块组成的,其中内核完成的工作比较简单,仅仅通过查找配置文件将客户端请求映射到一个location block,然后又将这个location block中所配置的每个指令将会启动不同的模块去完成相应的工作

所以,在讲述Nginx请求处理过程,首先要了解Nginx模块结构与功能,Nginx中有哪些模块,其功能又是如何。

1 Nginx模块

Nginx总共有5大一类模块:core、conf、event、http、mail,和48个二类模块每个模块有属于自己的配置项,由commands字段决定;每个模块在初始化和退出销毁时均有回调函数

多进程模式下的模块初始化主要有四个方面:脚本初始化、静态初始化、动态初始化、进程初始化

脚本初始化是指在安装nginx时,由configure脚本生成的相关文件,比如ngx_modules.c文件包含了nginx的所有模块;

静态初始化在编译时就完成,主要通过定义全局变量实现;

动态初始化在运行时完成,主要通过master进程main函数,ngx_init_cycle函数,及各模块文件内定义的init函数实现;

进程初始化是指各worker进程执行init_process函数。当nginx退出或重读配置文件或nginx平滑升级时,worker进程会调用各模块的exit_process函数来销毁资源。

开发人员可以根据nginx模块规则注册自己的模块,添加模块后要重新编译源码,并且修改nginx.conf配置文件才能使新模块生效。

1.1 四种角色模块

Nginx模块主要有4种角色:

(1) core(核心模块):构建nginx基础服务、管理其他模块;

(2) handlers(处理模块):用于处理HTTP请求,然后产生输出。

(3) filters(过滤模块):过滤handler产生的输出。

(4) load-balancers(负载均衡模块):当有多于一台的后端备选服务器时,选择一台转发HTTP请求。

Nginx的核心模块主要负责建立nginx服务模型、管理网络层和应用层协议、以及启动针对特定应用的一系列候选模块。其他模块负责分配给web服务器的实际工作:

(1) 当Nginx发送文件或者转发请求到其他服务器,由handlers(处理模块)或load-balancers(负载均衡模块)提供服务;

(2) 当需要Nginx把输出压缩或者在服务端加一些东西,由filters(过滤模块)提供服务。

1.2 模块结构设计

点击查看大图

点击查看大图

 

1.3 模块数据结构

  1. 核心:ngx_module_t(nginx所有模块的数据结构模板)
  2. 配置文件指令:ngx_command_t(主要负责模块与配置文件nginx.conf的交互)
  3. 指令配置:ngx_conf_t(解析某个具体的指令)
  4. 全局配置:ngx_cycle_t(nginx绝大部分初始化操作都围绕该结构体)

1.4 模块调用流程

  1. 当服务器启动,每个handlers(处理模块)都有机会映射到配置文件中定义的特定位置(location);如果有多个handlers(处理模块)映射到特定位置时,只有一个会“赢”(说明配置文件有冲突项,应该避免发生)。处理模块以三种形式返回:

    OK

    ERROR

    或者放弃处理这个请求而让默认处理模块来处理(主要是用来处理一些静态文件,事实上如果是位置正确而真实的静态文件,默认的处理模块会抢先处理)。

  2. 如果handlers(处理模块)把请求反向代理到后端的服务器,就变成另外一类的模块:load-balancers(负载均衡模块)。负载均衡模块的配置中有一组后端服务器,当一个HTTP请求过来时,它决定哪台服务器应当获得这个请求。Nginx的负载均衡模块采用两种方法:

    轮转法,它处理请求就像纸牌游戏一样从头到尾分发;

    IP哈希法,在众多请求的情况下,它确保来自同一个IP的请求会分发到相同的后端服务器。

  3. 如果handlers(处理模块)没有产生错误,filters(过滤模块)将被调用。多个filters(过滤模块)能映射到每个位置,所以(比如)每个请求都可以被压缩成块。它们的执行顺序在编译时决定。filters(过滤模块)是经典的“接力链表(CHAIN OF RESPONSIBILITY)”模型:一个filters(过滤模块)被调用,完成其工作,然后调用下一个filters(过滤模块),直到最后一个filters(过滤模块)。过滤模块链的特别之处在于:

    每个filters(过滤模块)不会等上一个filters(过滤模块)全部完成;

    它能把前一个过滤模块的输出作为其处理内容;有点像Unix中的流水线。

    过滤模块能以buffer(缓冲区)为单位进行操作,这些buffer一般都是一页(4K)大小,当然你也可以在nginx.conf文件中进行配置。这意味着,比如,模块可以压缩来自后端服务器的响应,然后像流一样的到达客户端,直到整个响应发送完成。

    总之,过滤模块链以流水线的方式高效率地向客户端发送响应信息。

  4. 所以总结下上面的内容,一个典型的HTTP处理周期是这样的:

    客户端发送HTTP请求 –>

    Nginx基于配置文件中的位置选择一个合适的处理模块 ->

    (如果有)负载均衡模块选择一台后端服务器 –>

    处理模块进行处理并把输出缓冲放到第一个过滤模块上 –>

    第一个过滤模块处理后输出给第二个过滤模块 –>

    然后第二个过滤模块又到第三个 –>

    依此类推 –> 最后把响应发给客户端。

    下图展示了nginx模块处理流程:


    点击查看大图

2 Nginx请求处理

Nginx在启动时会以daemon形式在后台运行,采用多进程+异步非阻塞IO事件模型来处理各种连接请求。多进程模型包括一个master进程,多个worker进程,一般worker进程个数是根据服务器CPU核数来决定的master进程负责管理Nginx本身和其他worker进程。如下图:

从上图中可以很明显地看到,4个worker进程的父进程都是master进程,表明worker进程都是从父进程fork出来的,并且父进程的ppid为1,表示其为daemon进程。

需要说明的是,在nginx多进程中,每个worker都是平等的,因此每个进程处理外部请求的机会权重都是一致的。

所有实际上的业务处理逻辑都在worker进程。worker进程中有一个ngx_worker_process_cycle()函数,执行无限循环,不断处理收到的来自客户端的请求,并进行处理,直到整个Nginx服务被停止。

worker 进程中,ngx_worker_process_cycle()函数就是这个无限循环的处理函数。在这个函数中,一个请求的简单处理流程如下:

  1. 操作系统提供的机制(例如 epoll, kqueue 等)产生相关的事件。
  2. 接收和处理这些事件,如是接收到数据,则产生更高层的 request 对象。
  3. 处理 request 的 header 和 body。
  4. 产生响应,并发送回客户端。
  5. 完成 request 的处理。
  6. 重新初始化定时器及其他事件。

2.1 多进程处理模型

下面来介绍一个请求进来,多进程模型的处理方式:

首先,master进程一开始就会根据我们的配置,来建立需要listen的网络socket fd,然后fork出多个worker进程。

其次,根据进程的特性,新建立的worker进程,也会和master进程一样,具有相同的设置。因此,其也会去监听相同ip端口的套接字socket fd

然后,这个时候有多个worker进程都在监听同样设置的socket fd,意味着当有一个请求进来的时候,所有的worker都会感知到。这样就会产生所谓的“惊群现象”。为了保证只会有一个进程成功注册到listenfd的读事件,nginx中实现了一个“accept_mutex”类似互斥锁,只有获取到这个锁的进程,才可以去注册读事件。其他进程全部accept 失败。

最后,监听成功的worker进程,读取请求,解析处理,响应数据返回给客户端,断开连接,结束。因此,一个request请求,只需要worker进程就可以完成。

进程模型的处理方式带来的一些好处就是:进程之间是独立的,也就是一个worker进程出现异常退出,其他worker进程是不会受到影响的;此外,独立进程也会避免一些不需要的锁操作,这样子会提高处理效率,并且开发调试也更容易。

如前文所述,多进程模型+异步非阻塞模型才是胜出的方案。单纯的多进程模型会导致连接并发数量的降低,而采用异步非阻塞IO模型很好的解决了这个问题;并且还因此避免的多线程的上下文切换导致的性能损失。

worker进程会竞争监听客户端的连接请求:这种方式可能会带来一个问题,就是可能所有的请求都被一个worker进程给竞争获取了,导致其他进程都比较空闲,而某一个进程会处于忙碌的状态,这种状态可能还会导致无法及时响应连接而丢弃discard掉本有能力处理的请求。这种不公平的现象,是需要避免的,尤其是在高可靠web服务器环境下。

针对这种现象,Nginx采用了一个是否打开accept_mutex选项的值,ngx_accept_disabled标识控制一个worker进程是否需要去竞争获取accept_mutex选项,进而获取accept事件

ngx_accept_disabled值,nginx单进程的所有连接总数的八分之一,减去剩下的空闲连接数量,得到的这个ngx_accept_disabled。

当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,并且将ngx_accept_disabled减 1,于是,每次执行到此处时,都会去减1,直到小于0。不去获取accept_mutex锁,就是等于让出获取连接的机会,很显然可以看出,当空闲连接越少时,ngx_accept_disable越大,于是让出的机会就越多,这样其它进程获取锁的机会也就越大。不去accept,自己的连接就控制下来了,其它进程的连接池就会得到利用,这样,nginx就控制了多进程间连接的平衡了。

2.2 一个简单的HTTP请求

从 Nginx 的内部来看,一个 HTTP Request 的处理过程涉及到以下几个阶段:

初始化 HTTP Request(读取来自客户端的数据,生成 HTTP Request 对象,该对象含有该请求所有的信息)。

处理请求头。

处理请求体。

如果有的话,调用与此请求(URL 或者 Location)关联的 handler。

依次调用各 phase handler 进行处理。

以上步骤,如下图所示:

输入图片说明

在这里,我们需要了解一下 phase handler 这个概念。phase 字面的意思,就是阶段。所以 phase handlers 也就好理解了,就是包含若干个处理阶段的一些 handler

在每一个阶段,包含有若干个 handler,再处理到某个阶段的时候,依次调用该阶段的 handler 对 HTTP Request 进行处理。

通常情况下,一个 phase handler 对这个 request 进行处理,并产生一些输出。通常 phase handler 是与定义在配置文件中的某个 location 相关联的

一个 phase handler 通常执行以下几项任务:

获取 location 配置。

产生适当的响应。

发送 response header。

发送 response body。

当 Nginx 读取到一个 HTTP Request 的 header 的时候,Nginx 首先查找与这个请求关联的虚拟主机的配置。如果找到了这个虚拟主机的配置,那么通常情况下,这个 HTTP Request 将会经过以下几个阶段的处理(phase handlers):

NGX_HTTP_POST_READ_PHASE: 读取请求内容阶段

NGX_HTTP_SERVER_REWRITE_PHASE: Server 请求地址重写阶段

NGX_HTTP_FIND_CONFIG_PHASE: 配置查找阶段

NGX_HTTP_REWRITE_PHASE: Location请求地址重写阶段

NGX_HTTP_POST_REWRITE_PHASE: 请求地址重写提交阶段

NGX_HTTP_PREACCESS_PHASE: 访问权限检查准备阶段

NGX_HTTP_ACCESS_PHASE: 访问权限检查阶段

NGX_HTTP_POST_ACCESS_PHASE: 访问权限检查提交阶段

NGX_HTTP_TRY_FILES_PHASE: 配置项 try_files 处理阶段

NGX_HTTP_CONTENT_PHASE: 内容产生阶段

NGX_HTTP_LOG_PHASE: 日志模块处理阶段

在内容产生阶段,为了给一个 request 产生正确的响应,Nginx 必须把这个 request 交给一个合适的 content handler 去处理。 如果这个 request 对应的 location 在配置文件中被明确指定了一个 content handler,那么Nginx 就可以通过对 location 的匹配,直接找到这个对应的 handler,并把这个 request 交给这个 content handler 去处理。这样的配置指令包括像,perl,flv,proxy_pass,mp4等。

如果一个 request 对应的 location 并没有直接有配置的 content handler,那么 Nginx 依次尝试:

如果一个 location 里面有配置 random_index on,那么随机选择一个文件,发送给客户端。

如果一个 location 里面有配置 index 指令,那么发送 index 指令指明的文件,给客户端。

如果一个 location 里面有配置 autoindex on,那么就发送请求地址对应的服务端路径下的文件列表给客户端。

如果这个 request 对应的 location 上有设置 gzip_static on,那么就查找是否有对应的.gz文件存在,有的话,就发送这个给客户端(客户端支持 gzip 的情况下)。

请求的 URI 如果对应一个静态文件,static module 就发送静态文件的内容到客户端。

内容产生阶段完成以后,生成的输出会被传递到 filter 模块去进行处理。filter 模块也是与 location 相关的。所有的 fiter 模块都被组织成一条链。输出会依次穿越所有的 filter,直到有一个 filter 模块的返回值表明已经处理完成。

这里列举几个常见的 filter 模块,例如:

server-side includes。

XSLT filtering。

图像缩放之类的。

gzip 压缩。

在所有的 filter 中,有几个 filter 模块需要关注一下。按照调用的顺序依次说明如下:

copy: 将一些需要复制的 buf(文件或者内存)重新复制一份然后交给剩余的 body filter 处理。

postpone: 这个 filter 是负责 subrequest 的,也就是子请求的。

write: 写输出到客户端,实际上是写到连接对应的 socket 上。

Java中文乱码解决之道(2): 字符编码详解

来源: chenssy

链接:http://www.cnblogs.com/chenssy/p/4202688.html

在上篇博文(java中文乱码解决之道(一)—–认识字符集)中,LZ简单介绍了主流的字符编码,对各种编码都是点到为止,以下LZ将详细阐述字符集、字符编码等基础知识和ASCII、GB的详情。

一、基础知识

在了解各种字符集之前我们需要了解一些最基础的知识,如:编码、字符、字符集、字符编码基础知识。

编码

计算机中存储的信息都是用二进制表示的,我们在屏幕上所看到文字、图片等都是通过二进制转换的结果。编码是信息从一种形式或格式转换为另一种形式的过程,通俗点讲就是就是将我们看到的文字、图片等信息按照某种规则存储在计算机中,例如‘c’在计算机中怎么表达,‘陈’在计算机中怎么表达,这个过程就称之为编码。解码是编码的逆过程,它是将存储在计算机的二进制转换为我们可以看到的文字、图片等信息,它体现的是视觉上的刺激。

n位二进制数可以组合成2的n次方个不同的信息,给每个信息规定一个具体码组,这种过程也叫编码。

在编码和解码中,他们就如加密、解密一般,他们一定会遵循某个规则,即y  = f(x),那么x = f(y);否则在解密过程就会导致‘a’解析成‘b’或者乱码。

字符

字符是可使用多种不同字符方案或代码页来表示的抽象实体,它是一个单位的字形、类字形单位或符号的基本信息,也是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

字符是指计算机中使用的字母、数字、字和符号,包括:1、2、3、A、B、C、~!·#¥%……—*()——+等等。在 ASCII 编码中,一个英文字母字符存储需要1个字节。在 GB 2312 编码或 GBK 编码中,一个汉字字符存储需要2个字节。在UTF-8编码中,一个英文字母字符存储需要1个字节,一个汉字字符储存需要3到4个字节。在UTF-16编码 中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。在UTF-32编码中,世界上任何字符的存 储都需要4个字节。

2014112600001_thumb4

字符集

字符是各种文字和符号的总称,而字符集则是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同。而计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。

常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

字符编码

计算机中的信息包括数据信息和控制信息,然而不管是那种信息,他们都是以二进制编码的方式存入计算机中,但是他们是怎么展示在屏幕上的呢?同时在展 现过程中如何才能保证他们不出错?这个时候字符编码就起到了重要作用!字符编码是一套规则,一套建立在符合集合与数字系统之间的对应关系之上的规则,它是 信息处理的基本技术。

使用字符编码这套规则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。

2014112600002_thumb1

二、ASCII

2.1、标准ASCII码

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语和其他西欧英语,它是现今最通用的单字节编码系统。

ASCII使用7位或者8位来表示128或者256种可能的字符。标准的ASCII码则是使用7位二进制数来表示所有的大小写字母、数字、标点符合和一些控制字符,其中:

0~31、127(共33个)是控制字符或者通信专用字符,如控制符:LF(换行)、CR(回车)、DEL(删除)等;通信专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等。ASCII值为8、9、10、13分别表示退格、制表、换号、回车字符。

32~126(共95个)字符,32为空格、48~57为阿拉伯数字、65~90为大写字母、97~122为小写字母,其余为一些标点符号和运算符号!

前面提过标准的ASCII码是使用七位来表示字符的,而最高位(b7)则是用作奇偶校验的。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。 (参考百度百科)

下面是ASCII字符对照表,更多详情请关注:》》 ASCII码表 《《

2014112400001_thumb3

2014112400002_thumb

2.2、扩展ASCII码

标准的ASCII是用七位来表示的,那么它的缺陷就非常明显了:只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,基本上只能应用于现代美 国英语,对于其他国家,128个字符肯定不够。于是,这些欧洲国家决定利用字节中闲置的最高位编入新的符号,这样一来,可以表达的字符数最多就为256 个,但是随着产生的问题也就来了:不同的国家有不同的字母,可能同一个编码在不同的国家所表示的字符不同。但是不管怎么样,在这些编码中0~127所表示的字符肯定是一样的,不一样的也只是128~255这一段。

8位的ASCII在欧洲国家表现的不尽人意,那么在其他国家就更加不用说了,我们拥有五千年历史文化的中华名族所包含的汉字多大10多万,不知道是 多少个256。所以一个字节8位表示的256个字符肯定是不够的,那么两个字节呢?可能够了吧!我们常见的汉字就是用两个字节表示的,如GB2312。

2014112600003_thumb

三、GB**

对于欧美国家来说,ASCII能够很好的满足用户的需求,但是当我们中华名族使用计算机时,ASCII明显就不满足需求了,有5000年历史文化的 我们,拥有的汉字达到将近10万,所以为了显示中文,我们必须设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。显示中文的常用字符编码 有:GB2312、GBK、GB18030。

GB2312

GB2312,中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,由中国国家标准总局发布,1981年5月1日实施。

GB2312编码的规则:一个小于127的字符的意义与原来相同,但两个大于127的 字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127 号以下的那些就叫”半角”字符了。

在GB2312中,GB2312共收录6763个汉字,其中一级汉字3755个,二级汉字3008个,还收录了拉丁字母、希腊字母、日文等682个 全角字符。由于GB2312的出现,它基本上解决了我们日常的需要,它所收录的汉子已经覆盖了中国大陆99.75%的使用平率。但是我国文化博大精深,对 于人名、古汉语等方面出现的罕用字,GB2312还是不能处理,于是后面的GBK和GB18030汉字字符集出现了。

GB2312字符集库非常庞大,详情:GB2312简体中文编码表

GBK

GBK,全称《汉字内码扩展规范》,由中华人民共和国全国信息技术标准化技术委员会1995年12月1日制订,也是汉字编码的标准之一。

GBK是GB2312的扩展,他向下与GB2312兼容,,向上支持 ISO 10646.1 国际标准,是前者向后者过渡过程中的一个承上启下的标准。同时它是使用双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),首字节在 81-FE 之间,尾字节在 40-FE 之间,共23940个码位,共收录了21003个汉字。

GB18030

GB18030,国家标准GB18030《信息技术 中文编码字符集》,是我国计算机系统必须遵循的基础性标准之一。它有两个版本:GB18030-2000、GB18030-2005。其中 GB18030-2000仅规定了常用非汉字符号和27533个汉字(包括部首、部件等)的编码,而GB18030-2005是全文强制性标准,市场上销 售的产品必须符合,它是GB18030-2000的基础上增加了42711个汉字和多种我国少数民族文字的编码。

GB18030标准采用单字节、双字节和四字节三种方式对字符编码。(码位总体结构见下图)

单字节部分采用GB/T 11383的编码结构与规则,使用0×00至0×7F码位(对应于ASCII码的相应码位)。双字节部分,首字节码位从0×81至0×FE,尾字节码位分 别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第 一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。

2014112600004_thumb

四、参考文献&进一步阅读

编码:http://baike.baidu.com/subview/237708/11062012.htm(百度百科)

字符:http://baike.baidu.com/view/263416.htm(百度百科)

字符集:http://baike.baidu.com/view/51987.htm(百度百科)

字符编码:http://baike.baidu.com/view/1204863.htm(百度百科)

字符集和字符编码:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html吴秦

ASCII:http://baike.baidu.com/view/15482.htm

GB2312:http://baike.baidu.com/view/443268.htm

GBK:http://baike.baidu.com/view/931619.htm

GB18030:http://baike.baidu.com/view/889058.htm


—–原文出自:http://cmsblogs.com/?p=1412请尊重作者辛勤劳动成果,转载说明出处.

—–个人站点:http://cmsblogs.com

Java中文乱码解决之道(1): 认识字符集

来源: chenssy

链接:http://www.cnblogs.com/chenssy/p/4200277.html

沉寂了许久(大概有三个多月了吧),LZ“按捺不住”开始写博了!

java编码中的中文问题是一个老生常谈的问题了,每次遇到中文乱码LZ要么是按照以前的经验修改,要么则是baidu.com来 解决问题。阅读许多关于中文乱码的解决办法的博文后,发现对于该问题我们都(更加包括我自己)没有一个清晰明了的认识,于是LZ想通过这系列博文(估计只 有几篇)来彻底分析、解决java中文乱码问题,如有错误之处望各位同仁指出!当然,此系列博文并非LZ完全原创,都是在前辈基础上总结,归纳,如果雷同 纯属借鉴……

问题起源

对于计算机而言,它仅认识两个0和1,不管是在内存中还是外部存储设备上,我们所看到的文字、图片、视频等等“数据”在计算机中都是已二进制形式存在的。不同字符对应二进制数的规则,就是字符的编码。字符编码的集合称为字符集。

在早期的计算机系统中,使用的字符是非常少的,他们只包括26个英文字母、数字符号和一些常用符号,对于这些字符进行编码,用1个字节就足够了,但 是随着计算机的不断发展,为了适应全世界其他各国民族的语言,这些少得可怜的字符编码肯定是不够的。于是人们提出了UNICODE编码,它采用双字节编 码,兼容英文字符和其他国家民族的双字节字符编码。

每个国家为了统一编码都会规定该国家/地区计算机信息交换用的字符集编码,为了解决本地字符信息的计算机处理,于是出现了各种本地化版本,引进 LANG, Codepage 等概念。现在大部分具有国际化特征的软件核心字符处理都是以 Unicode 为基础的,在软件运行时根据当时的 Locale/Lang/Codepage 设置确定相应的本地字符编码设置,并依此处理本地字符。在处理过程中需要实现 Unicode 和本地字符集的相互转换。

同然,java内部采用的就是Unicode编码,所以在java运行的过程中就必然存在从Unicode编码与相应的计算机操作系统或者浏览器支持的编码格式相互转化的过程,这个转换的过程有一系列的步骤,如果某个步骤出现错误,则输出的文字就会是乱码。

所以产生java乱码的问题就在于JVM与对应的操作系统/浏览器进行编码格式转换时出现了错误。

其实要解决java乱码问题的方法还是比较简单的,但是要究其原因,理解背后的原理还是需要了解

其实解决 JAVA 程序中的汉字编码问题的方法往往很简单,但理解其背后的原因,定位问题,还需要了解现有的汉字编码和编码转换。

常见字符编码

计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。常见的字符编码主要包括:ASCII编码、GB**编 码、Unicode。下面LZ就简单地介绍下!(为什么是简单介绍?因为LZ在网上查找资料想去了解字符编码时,发现这个问题比我想象的复杂太多了,所以 LZ需要另起一篇详细介绍,所以各位看客就简单看看吧!!)

1.ASCII编码

ASCII,American Standard Code for Information Interchange,是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统。

ASCII码使用指定的7位或者8为二进制数字组合表示128或者256种可能的字符。标准的ASCII编码使用的是7(2^7 = 128)位二进制数来表示所有的大小写字母、数字和标点符号已经一些特殊的控制字符,最前面的一位统一规定为0。其中0~31及127(共33个)是控制 字符或通信专用字符,32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字,65~90为26个大写英文字 母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。

2014112400001

2014112400002

2.GBK***编码

ASCII最大的缺点就是显示字符有限,他虽然解决了部分西欧语言的显示问题,但是对更多的其他语言他实在是无能为了。随着计算机技术的发展,使用 范围越来越广泛了,ASCII的缺陷越来越明显了,其他国家和地区需要使用计算机,必须要设计一套符合本国/本地区的编码规则。例如为了显示中文,我们就 必须要设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。

GB2312,用于汉字处理、 汉字通信等系统之间的信息交换,通行于中国大陆。它的编码规则是:小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉 字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。虽然GB2312收录了这么多汉子,他所覆盖 的使用率可以达到99%,但是对于那些不常见的汉字,例如人名、地名、古汉语,它就不能处理了,于是就有下面的GBK、GB 18030的出现。(点击GB2312简体中文编码表查看)。

GB18030,全 称:国家标准GB 18030-2005《信息技术 中文编码字符集》,是我国计算机系统必须遵循的基础性标准之一,GB18030有两个版本:GB18030-2000和GB18030-2005。 GB18030-2000是GBK的取代版本,它的主要特点是在GBK基础上增加了CJK统一汉字扩充A的汉字。

GB 18030主要有以下特点:

与UTF-8相同,采用多字节编码,每个字可以由1个、2个或4个字节组成。

编码空间庞大,最多可定义161万个字符。

支持中国国内少数民族的文字,不需要动用造字区。

汉字收录范围包含繁体汉字以及日韩汉字

2014112400003

GBK,汉字编码标准之一,全称《汉字内码扩展规范》,它 向下与 GB 2312 编码兼容,向上支持 ISO 10646.1 国际标准,是前者向后者过渡过程中的一个承上启下的标准。它的编码范围如下图:

2014112400004

3.Unicode编码

正如前面前面所提到的一样,世界存在这么多国家,也存在着多种编码风格,像中文的GB232、GBK、GB18030,这样乱搞一套,虽然在本地运行没有问题,但是一旦出现在网络上,由于互不兼容,访问则会出现乱码。为了解决这个问题,伟大的Unicode编码腾空出世。

Unicode编码的作用就是能够使计算机实现夸平台、跨语言的文本转换和处理。它几乎包含了世界上所有的符号,并且每个符号都是独一无二的。在它的编码世界里,每一个数字代表一个符号,每一个符号代表了一个数字,不存在二义性。

Unicode编码又称统一码、万国码、单一码,它是业界的一种标准,是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定 了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。同时Unicode是字符集,它存在很多几种实现方式如:UTF-8、 UTF-16.

UTF-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种unicode的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。重复一遍:UTF-8是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有两条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

推荐阅读

此篇博文只是开篇之作,启下之用, 对字符集的介绍也只是简简单单,没有太多的描述,因为LZ在查字符集的资料过程中发现字符集真的是太复杂了,LZ有点儿驾驭不了,需要仔细研究,然后写一篇较为详细的博文!各位敬请期待!!

参考文献:

字符集和字符编码:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

百度百科 ASCII:http://baike.baidu.com/view/15482.htm

百度百科:GB2312:http://baike.baidu.com/view/443268.htm?fromtitle=GB2312&fromid=483170&type=syn

百度百科:GB18030:http://baike.baidu.com/view/889058.htm

百度百科:GBK:http://baike.baidu.com/view/931619.htm?fromtitle=GBK&fromid=481954&type=search

百度百科:Unicode:http://baike.baidu.com/view/40801.htm

百度百科:UTF-8:http://baike.baidu.com/view/25412.htm

如有错误之处,忘指出!!不胜感激!!!


—–原文出自:http://cmsblogs.com/?p=1395,请尊重作者辛勤劳动成果,转载说明出处.

—–个人站点:http://cmsblogs.com

Java堆内存

来源: 朱小厮

链接: http://blog.csdn.net/u013256816/article/details/50764532

Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。

在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。

堆的内存模型大致为:

新生代:Young Generation,主要用来存放新生的对象。

老年代:Old Generation或者称作Tenured Generation,主要存放应用程序声明周期长的内存对象。

永久代:(方法区,不属于java堆,另一个别名为“非堆Non-Heap”但是一般查看PrintGCDetails都会带上PermGen区)是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域. 它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用会加载很多Class的话,就很可能出现PermGen space错误。

堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。

默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。

默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。

JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。

因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

回收方法区(附加补充)

很多人认为方法区(或者HotSpot虚拟机中的永久代[PermGen])是没有垃圾收集的,java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集,而且在方法去中进行垃圾收集的“性价比”一般比较低:在堆中,尤其是在新生代中,常规应用进行一次垃圾收集一般可以回收70%-95%的空间,而永久代的垃圾收集效率远低于此。

永久代的垃圾收集主要回收两部分内容:废弃的常量和无用的类。

1. 废弃的常量:回收废弃常量与回收java堆中的对象非常类似。以常量池字面量的回收为例,加入一个字符串“abc”已经进入了常量池中,但是当前系统没有任何一个String对象是叫做”abc”的,换句话说,就是有任何String对象应用常量池中的”abc”常量,也没有其他地方引用了这个字面量,如果这时发生内存回收,而且必要的话,这个“abc”常量就会被系统清理出常量池。常量池中的其他类(接口)、方法、字段的符号引用也与此类似。(注:jdk1.7及其之后的版本已经将常量池从永久代中移出)

2. 无用的类:类需要同时满足下面3个条件才能算是“无用的类”:

  • 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

虚拟机可以对满足上述3个条件的无用类进行回收,这里说的仅仅是”可以“,而并不和对象一样,不使用了就必然会回收。是否对类进行回收,HotSpot虚拟机提供了-Xnoclassgc(关闭CLASS的垃圾回收功能,就是虚拟机加载的类,即便是不使用,没有实例也不会回收。)参数进行控制。

在大量使用反射、动态代理、CGlib等ByteCode框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

GC

Java 中的堆也是 GC 收集垃圾的主要区域。GC 分为两种:Minor GC、Full GC ( 或称为 Major GC )。

Minor GC 是发生在新生代中的垃圾收集动作,所采用的是复制算法。

新生代几乎是所有 Java 对象出生的地方,即 Java 对象申请的内存以及存放都是在这个地方。Java 中的大部分对象通常不需长久存活,具有朝生夕灭的性质。

当一个对象被判定为 “死亡” 的时候,GC 就有责任来回收掉这部分对象的内存空间。新生代是 GC 收集垃圾的频繁区域。

当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。

但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制(新生代采用复制算法收集内存)。

为了能够更好的适应不同的程序的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。

Full GC 是发生在老年代的垃圾收集动作,所采用的是“标记-清除”或者“标记-整理”算法。

现实的生活中,老年代的人通常会比新生代的人 “早死”。堆内存中的老年代(Old)不同于这个,老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。因此,Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。

在发生MinorGC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么MinorGC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试这进行一次MinorGC,尽管这次MinorGC是有风险的;如果小于,或者HandlePromptionFailure设置不允许冒险,那这是也要改为进行一次FullGC.

另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。

GC日志

首先看一下如下代码:

package jvm;

 

public class PrintGCDetails

{

public static void main(String[] args)

{

Object obj = new Object();

System.gc();

System.out.println();

obj = new Object();

obj = new Object();

System.gc();

System.out.println();

}

}

设置JVM参数为-XX:+PrintGCDetails,执行结果如下:

[GC [PSYoungGen: 1019K->568K(28672K)] 1019K->568K(92672K), 0.0529244 secs] [Times: user=0.00 sys=0.00, real=0.06 secs]

{博主自定义注解:[GC [新生代: MinorGC前新生代内存使用->MinorGC后新生代内存使用(新生代总的内存大小)] MinorGC前JVM堆内存使用的大小->MinorGC后JVM堆内存使用的大小(堆的可用内存大小), MinorGC总耗时] [Times: 用户耗时=0.00 系统耗时=0.00, 实际耗时=0.06 secs] }

[Full GC [PSYoungGen: 568K->0K(28672K)] [ParOldGen: 0K->478K(64000K)] 568K->478K(92672K) [PSPermGen: 2484K->2483K(21504K)], 0.0178331 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]

{博主自定义注解:[Full GC [PSYoungGen: 568K->0K(28672K)] [老年代: FullGC前老年代内存使用->FullGC后老年代内存使用(老年代总的内存大小)] FullGC前JVM堆内存使用的大小->FullGC后JVM堆内存使用的大小(堆的可用内存大小) [永久代: 2484K->2483K(21504K)], 0.0178331 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]}

 

[GC [PSYoungGen: 501K->64K(28672K)] 980K->542K(92672K), 0.0005080 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

[Full GC [PSYoungGen: 64K->0K(28672K)] [ParOldGen: 478K->479K(64000K)] 542K->479K(92672K) [PSPermGen: 2483K->2483K(21504K)], 0.0133836 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]

 

Heap

PSYoungGen      total 28672K, used 1505K [0x00000000e0a00000, 0x00000000e2980000, 0x0000000100000000)

eden space 25088K, 6% used [0x00000000e0a00000,0x00000000e0b78690,0x00000000e2280000)

from space 3584K, 0% used [0x00000000e2600000,0x00000000e2600000,0x00000000e2980000)

to   space 3584K, 0% used [0x00000000e2280000,0x00000000e2280000,0x00000000e2600000)

ParOldGen       total 64000K, used 479K [0x00000000a1e00000, 0x00000000a5c80000, 0x00000000e0a00000)

object space 64000K, 0% used [0x00000000a1e00000,0x00000000a1e77d18,0x00000000a5c80000)

PSPermGen       total 21504K, used 2492K [0x000000009cc00000, 0x000000009e100000, 0x00000000a1e00000)

object space 21504K, 11% used [0x000000009cc00000,0x000000009ce6f2d0,0x000000009e100000)

注:你可以用JConsole或者Runtime.getRuntime().maxMemory(),Runtime.getRuntime().totalMemory(), Runtime.getRuntime().freeMemory()来查看Java中堆内存的大小。

再看一个例子:

package jvm;

public class PrintGCDetails2

{

/**

* -Xms60m -Xmx60m -Xmn20m -XX:NewRatio=2 ( 若 Xms = Xmx, 并且设定了 Xmn,

* 那么该项配置就不需要配置了 ) -XX:SurvivorRatio=8 -XX:PermSize=30m -XX:MaxPermSize=30m

* -XX:+PrintGCDetails

*/

public static void main(String[] args)

{

new PrintGCDetails2().doTest();

}

 

public void doTest()

{

Integer M = new Integer(1024 * 1024 * 1); // 单位, 兆(M)

byte[] bytes = new byte[1 * M]; // 申请 1M 大小的内存空间

bytes = null; // 断开引用链

System.gc(); // 通知 GC 收集垃圾

System.out.println();

bytes = new byte[1 * M]; // 重新申请 1M 大小的内存空间

bytes = new byte[1 * M]; // 再次申请 1M 大小的内存空间

System.gc();

System.out.println();

}

}

运行结果:

[GC [PSYoungGen: 2007K->568K(18432K)] 2007K->568K(59392K), 0.0059377 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

[Full GC [PSYoungGen: 568K->0K(18432K)] [ParOldGen: 0K->479K(40960K)] 568K->479K(59392K) [PSPermGen: 2484K->2483K(30720K)], 0.0223249 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]

 

[GC [PSYoungGen: 3031K->1056K(18432K)] 3510K->1535K(59392K), 0.0140169 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]

[Full GC [PSYoungGen: 1056K->0K(18432K)] [ParOldGen: 479K->1503K(40960K)] 1535K->1503K(59392K) [PSPermGen: 2486K->2486K(30720K)], 0.0119497 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

 

Heap

PSYoungGen      total 18432K, used 163K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)

eden space 16384K, 1% used [0x00000000fec00000,0x00000000fec28ff0,0x00000000ffc00000)

from space 2048K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x0000000100000000)

to   space 2048K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x00000000ffe00000)

ParOldGen       total 40960K, used 1503K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000)

object space 40960K, 3% used [0x00000000fc400000,0x00000000fc577e10,0x00000000fec00000)

PSPermGen       total 30720K, used 2493K [0x00000000fa600000, 0x00000000fc400000, 0x00000000fc400000)

object space 30720K, 8% used [0x00000000fa600000,0x00000000fa86f4f0,0x00000000fc400000)

从打印结果可以看出,堆中新生代的内存空间为 18432K ( 约 18M ),eden 的内存空间为 16384K ( 约 16M),from / to survivor 的内存空间为 2048K ( 约 2M)。

这里所配置的 Xmn 为 20M,也就是指定了新生代的内存空间为 20M,可是从打印的堆信息来看,新生代怎么就只有 18M 呢? 另外的 2M 哪里去了?

别急,是这样的。新生代 = eden + from + to = 16 + 2 + 2 = 20M,可见新生代的内存空间确实是按 Xmn 参数分配得到的。

而且这里指定了 SurvivorRatio = 8,因此,eden = 8/10 的新生代空间 = 8/10 * 20 = 16M。from = to = 1/10 的新生代空间 = 1/10 * 20 = 2M。

堆信息中新生代的 total 18432K 是这样来的: eden + 1 个 survivor = 16384K + 2048K = 18432K,即约为 18M。

因为 jvm 每次只是用新生代中的 eden 和 一个 survivor,因此新生代实际的可用内存空间大小为所指定的 90%。

因此可以知道,这里新生代的内存空间指的是新生代可用的总的内存空间,而不是指整个新生代的空间大小。

另外,可以看出老年代的内存空间为 40960K ( 约 40M ),堆大小 = 新生代 + 老年代。因此在这里,老年代 = 堆大小 – 新生代 = 60 – 20 = 40M。

最后,这里还指定了 PermSize = 30m,PermGen 即永久代 ( 方法区 ),它还有一个名字,叫非堆,主要用来存储由 jvm 加载的类文件信息、常量、静态变量等。

附:JVM常用参数

-XX:+

-XX:-

-XX:

-XX:

堆设置

-Xms :初始堆大小

-Xmx :最大堆大小

-Xmn:新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%

-XX:NewSize=n :设置年轻代大小

-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4

-XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

-XX:PermSize=n 永久代(方法区)的初始大小

-XX:MaxPermSize=n :设置永久代大小

-Xss 设定栈容量;对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,因为在HotSpot中并不区分虚拟机和本地方法栈。

-XX:PretenureSizeThreshold (该设置只对Serial和ParNew收集器生效) 可以设置进入老生代的大小限制

-XX:MaxTenuringThreshold=1(默认15)垃圾最大年龄 如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率

该参数只有在串行GC时才有效.

收集器设置

-XX:+UseSerialGC :设置串行收集器

-XX:+UseParallelGC :设置并行收集器

-XX:+UseParallelOldGC :设置并行年老代收集器

-XX:+UseConcMarkSweepGC :设置并发收集器

垃圾回收统计信息

-XX:+PrintHeapAtGC GC的heap详情

-XX:+PrintGCDetails GC详情

-XX:+PrintGCTimeStamps 打印GC时间信息

-XX:+PrintTenuringDistribution 打印年龄信息等

-XX:+HandlePromotionFailure 老年代分配担保(true or false)

-Xloggc:gc.log 指定日志的位置

并行收集器设置

-XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。

-XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间

-XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

并发收集器设置

-XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。

-XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

其他

-XX:PermSize=10M和-XX:MaxPermSize=10M限制方法区大小。

-XX:MaxDirectMemorySize=10M指定DirectMemory(直接内存)容量,如果不指定,则默认与JAVA堆最大值(-Xmx指定)一样。

-XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照(.hprof文件)以便时候进行分析(比如Eclipse Memory Analysis)。

参考资料:

1. 《java 虚拟机–新生代与老年代GC》

2. 《Java 堆内存》

3. 《深入理解Java虚拟机》周志明著

Java内存模型

英文:Jakob Jenkov

译文:张坤

链接:http://ifeve.com/java-memory-model-6/

 

Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型。

如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的。Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。

原始的Java内存模型存在一些不足,因此Java内存模型在Java1.5时被重新修订。这个版本的Java内存模型在Java8中人在使用。

Java内存模型内部原理

Java内存模型把Java虚拟机内部划分为线程栈和堆。这张图演示了Java内存模型的逻辑视图。

Java Memory Model

每一个运行在Java虚拟机里的线程都拥有自己的线程栈。这个线程栈包含了这个线程调用的方法当前执行点相关的信息。一个线程仅能访问自己的线程 栈。一个线程创建的本地变量对其它线程不可见,仅自己可见。即使两个线程执行同样的代码,这两个线程任然在在自己的线程栈中的代码来创建本地变量。因此, 每个线程拥有每个本地变量的独有版本。

所有原始类型的本地变量都存放在线程栈上,因此对其它线程不可见。一个线程可能向另一个线程传递一个原始类型变量的拷贝,但是它不能共享这个原始类型变量自身。

堆上包含在Java程序中创建的所有对象,无论是哪一个对象创建的。这包括原始类型的对象版本。如果一个对象被创建然后赋值给一个局部变量,或者用来作为另一个对象的成员变量,这个对象任然是存放在堆上。

下面这张图演示了调用栈和本地变量存放在线程栈上,对象存放在堆上。

enter image description here

一个本地变量可能是原始类型,在这种情况下,它总是“呆在”线程栈上。

一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上。

一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量任然存放在线程栈上,即使这些方法所属的对象存放在堆上。

一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。

静态成员变量跟随着类定义一起也存放在堆上。

存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个本地变量的私有拷贝。

下图演示了上面提到的点:

enter image description here

两个线程拥有一些列的本地变量。其中一个本地变量(Local Variable 2)执行堆上的一个共享对象(Object 3)。这两个线程分别拥有同一个对象的不同引用。这些引用都是本地变量,因此存放在各自线程的线程栈上。这两个不同的引用指向堆上同一个对象。

注意,这个共享对象(Object 3)持有Object2和Object4一个引用作为其成员变量(如图中Object3指向Object2和Object4的箭头)。通过在Object3中这些成员变量引用,这两个线程就可以访问Object2和Object4。

这张图也展示了指向堆上两个不同对象的一个本地变量。在这种情况下,指向两个不同对象的引用不是同一个对象。理论上,两个线程都可以访问Object1和Object5,如果两个线程都拥有两个对象的引用。但是在上图中,每一个线程仅有一个引用指向两个对象其中之一。

因此,什么类型的Java代码会导致上面的内存图呢?如下所示:

public class MyRunnable implements Runnable() {

    public void run() {
        methodOne();
    }

    public void methodOne() {
        int localVariable1 = 45;

        MySharedObject localVariable2 =
            MySharedObject.sharedInstance;

        //... do more with local variables.

        methodTwo();
    }

    public void methodTwo() {
        Integer localVariable1 = new Integer(99);

        //... do more with local variable.
    }
}


public class MySharedObject {

    //static variable pointing to instance of MySharedObject

    public static final MySharedObject sharedInstance =
        new MySharedObject();


    //member variables pointing to two objects on the heap

    public Integer object2 = new Integer(22);
    public Integer object4 = new Integer(44);

    public long member1 = 12345;
    public long member1 = 67890;
}

如果两个线程同时执行run()方法,就会出现上图所示的情景。run()方法调用methodOne()方法,methodOne()调用methodTwo()方法。

methodOne()声明了一个原始类型的本地变量和一个引用类型的本地变量。

每个线程执行methodOne()都会在它们对应的线程栈上创建localVariable1localVariable2的私有拷贝。localVariable1变量彼此完全独立,仅“生活”在每个线程的线程栈上。一个线程看不到另一个线程对它的localVariable1私有拷贝做出的修改。

每个线程执行methodOne()时也将会创建它们各自的localVariable2拷贝。然而,两个localVariable2的不同拷贝都指向堆上的同一个对象。代码中通过一个静态变量设置localVariable2指向一个对象引用。仅存在一个静态变量的一份拷贝,这份拷贝存放在堆上。因此,localVariable2的两份拷贝都指向由MySharedObject指向的静态变量的同一个实例。MySharedObject实例也存放在堆上。它对应于上图中的Object3。

注意,MySharedObject类也包含两个成员变量。这些成员变量随着这个对象存放在堆上。这两个成员变量指向另外两个Integer对象。这些Integer对象对应于上图中的Object2和Object4.

注意,methodTwo()创建一个名为localVariable的本地变量。这个成员变量是一个指向一个Integer对象的对象引用。这个方法设置localVariable1引用指向一个新的Integer实例。在执行methodTwo方法时,localVariable1引用将会在每个线程中存放一份拷贝。这两个Integer对象实例化将会被存储堆上,但是每次执行这个方法时,这个方法都会创建一个新的Integer对象,两个线程执行这个方法将会创建两个不同的Integer实例。methodTwo方法创建的Integer对象对应于上图中的Object1和Object5。

还有一点,MySharedObject类中的两个long类型的成员变量是原始类型的。因为,这些变量是成员变量,所以它们任然随着该对象存放在堆上,仅有本地变量存放在线程栈上。

硬件内存架构

现代硬件内存模型与Java内存模型有一些不同。理解内存模型架构以及Java内存模型如何与它协同工作也是非常重要的。这部分描述了通用的硬件内存架构,下面的部分将会描述Java内存是如何与它“联手”工作的。

下面是现代计算机硬件架构的简单图示:

enter image description here

一个现代计算机通常由两个或者多个CPU。其中一些CPU还有多核。从这一点可以看出,在一个有两个或者多个CPU的现代计算机上同时运行多个线程 是可能的。每个CPU在某一时刻运行一个线程是没有问题的。这意味着,如果你的Java程序是多线程的,在你的Java程序中每个CPU上一个线程可能同 时(并发)执行。

每个CPU都包含一系列的寄存器,它们是CPU内内存的基础。CPU在寄存器上执行操作的速度远大于在主存上执行的速度。这是因为CPU访问寄存器的速度远大于主存。

每个CPU可能还有一个CPU缓存层。实际上,绝大多数的现代CPU都有一定大小的缓存层。CPU访问缓存层的速度快于访问主存的速度,但通常比访 问内部寄存器的速度还要慢一点。一些CPU还有多层缓存,但这些对理解Java内存模型如何和内存交互不是那么重要。只要知道CPU中可以有一个缓存层就 可以了。

一个计算机还包含一个主存。所有的CPU都可以访问主存。主存通常比CPU中的缓存大得多。

通常情况下,当一个CPU需要读取主存时,它会将主存的部分读到CPU缓存中。它甚至可能将缓存中的部分内容读到它的内部寄存器中,然后在寄存器中执行操作。当CPU需要将结果写回到主存中去时,它会将内部寄存器的值刷新到缓存中,然后在某个时间点将值刷新回主存。

当CPU需要在缓存层存放一些东西的时候,存放在缓存中的内容通常会被刷新回主存。CPU缓存可以在某一时刻将数据局部写到它的内存中,和在某一时 刻局部刷新它的内存。它不会再某一时刻读/写整个缓存。通常,在一个被称作“cache lines”的更小的内存块中缓存被更新。一个或者多个缓存行可能被读到缓存,一个或者多个缓存行可能再被刷新回主存。

Java内存模型和硬件内存架构之间的桥接

上面已经提到,Java内存模型与硬件内存架构之间存在差异。硬件内存架构没有区分线程栈和堆。对于硬件,所有的线程栈和堆都分布在主内中。部分线程栈和堆可能有时候会出现在CPU缓存中和CPU内部的寄存器中。如下图所示:

enter image description here

当对象和变量被存放在计算机中各种不同的内存区域中时,就可能会出现一些具体的问题。主要包括如下两个方面:

-线程对共享变量修改的可见性
-当读,写和检查共享变量时出现race conditions

下面我们专门来解释以下这两个问题。

共享对象可见性

如果两个或者更多的线程在没有正确的使用volatile声明或者同步的情况下共享一个对象,一个线程更新这个共享对象可能对其它线程来说是不接见的。

想象一下,共享对象被初始化在主存中。跑在CPU上的一个线程将这个共享对象读到CPU缓存中。然后修改了这个对象。只要CPU缓存没有被刷新会主 存,对象修改后的版本对跑在其它CPU上的线程都是不可见的。这种方式可能导致每个线程拥有这个共享对象的私有拷贝,每个拷贝停留在不同的CPU缓存中。

下图示意了这种情形。跑在左边CPU的线程拷贝这个共享对象到它的CPU缓存中,然后将count变量的值修改为2。这个修改对跑在右边CPU上的其它线程是不可见的,因为修改后的count的值还没有被刷新回主存中去。

enter image description here

解决这个问题你可以使用Java中的volatile关键字。volatile关键字可以保证直接从主存中读取一个变量,如果这个变量被修改后,总是会被写回到主存中去。

Race Conditions

如果两个或者更多的线程共享一个对象,多个线程在这个共享对象上更新变量,就有可能发生race conditions

想象一下,如果线程A读一个共享对象的变量count到它的CPU缓存中。再想象一下,线程B也做了同样的事情,但是往一个不同的CPU缓存中。现在线程A将count加1,线程B也做了同样的事情。现在count已经被增在了两个,每个CPU缓存中一次。

如果这些增加操作被顺序的执行,变量count应该被增加两次,然后原值+2被写回到主存中去。

然而,两次增加都是在没有适当的同步下并发执行的。无论是线程A还是线程B将count修改后的版本写回到主存中取,修改后的值仅会被原值大1,尽管增加了两次。

下图演示了上面描述的情况:

enter image description here

解决这个问题可以使用Java同步块。一个同步块可以保证在同一时刻仅有一个线程可以进入代码的临界区。同步块还可以保证代码块中所有被访问的变量将会从主存中读入,当线程退出同步代码块时,所有被更新的变量都会被刷新回主存中去,不管这个变量是否被声明为volatile。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java内存模型

 

程序员必读的书,StackOverflow 创始人推荐

伯乐在线/艾凌风

原载: http://blog.jobbole.com/100450/

Stack Overflow 创始人 Jeff Atwood 推荐给程序员的书。


本文最近一次更新是2015年3月份。 为什么我很少更新我的读书清单呢?因为虽然在这 10 年里,计算机一直在迅猛发展,但人始终却没有变。 为了开发出更好的软件,你需要理解人是如何工作的,这也是我推荐的这些书所关注的领域。

代码大全2

Steve McConnell所著的《代码大全2》 就像是为软件开发者所编写的《烹饪的乐趣》。能够去阅读这本书,说明你很享受自己的工作,并且在认真地对待自己的工作。同时,你还想要不断的进步。在《代 码大全》中Steve写到,普通程序员每年阅读的技术书籍不到一本。仅仅是阅读这本书的行为,就可能已经把你和你90%的程序员同事们区别开来了。

我非常喜欢这本书,以至于本站(coding horror)的名字也源于此书。书中列举的编程反例都被打上了”Coding Horror”的标签。没有什么比Coding Horror更有意思的了,直到你自己遇上一次。突然间一切都不那么有趣了。帮自己一个忙,把这本书作为你要研读的第一本书,并把它作为你推荐给同事的第一本书。

人月神话

这本书可能是我们这领域唯一的一本经典了。如果你还没读过,那就太不对了。

我敢说任何一个拿起这本书的程序员都没有发现关于那个早就不使用操作系统的故事以及它的开发团队之间惊人的相关性。这本二十五年前出版的老书大胆的阐明了一个观点:计算机也许会变,但人永远不会。

花时间去阅读这本经典书籍一定比你去阅读当今哪些几千页的大部头书籍更加有意义。

点石成金 : 访客至上的网页设计秘笈

在关于可用性的书籍中,这是我读过的最好的一本书。书名提到了“网页的可用性”,但是请不要被这一虚假的特指所迷惑。Steve Krug在书中提到了可用性这一概念所包含的全部重要内容,而且讲的很好,书也很有意思。如果你只想读一本关于可用性的书,那么读这本就可以了。这本书囊括了很多有用的信息,并且以简练的、平易近人的方式将这些信息呈现给你。这本书对于很多人都是适用的:技术人员、非技术人员、用户、开发者、经理等凡是你能说出名字的任何人。

呃。。。好吧。从来没有开过这样的会议。顺便提一下,解决这个问题的办法是进行一次快速的可用性测试。请想象这样的场景:基于实际数据来做决定而不是基于一场为了通过说服所有持有反对意见的人的辩论。真是革命性的转变啊!

快速软件开发

这本书的全称是:《快速软件开发:掌控软件开发进度》,这个标题不仅冗长还有些可笑,更不幸的是它用词不当。

快速软件开发》并不是一本关于快速开发的书。它讲述的是软件开发失败这一现实问题。大多数的软件开发项目都会失败:有时是没能按期交付,有时是开发出了不合格的产品,甚至有的时候都没有能够完成开发。这并不是什么论点,而是一个事实。一个令人不快的事实是:你的团队要足够的好,才能避免失败,更别说取得成功了。尽管这一切听起来可能会令人沮丧——好吧,这确实令人沮丧——但你仍然会想要去读一读这本书。

为什么呢?因为你曾经犯过的错误,或者其他人犯过的错误,如果能够避免再犯,就已经成功了一半*了。这本书传达了一个真谛:犯错是有益的——只要这些错误是一些未曾犯过的错误。如果你犯了一些经典的老错误,那么你在没有开始前就已经失败了。同时,你可能并没有意识到,你现在就在犯着类似的错误。

对我们这一行来讲,唯一不变的就是变化。所以拥抱变化和采取不同的“快速”开发技术是很自然的一件事。但是这句话反过来说就不对了。我们不能认为自 1970年以来,所有的旧式软件开发课程同今天的技术相比已经是废弃的或是没用的了。老生常谈的一件事是:计算机改变了很多;人却没有。在你准备开始前, 至少对于哪些可行哪些不可行有个认识。用 McConnell 的话说就是:“粉刷之前请先阅读油漆桶上的说明文字。” 诚然,这听上去已经足够直白了,但是直到你读了这本书,你才意识到,我们很少会真正去这么做。

  • 根据书的内容,严格来讲,有四分之一的内容。但是我觉得要比这多得多。

人件

如果你曾经看到过一个全明星球队,因为教练水平不高而战绩不佳,那你肯定会喜欢这本书。如果团队成员不能相互沟通或是认同一件事,那么你的团队中不 论有多少“编程之星”都没用。如果一个开发者经常被一些琐事打断,即使他是个天才,也不能够高效的工作。开发者并不清楚他们自己的社交技能,但是,讽刺的 是:这可能是你项目成功的关键因素。如果你希望成为一个真正的“团队领袖”,而不是徒有其名,你需要看看这本书。

尽管《人件》中有很多不错的、完全正确的观点,但是书中描绘的这种雇员管理对于大多数公司来讲纯粹是幻想。但是至少你可以在你的工作环境,或是你的团队出现问题的时候有所察觉——最重要的是,你可以知道怎么做。

设计心理学

软件开发有时候是一件极度令人沮丧的事情,因为很多事情都会做错。我们做的很多事情都是防御性的:尝试在情况变坏之前做出预测。这令人十分伤神,并 且最终可能会被证明是错的。我经常根非技术人员这样去解释这个问题:就好像去造一块有上千个运动部件的手表,其中每个部件都会动不动就随机坏掉。棒极了!

软件开发是很困难的,这点没错,但是做一个门也很困难。设计的微妙之处存在于我们接触到的每个事物,不论是最新的 SQL 引擎还是一双普通的鞋。这本书会让你对“恶魔藏在细节里”这句话产生新的认识。如果设计一个门并不是我们想象的那样是一件很简单的事的话,也许是时候因为 意识到我们也无法设计出完美的软件而给自己放个假了。

About Face:交互设计精髓

Alan Cooper 是 Visual Basic语言之父,可用性领域的教父级人物。我拥有这本书的多个版本(现在是第四版),这本书是少数越修订越好的书,越来越多的合作者向本书加入了不同的观点。

《About Face》一书中包含了关于移动应用和 web 应用的通用实用指导。 以老掉牙的 Windows 95 人机界面作为例子来进行阐释,将该系统已经改进的地方(在进行对话框选择前使用视觉样例进行展示)和还没有改进的部分(使用愚蠢的模态框来停止正在运行的 进程)进行对比是很有趣的一件事。

这是一本非常有用的书;我在我自己的项目中用到了书中提到了全部的指导。

《交互设计之路:让高科技产品回归人性》

正是这本书向世人介绍了角色模型的概念:不要把用户想象为一群抽象的、难以描述的、无定形的人。角色模型指导我 们和特定的用户进行交谈,这些用户有名字,有个性,有需求也有目标。我们的用户是否需要打印预览功能?谁知道?但是,如果对于客户经理 Gerry Manheim 来说,打印每周花销报表是他的工作,那你最好提供打印预览功能给他。这里边没有什么神奇的东西;一如既往的是,一切都归结于你的用户是谁,他们究竟要做什 么——角色模型是解决这一问题的好办法。

程序员认为自己在设计产品可用性时能够代表“普通”用户作出某些决定,但是在现实世界中,他们完全不能代表用户。程序员是一群怪人,充其量能算是是 一种极端的用户——就好比“逻辑人(Homo Logicus)” vs. “现代智人(Homo Sapiens)”。除非你碰巧开发的是一款编译器,因为编译器的用户也是程序员。

这本书有一个隐含的观点,有的时候,无论你的设计有多好,就像由 Alan 担任顾问并在此书中用作案例的这两款软件:扫描仪软件以及网页开发软件,在市场上都没有能够取得成功,但这和软件的可用性无关,因为它们的可用性已经被证明是非常优秀的了。有些时候,非常优秀的产品同样会失败,而其失败的原因是你无法掌控的,无论你多么努力。对于此书中的一些华而不实的词藻,你可以用以上事实将自己拉回到现实当中。

  • 我有书中图片里的同款 USB 扫描仪,设备配套对软件令我印象深刻。后来我把这台扫描仪送给了我父亲。有一次和他打电话,我并没有提到任何关于扫描仪的事情,但是他却提到他很喜欢这个扫描软件。这一切都发生在这本书出版之前!

编程珠玑

在这里推荐《编程珠玑》,我本来有些犹豫,因为这本书中介绍了很多底层的编程技巧。但是书中确实包含了很多软件开发中的『珠玑』,所以值得每位开发者花时间去读一读。任何包含这幅图的书…

…都是物有所值的。利用TRS-80 与 DEC Alpha 的对比来阐释48n和n3算法的差别?各位,真的没有比这样做更合适的了。能和大师一起工作一年是最好的了,退而求其次,你也可以读读《编程珠玑》。这本书将很多软件工程师的智慧提炼成了简洁易懂的文字,纳入其中。

我不会骗你:有一些章节是可以完全略过的。比如说,第11、13和14章分别介绍了如何实现排序,堆和哈希算法,考虑到现如今这些基本算法都有成熟 的库可以使用,我无法想象再去实现它们有什么意义。 对于那些和教科书一样恼人的习题,这里有一个很实在的建议。浏览一下这本书,跳过代码部分。有件事可能会让你失望,第八章“粗略估算”(Column 8, “Back of the Envelope” )是必须要看的。这里有我见过的最佳的估算方法。这章还解释了一些疯狂的面试问题,一些公司很喜欢用这些问题提问我们。

如果你还在犹豫,你也可以在网上阅读一下此书的样章。最近我用书中关于字符串的章节去解释了马尔科夫链在生成人造数据填充空数据库时的作用。

程序员修炼之道:从小工到专家

看这本书时常会让我想到《编程珠玑》,但是实际上这本书更好一些。因为这本书没有那么的专注于代码,取而代之的的是,作者在这本书中总结了实际工作中发现的全部实用方法。并非所有的方法都是与编程相关的。比如,问问自己『为什么我要做这件事?是否值得这样做?』,跳出固有的思维方式。你应该把这些东西融入到你和你同事的日常生活中。正是这些内容,使得《程序员修炼之道》成为了一本如此优秀的书。

如果你想再多了解一些这本书,我建立一个HTML 版本的插页参考卡片,这个参考卡片很好的总结了这本书的内容。

《Web 可用性设计》

Jakob Neilsen 因为他所创建的可用性网站而出名。1989年,当他的书出版的时候,他就是一个可用性专家了。《Web 可用性设计》是一本专注于 web 可用性的新手教程,所以它和面向 GUI 的 Cooper 的那本书有所不同。

《定量信息的视觉显示》

《视觉解释:图像和数量,证据与线索》

《想象信息》

《美丽的证据》

信息是很美的。一个设计良好的 GUI 也很美。

除非你是个完美主义者(或是一个受虐狂,我猜),否则你没有必要把一套四本全买齐,但是前两本是必须的。

Chris Sells 对 Tufte 的书有些有趣的见解,这些见解源于他2004年6月参加Tufte研讨会时的见闻。

正则表达式经典实例

众所周知 UNIX 非常复杂、难以理解。正则表达式也是这样。

我可能已经是『保持简单直白』俱乐部的正是成员了,但是我愿意将正则表达式作为一个特例。若能正确的书写正则表达式,则在处理字符串时,它可以帮你节省非常多的时间。我从来没有遇到过一个项目,正则表达不能在某些地方为我们提供方便。

一旦你深入研究了正则表达式,你就会沉醉于正则表达式惊人的能力和潜力,这一切也造就了 Perl。记住,绝对的权利会导致绝对的腐败。但是同样非常的赞。

译者简介


艾凌风:兴趣点:Python,C/C++,在线教育,英语