首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

hive在E-MapReduce集群的实践(一)hive异常排查入门

hive是hadoop集群最常用的数据分析工具,只要运行sql就可以分析海量数据。初学者在使用hive时,经常会遇到各种问题,不知道该怎么解决。 本文是hive实践系列的第一篇,以E-MapReduce集群环境为例,介绍常见的hive执行异常,定位和解决方法,以及hive日志查看方法。 除作者本人的知乎专栏外,其他转载需要先联系我。 一.常见异常表现 主要是执行hive sql时卡住,提示异常信息。 如执行sql时直接提示异常信息,执行sql时卡住,显示mapreduce进度一直0%,mapreduce进度长时间不变化,执行一半提示异常退出,等等。 二.异常定位和解决 2.1.执行sql直接提示异常信息 一般是语法问题,资源问题或hive服务异常。 2.1.1 语法解析错误 sql写的有问题。如ParseException hive> sho

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

【Java入门提高篇】Day14 Java中的泛型初探

泛型是一个很有意思也很重要的概念,本篇将简单介绍Java中的泛型特性,主要从以下角度讲解: 1.什么是泛型。 2.如何使用泛型。 3.泛型的好处。 1.什么是泛型? 泛型,字面意思便是参数化类型,平时所面对的类型一般都是具体的类型,如果String,Integer,Double,而泛型则是把所操作的数据类型当作一个参数。如,ArrayList<String>(),通过传入不同的类型来指定容器中存储的类型,而不用为不同的类型创建不同的类,这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 2.如何使用泛型? 我们先来看看泛型是什么样子的: public interface List<E> { void add(E); Iterator<E> iterator(); } 这是List接口,这里用E来代替具体类型,这样就可以往里面传入任意类型,也许你要问了,直接使用Object不好吗?我们来用一个栗子比较一下: 先用非泛型方式来实现一下: public class ObjHolder { private Object a; public ObjHolder(Object a) { this.a = a; } public void set(Object a) { this.a = a; } public Object get(){ return a; } public static void main(String[] args) { ObjHolder holderA = new ObjHolder("Frank"); System.out.println((String) holderA.get()); holderA.set(233); System.out.println((Integer) holderA.get()); } } 这样就实现了一个包装类,可以用来存取一个任意类型的对象。但是每次取出来都需要进行类型转化,如果方法的参数类型是ObjHolder的话,无法知道它里面存放的对象的确切类型,这样就反而带来很多不必要的麻烦。 现在来看一下用泛型实现是怎样的: public class GenericHolder<T> { private T obj; public GenericHolder(T obj){ this.obj = obj; } public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } public static void main(String[] args) { GenericHolder<String> holderA = new GenericHolder<String>("Frank"); System.out.println(holderA.getObj()); //holderA.set(233);无法编译通过,因为只能往holderA中存入String类型 GenericHolder<Integer> holderB = new GenericHolder<Integer>(233); System.out.println(holderB.getObj()); } } 这样通过传入类型信息如String和Integer,来代替其中的泛型参数T,这里的T可以理解为一个占位符,用其他字母也是可以的,一旦传入具体类型,如String,则所有使用T的地方都会用String类型替换。 对比一下上面两种方式,区别在哪呢?打个比方,不用泛型的实现方式,相当于一个袋子,里面可以装任意类型的黑盒子,你什么都可以往里放,但是你可能不知道你下一个取出来的是什么东西,而泛型的实现方式,相当于一个贴了标签的黑盒子,标签上可以写任何信息,如写上水果,那么这个盒子就只能装水果,你也会知道每次取出来的肯定是水果而不是其它东西,同理类似如写上杂粮,那么这个袋子就只能用来装杂粮,但其实上都是同一种袋子,并不是为每一种类型的东西准备一种袋子。(因为Java的泛型使用了类型擦除机制,至于类型擦除是什么,暂时不做过多介绍,以后会有文章做更详细的说明)。 泛型被广泛应用在容器类中,如ArrayList<T>() 表示用于存储特定类型的数组,除此之外,还有很多泛型接口,如Comparable<T>。使用泛型能带来极大的便利性。 在泛型中可以对类型进行限制,如:<T extends Comparable<T>>表示只能传递已经实现了Comparable接口的类型对象,这里是使用extends而不是implement,而且对于接口也只能写一个。<T extends Number>表示只能接收Number类或者其子类的对象。与之相反的边界通配符是super,如:<T extends Phone>表示只能接收类型为Phone或其父类的对象。 在使用extends和super的时候需要特别注意,因为使用它们是有副作用的,比如: List<T extends Number> list = new ArrayList<Number>(); list.add(4.0);//编译错误 list.add(3);//编译错误 因为泛型是为了类型安全设计的,如果往List<? extends Number> list 塞值的话,在取的时候就无法确认它到底是什么类型了,编译器只知道它是Number类型或者它的派生类型,但无法确定是哪个具体类型。通配符T表示其中存的都是同一种类型,因此使用extend下边界的话是无法进行存操作的。同理super下边界是不能取值的。 那什么时候该用extends,什么时候该用super呢?先说结论: PECS原则: 频繁往外读取内容的,适合用上界Extends。 经常往里插入的,适合用下界Super。 3.泛型的好处? 泛型看起来很炫酷,但初看起来,好像没什么卵用?客官且慢,进屋里坐(滑稽)。 使用泛型的好处我们来一项一项列出来: 1,类型安全。 这是最显而易见的,泛型的主要目标是提高 Java 程序的类型安全。通过使用泛型定义的变量的类型限制,可以很容易实现编译期间的类型检测,避免了大量因为使用Object带来的不必要的类型错误。 没有泛型,这些对Object变量的类型假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中),而且每次使用前还需要进行不安全的强制类型转换。 2,代码复用。 泛型的一个很大好处就是增加了代码的复用性,比如上面的 GenericHolder 类,就能存取任意类型的对象,而不用为每种类型写一个包装类。 3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。 至此,本篇讲解完毕,如果想要更好的理解,还需要多写代码,在实践中去应用。 欢迎大家继续关注! 我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan真正重要的东西,用眼睛是看不见的。

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

菜鸟入门【ASP.NET Core】13:Individual authentication 模板、EF Core Migration

Individual authentication 模板 我们首先用VSCode新建一个mvc的网站,这个网站创立的时候回自动为我们创建Identuty Core以及EF Core的代码示例,我们可以用命令 dotnet new mvc --help 来查看一些参数: 由于我们创建mvc项目是默认不带Identity验证的,所以我们要加上下面的 -au|--auth 参数来使用Individual创建带Identity验证的网站 还有一个参数-uld|--use-local-db 参数来使用本地数据库,在VSCode默认的是使用SqlLite,在VS2017中默认使用的是LocalDB。 接下来我们就可以使用以下命令创建包含Identity的mvc网站IdentitySample dotnet new mvc -au Individual -uld --name IdentitySample 创建完成后我们打开创建的项目,然后查看appsettings.json,发现已经默认创建了数据库连接,我们可以将数据库修改成自己的数据库地址 同时我们可以打开Startup.cs可以查看数据库配置以及Identity验证已经帮我们添加好了 接下来我们初始化一下数据库,否则启动之后会报错,所以我们要使用EF Core的Migration命令来初始化数据库。 我们使用的第一个命令是 dotnet ef database update 他会根据当前migration文件夹下的文件来帮我们进行数据库的创建和更新。 我们可以在终端看到执行的sql语句 View Code 然后我们去数据库就可以查看到我们创建的数据库和数据表了 接下来我们运行 dotnet run 来运行我们创建的mvc网站,发现已经实现了登录和注册,以及前后台验证 EF Core Migration 手动命令行的方式 VSCode VS2017 说明 dotnet ef migrations add InitialCreate Add-Migration 对当前EF实体模型增加一个配置文件 dotnet ef database update Update-Database 对当前版本进行更新 dotnet ef migrations remove Remove-Migration 删除最新的Migration dotnet ef database update LastGoodMigration Update-DatabaseLastGoodMigration 对指定版本进行更新 dotnet ef migrations script Script-Migration 对当前更新生成一个sql的脚本,我们可以使用脚本到数据库取执行 接下来我们实践一下,我们来操作一下数据库中的AspNetUsers表,我们打开项目中的ApplicationUser.cs,添加新属性NewColumn 然后我们使用命令dotnet ef migrations add AddNewColumn 生成配置文件 这个时候数据库是没有进行更新的,我们只有执行dotnet ef database update 命令才会更新到数据库 接下来我们继续打开项目中的ApplicationUser.cs,添加新属性Address 然后我们使用命令dotnet ef migrations add AddAddress 生成配置文件 执行dotnet ef database update 命令更新到数据库 接下来我们使用dotnet ef database updateAddNewColumn 就可以将数据库回滚到指定的版本 接下来执行dotnet ef migrations remove 命令会将当前项目之后没有用的配置文件删除,我们这里执行后会将AddAddress配置文件删除 PS C:\Users\Administrator\Desktop\Demo2\IdentitySample> dotnet ef migrations remove info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0] User profile is available. Using 'C:\Users\Administrator\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. info: Microsoft.EntityFrameworkCore.Infrastructure[100403] Entity Framework Core 2.0.0-rtm-26452 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None info: Microsoft.EntityFrameworkCore.Database.Command[200101] Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT OBJECT_ID(N'__EFMigrationsHistory'); info: Microsoft.EntityFrameworkCore.Database.Command[200101] Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT [MigrationId], [ProductVersion] FROM [__EFMigrationsHistory] ORDER BY [MigrationId]; Removing migration '20180105053249_AddAddress'. Reverting model snapshot. Done. 我们可以用dotnet ef migrations script 命令来生成sql脚本,我们可以将sql拷贝出来放在数据库取执行。 IF OBJECT_ID(N'__EFMigrationsHistory') IS NULLBEGIN CREATE TABLE [__EFMigrationsHistory] ( [MigrationId] nvarchar(150) NOT NULL, [ProductVersion] nvarchar(32) NOT NULL, CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) );END; GO CREATE TABLE [AspNetRoles] ( [Id] nvarchar(450) NOT NULL, [ConcurrencyStamp] nvarchar(max) NULL, [Name] nvarchar(256) NULL, [NormalizedName] nvarchar(256) NULL, CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id])); GO CREATE TABLE [AspNetUserTokens] ( [UserId] nvarchar(450) NOT NULL, [LoginProvider] nvarchar(450) NOT NULL, [Name] nvarchar(450) NOT NULL, [Value] nvarchar(max) NULL, CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name])); GO CREATE TABLE [AspNetUsers] ( [Id] nvarchar(450) NOT NULL, [AccessFailedCount] int NOT NULL, [ConcurrencyStamp] nvarchar(max) NULL, [Email] nvarchar(256) NULL, [EmailConfirmed] bit NOT NULL, [LockoutEnabled] bit NOT NULL, [LockoutEnd] datetimeoffset NULL, [NormalizedEmail] nvarchar(256) NULL, [NormalizedUserName] nvarchar(256) NULL, [PasswordHash] nvarchar(max) NULL, [PhoneNumber] nvarchar(max) NULL, [PhoneNumberConfirmed] bit NOT NULL, [SecurityStamp] nvarchar(max) NULL, [TwoFactorEnabled] bit NOT NULL, [UserName] nvarchar(256) NULL, CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id])); GO CREATE TABLE [AspNetRoleClaims] ( [Id] int NOT NULL IDENTITY, [ClaimType] nvarchar(max) NULL, [ClaimValue] nvarchar(max) NULL, [RoleId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE); GO CREATE TABLE [AspNetUserClaims] ( [Id] int NOT NULL IDENTITY, [ClaimType] nvarchar(max) NULL, [ClaimValue] nvarchar(max) NULL, [UserId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE); GO CREATE TABLE [AspNetUserLogins] ( [LoginProvider] nvarchar(450) NOT NULL, [ProviderKey] nvarchar(450) NOT NULL, [ProviderDisplayName] nvarchar(max) NULL, [UserId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY ([LoginProvider], [ProviderKey]), CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE); GO CREATE TABLE [AspNetUserRoles] ( [UserId] nvarchar(450) NOT NULL, [RoleId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY ([UserId], [RoleId]), CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE, CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE); GO CREATE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]); GO CREATE INDEX [IX_AspNetRoleClaims_RoleId] ON [AspNetRoleClaims] ([RoleId]); GO CREATE INDEX [IX_AspNetUserClaims_UserId] ON [AspNetUserClaims] ([UserId]); GO CREATE INDEX [IX_AspNetUserLogins_UserId] ON [AspNetUserLogins] ([UserId]); GO CREATE INDEX [IX_AspNetUserRoles_RoleId] ON [AspNetUserRoles] ([RoleId]); GO CREATE INDEX [IX_AspNetUserRoles_UserId] ON [AspNetUserRoles] ([UserId]); GO CREATE INDEX [EmailIndex] ON [AspNetUsers] ([NormalizedEmail]); GO CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]); GO INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])VALUES (N'00000000000000_CreateIdentitySchema', N'2.0.0-rtm-26452'); GO DROP INDEX [UserNameIndex] ON [AspNetUsers]; GO DROP INDEX [IX_AspNetUserRoles_UserId] ON [AspNetUserRoles]; GO DROP INDEX [RoleNameIndex] ON [AspNetRoles]; GO ALTER TABLE [AspNetUsers] ADD [NewColumn] nvarchar(max) NULL; GO CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]) WHERE [NormalizedUserName] IS NOT NULL; GO CREATE UNIQUE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]) WHERE [NormalizedName] IS NOT NULL; GO ALTER TABLE [AspNetUserTokens] ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE; GO INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])VALUES (N'20180105034732_AddNewColumn', N'2.0.0-rtm-26452'); GO IF OBJECT_ID(N'__EFMigrationsHistory') IS NULL BEGIN CREATE TABLE [__EFMigrationsHistory] ( [MigrationId] nvarchar(150) NOT NULL, [ProductVersion] nvarchar(32) NOT NULL, CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) ); END; GO CREATE TABLE [AspNetRoles] ( [Id] nvarchar(450) NOT NULL, [ConcurrencyStamp] nvarchar(max) NULL, [Name] nvarchar(256) NULL, [NormalizedName] nvarchar(256) NULL, CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id]) ); GO CREATE TABLE [AspNetUserTokens] ( [UserId] nvarchar(450) NOT NULL, [LoginProvider] nvarchar(450) NOT NULL, [Name] nvarchar(450) NOT NULL, [Value] nvarchar(max) NULL, CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name]) ); GO CREATE TABLE [AspNetUsers] ( [Id] nvarchar(450) NOT NULL, [AccessFailedCount] int NOT NULL, [ConcurrencyStamp] nvarchar(max) NULL, [Email] nvarchar(256) NULL, [EmailConfirmed] bit NOT NULL, [LockoutEnabled] bit NOT NULL, [LockoutEnd] datetimeoffset NULL, [NormalizedEmail] nvarchar(256) NULL, [NormalizedUserName] nvarchar(256) NULL, [PasswordHash] nvarchar(max) NULL, [PhoneNumber] nvarchar(max) NULL, [PhoneNumberConfirmed] bit NOT NULL, [SecurityStamp] nvarchar(max) NULL, [TwoFactorEnabled] bit NOT NULL, [UserName] nvarchar(256) NULL, CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id]) ); GO CREATE TABLE [AspNetRoleClaims] ( [Id] int NOT NULL IDENTITY, [ClaimType] nvarchar(max) NULL, [ClaimValue] nvarchar(max) NULL, [RoleId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE ); GO CREATE TABLE [AspNetUserClaims] ( [Id] int NOT NULL IDENTITY, [ClaimType] nvarchar(max) NULL, [ClaimValue] nvarchar(max) NULL, [UserId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); GO CREATE TABLE [AspNetUserLogins] ( [LoginProvider] nvarchar(450) NOT NULL, [ProviderKey] nvarchar(450) NOT NULL, [ProviderDisplayName] nvarchar(max) NULL, [UserId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY ([LoginProvider], [ProviderKey]), CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); GO CREATE TABLE [AspNetUserRoles] ( [UserId] nvarchar(450) NOT NULL, [RoleId] nvarchar(450) NOT NULL, CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY ([UserId], [RoleId]), CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE, CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); GO CREATE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]); GO CREATE INDEX [IX_AspNetRoleClaims_RoleId] ON [AspNetRoleClaims] ([RoleId]); GO CREATE INDEX [IX_AspNetUserClaims_UserId] ON [AspNetUserClaims] ([UserId]); GO CREATE INDEX [IX_AspNetUserLogins_UserId] ON [AspNetUserLogins] ([UserId]); GO CREATE INDEX [IX_AspNetUserRoles_RoleId] ON [AspNetUserRoles] ([RoleId]); GO CREATE INDEX [IX_AspNetUserRoles_UserId] ON [AspNetUserRoles] ([UserId]); GO CREATE INDEX [EmailIndex] ON [AspNetUsers] ([NormalizedEmail]); GO CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]); GO INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) VALUES (N'00000000000000_CreateIdentitySchema', N'2.0.0-rtm-26452'); GO DROP INDEX [UserNameIndex] ON [AspNetUsers]; GO DROP INDEX [IX_AspNetUserRoles_UserId] ON [AspNetUserRoles]; GO DROP INDEX [RoleNameIndex] ON [AspNetRoles]; GO ALTER TABLE [AspNetUsers] ADD [NewColumn] nvarchar(max) NULL; GO CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]) WHERE [NormalizedUserName] IS NOT NULL; GO CREATE UNIQUE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]) WHERE [NormalizedName] IS NOT NULL; GO ALTER TABLE [AspNetUserTokens] ADD CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE; GO INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) VALUES (N'20180105034732_AddNewColumn', N'2.0.0-rtm-26452'); GO

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

杨老师课堂_安卓教程第一篇之入门

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kese7952/article/details/78852369 1.1G-4G g:generation 代 3g:第三代移动通信技术 1g: 大哥大 特点:安全性差,容易受干扰,通话不稳定,不能发短信 2g:小灵通等功能机 特点:通话质量稳定,可以发短信彩信,简单wap上网,支持一些简单的java游戏 3g:android ios 等智能手机 特点:上网快了很多,能够处理图像,音乐,视频流等多种媒体形式. 4g: lte , long time evolution 特点: 上网速度更快,100M带宽。 区别:网速不同,处理的内容不同 2.Android操作系统介绍 android系统是由安迪鲁宾团队开发的,最初用于数码相机,2005.08被google收购 android名字是因为安迪鲁宾喜欢一个游戏的人物--大瓢虫 android图标:上厕所的灵感 android应用范围:手机,平板,智能家居,穿戴设备。 3.Android进化史 2.3 比较稳定的一个版本 ,NFC 近场通信技术 3.0 专为平板设计 4.1.2 4.0后比较稳定的版本,4.*同时支持平板和手机 5.0 新特性 4.Android系统架构(重点) 分层的架构 JNI java native interface 1.application :应用层 ; java 2.application framework :应用框架层 , java+JNI 3.libraries 和 dalvik : 函数库和虚拟机层, c/c++ 4.linux kernel : linux 内核驱动层, c 5.两种虚拟机的不同 (熟练了解) 版权问题: jvm : java虚拟机 sun dvm: dalvik虚拟机 google 区别: 1.基于的架构不同,jvm 基于栈架构,栈是位于内存上的一个空间,执行指令操作,需要向cpu寻址; dvm 基于寄存器架构,寄存器是cpu的一个组成部分,执行指令操作无需寻址直接执行。 2.执行文件的格式不同,jvm执行的是多个.class文件。 dvm执行的是一个.dex文件 6.art 模式 android runtime 空间换时间的概念。 art:程序在安装时需要预编译读取,将代码转换为机器码,好处:程序运行时,无需时时转换,运行速度快 ; 缺点:安装时间稍长,由于转换机器码,所以占用略高的存储空间。 7.开发环境的搭建 1.JDK 32 64 2.开发工具,eclipse , android studio 3.android sdk , sdk: soft developer kit adt : android develper tool bundle:集 apilevel : 19 4.4版本 18 4.3 11 3.0 10 2.3 8 2.2 aapt:android application package tool adb : 建立电脑与手机之间的链接 dx.bat : 将多个.class 打包成一个.dex sdk下的目录: add-ons:预留的一个附加目录 build-tools:构建工具目录 docs: 文档目录 extras:开发中额外提供的一些工具及jar platforms: 不同版本android的核心jar包 platforms-tools:平台一些相关的工具 sources:源码 system-images:系统镜像文件 tools:开发中使用的一些工具,如9path,做图片拉伸适配的。 8.Android SDKManager介绍 9.模拟器的简介及创建 常用的屏幕分辨率: 3.2 ----- QVGA ------320*480 3.7 ----- WVGA ------480*800 4.7 -----WXGA ------1280*720 10.DDMS介绍 ddms: dalvik debug manitor services devices: 列出当前电脑所连接的所有android设备,及android设备运行的进程,结束一个进程,设置程序为debug模式,截屏。 logcat: 会打印系统运行过程中所有日志信息。 file explorer: 列出当前设备所有目录。 /data/app:安装的第三方apk都在此目录 /system/app: 系统预装应用apk在此目录 /data/data:应用的私有目录,系统每安装一个新的应用程序,都会在此目录创建该应用包名的文件,用来存放该应用的私有数据,当应用卸载时,该包名的文件夹也会被删除。 /sdcard :外部存储目录,一般会链接指向到另一个目录,用来存放大数据。 11.创建HelloWorld工程 部署运行的三种方式: 1.右击工程,run as 2.工具栏的按钮 3.快捷键:ctrl+F11 12.android工程目录结构 img: ../img/a.jpg src: java 源码代码 gen: 自动生成的文件目录,不需要修改; R类 ,是对资源文件的一个索引 android核心jar包和第三方jar包 assets:资产目录,用来存放程序运行过程中所需要的一些工具,数据库 bin:编译打包过程中产生的目录 libs: res: drawable:图片资源 layout:布局资源 menu:菜单资源 values: demins 长度相关, string:字符串 style 样式 androidManifest.xml: 清单文件, 包名,版本号,版本名称,最低运行版本,图标,应用名称,程序的入口activity, 还可以配置应用程序使用的权限信息。 13.Android的打包过程 jdk dx.bat aapt 签名jarsigner .java -----> .class ------>.dex(res,assets,androidmanifest.xml)------->.apk--------->final apk 14.ADB指令练习 (重点) ADB :android debug bridge 建立手机与电脑直接的连接 adb运行的端口号是5037 环境变量的配置:C:\kaifa\adt-bundle-windows-x86_64_20140101\sdk\platform-tools 1.adb devices :列出当前电脑所连接的android设备 2.adb push pc_path phone_path :将电脑端文件放到手机端 3.adb pull phone_paht pc_path :将手机端文件拉到电脑端 4.adb install [-r] apkpath ; 安装一个电脑端的apk文件。-r:强制安装 5.adb uninstall packagename; 卸载一个应用 6.adb kill-server : 结束adb服务的链接 7.adb start-server :开启adb服务的链接 8.netstat -oan 查看端口: 查看端口 9.adb shell:进入当前设备linux环境下 10.adb shell + ls -l :查看当前设备的目录结构 11.adb shell+ logcat :查看系统运行中的日志信息 注意: 如果当前电脑链接的是多台android设备,需要指定操作的是哪台设备,需要在adb后加 -s 设备序列号。 15.电话拨号器(重点) 1.产品经理: 需求分析文档,设计原型图 2.UI工程师: 设计UI界面 3.架构师: 写架构,接口文档 4.码农: 服务端,客户端 1.写布局界面 2.写业务逻辑 1.通过布局文件中对控件配置的id,在activity中可以获取控件的对象,Edittext Button findViewById(int id); 2.为按钮设置点击事件 bt_callphone.setOnclickListener( OnclickListener listener); 3.在点击事件的onclick方法中,找到用户输入的电话号码 4.创建一个Intent对象 Intent intent = new Intent(); 5.为Intent对象设置一个打电话的动作 intent.setAciton(Intent.ACTION_CALL); 6.位Intent对象设置一个数据 intent.setData(Uri.parser("tel:"+number)); 7.启动Intent对象 startActivity(intent); 8.在androidmanifest.xml中设置一个打电话的权限 <uses-permission android:name="android.permission.CALL_PHONE"/> 5.测试工程师: 测试应用 6.运营人员: 写软文,上传应用 7.商务合作: 买量,买广告位,卖广告位 16.四种方法写按钮点击事件 17.Android中常用布局 (多练习) table div+css

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

Hadoop MapReduce编程 API入门系列之挖掘气象数据版本2(十)

这篇博文,包括了,实际生产开发非常重要的,单元测试和调试代码。这里不多赘述,直接送上代码。 MRUnit 框架 MRUnit是Cloudera公司专为Hadoop MapReduce写的单元测试框架,API非常简洁实用。MRUnit针对不同测试对象使用不同的Driver: MapDriver:针对单独的Map测试 ReduceDriver:针对单独的Reduce测试 MapReduceDriver:将map和reduce串起来测试 PipelineMapReduceDriver:将多个MapReduce对串志来测试 记得,将这个jar包,放到工程项目里。我这里是在工程项目的根目录下的lib下。 代码版本2 编写TemperatureMapperTest.java的代码。 编译,出现以下,则说明无误。 在test()方法中,withInput的key/value参数分别为偏移量和一行气象数据,其类型要与TemperatureMapper的输入类型一致即为LongWritable和Text。 withOutput的key/value参数分别是我们期望输出的new Text("03103")和new IntWritable(200),我们要达到的测试效果就是我们的期望输出结果与 TemperatureMapper 的实际输出结果一致。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 Mapper 测试成功了。 创建TemperatureReduceTest.java,来对Reduce进行测试。 在test()方法中,withInput的key/value参数分别为new Text(key)和List类型的集合values。withOutput 的key/value参数分别是我们所期望输出的new Text(key)和new IntWritable(150),我们要达到的测试效果就是我们的期望输出结果与TemperatureReducer实际输出结果一致。 编写TemperatureReduceTest.java的代码。 编译,出现以下,则说明无误。 Reducer 端的单元测试,鼠标放在 TemperatureReduceTest 类上右击,选择 Run As ——> JUnit test,运行结果如下所示。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 Reducer 测试成功了。 MapReduce 单元测试 把 Mapper 和 Reducer 集成起来的测试案例代码如下。 创建TemperatureTest.java,来进行测试。 在 test() 方法中,withInput添加了两行测试数据line和line2,withOutput 的key/value参数分别为我们期望的输出结果new Text("03103")和new IntWritable(150)。我们要达到的测试效果就是我们期望的输出结果与Temperature实际的输出结果一致。 编写TemperatureTest.java的代码。 编译,出现以下,则说明无误。 Reducer 端的单元测试,鼠标放在 TemperatureTest.java类上右击,选择 Run As ——> JUnit test,运行结果如下所示。 测试方法为 test() 方法,左边的对话框里显示"Runs:1/1,Errors:0,Failures:0",说明 MapReduce 测试成功了。 Temperature.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import org.apache.hadoop.io.IntWritable; 6 import org.apache.hadoop.io.LongWritable; 7 import org.apache.hadoop.io.Text; 8 import org.apache.hadoop.mapreduce.Mapper; 9 import org.apache.hadoop.mapreduce.lib.input.FileSplit; 10 import org.apache.hadoop.conf.Configuration; 11 import org.apache.hadoop.conf.Configured; 12 import org.apache.hadoop.fs.FileSystem; 13 import org.apache.hadoop.fs.Path; 14 import org.apache.hadoop.io.IntWritable; 15 import org.apache.hadoop.io.Text; 16 import org.apache.hadoop.mapreduce.Job; 17 import org.apache.hadoop.mapreduce.Mapper; 18 import org.apache.hadoop.mapreduce.Reducer; 19 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 20 import org.apache.hadoop.mapreduce.lib.input.FileSplit; 21 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 22 import org.apache.hadoop.util.Tool; 23 import org.apache.hadoop.util.ToolRunner; 24 25 26 /* 27 Hadoop内置的数据类型: 28 BooleanWritable:标准布尔型数值 29 ByteWritable:单字节数值 30 DoubleWritable:双字节数值 31 FloatWritable:浮点数 32 IntWritable:整型数 33 LongWritable:长整型数 34 Text:使用UTF8格式存储的文本 35 NullWritable:当<key, value>中的key或value为空时使用 36 */ 37 38 39 /** 40 * 统计美国每个气象站30年来的平均气温 41 * 1、编写map()函数 42 * 2、编写reduce()函数 43 * 3、编写run()执行方法,负责运行MapReduce作业 44 * 4、在main()方法中运行程序 45 * 46 * @author zhouls 47 * 48 */ 49 //继承Configured类,实现Tool接口 50 public class Temperature extends Configured implements Tool{ 51 public static class TemperatureMapper extends Mapper<LongWritable, Text, Text, IntWritable>{ 52 //输入的key,输入的value,输出的key,输出的value 53 //输入的LongWritable键是某一行起始位置相对于文件起始位置的偏移量,不过我们不需要这个信息,所以将其忽略。 54 55 // 在这种情况下,我们将气象站id按 Text 对象进行读/写(因为我们把气象站id当作键),将气温值封装在 IntWritale 类型中。只有气温数据不缺失,这些数据才会被写入输出记录中。 56 57 58 // map 函数的功能仅限于提取气象站和气温信息 59 60 /** 61 * @function Mapper 解析气象站数据 62 * @input key=偏移量 value=气象站数据 63 * @output key=weatherStationId value=temperature 64 */ 65 public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{ 66 //map()函数还提供了context实例,用于键值对的输出 或者说 map() 方法还提供了 Context 实例用于输出内容的写入 67 68 // 就本示例来说,输入键是一个长整数偏移量,输入值是一行文本,输出键是气象站id,输出值是气温(整数)。 69 // 同时context作为了map和reduce执行中各个函数的一个桥梁,这个设计和Java web中的session对象、application对象很相似 70 71 72 //第一步,我们将每行气象站数据转换为每行的String类型 73 String line = value.toString(); //每行气象数据 74 // values是1980 12 01 00 78 -17 10237 180 21 1 0 0 75 // line是"1980 12 01 00 78 -17 10237 180 21 1 0 0" 76 77 78 //第二步:提取气温值 79 int temperature = Integer.parseInt(line.substring(14, 19).trim());//每小时气温值 80 //需要转换为整形,截取第14位到19位,从第0位开始,trim()的功能是去掉首尾空格。 81 //substring()方法截取我们业务需要的值 82 83 // substring(start, stop)其内容是从 start 处到 stop-1 处的所有字符,其长度为 stop 减 start。 84 85 // 如Hello world! 若是substring(3,7) 则是lo w 86 87 // Integer.parseInt() 返回的是一个int的值。在这里, 给temperature 88 89 // new Integer.valueof()返回的是Integer的对象。 90 // Integer.parseInt() 返回的是一个int的值。 91 // new Integer.valueof().intValue();返回的也是一个int的值。 92 93 94 95 96 97 // 1980 12 01 00 78 -17 10237 180 21 1 0 0 98 //78是气温值 99 100 // temperature是78 101 102 // 30yr_03103.dat 103 // 30yr_03812.dat 104 // 30yr_03813.dat 105 // 30yr_03816.dat 106 // 30yr_03820.dat 107 // 30yr_03822.dat 108 // 30yr_03856.dat 109 // 30yr_03860.dat 110 // 30yr_03870.dat 111 // 30yr_03872.dat 112 113 114 // (0,1985 07 31 02 200 94 10137 220 26 1 0 -9999) 115 // (62,1985 07 31 03 172 94 10142 240 0 0 0 -9999) 116 // (124,1985 07 31 04 156 83 10148 260 10 0 0 -9999) 117 // (186,1985 07 31 05 133 78 -9999 250 0 -9999 0 -9999) 118 // (248,1985 07 31 06 122 72 -9999 90 0 -9999 0 0) 119 // (310,1985 07 31 07 117 67 -9999 60 0 -9999 0 -9999) 120 // (371,1985 07 31 08 111 61 -9999 90 0 -9999 0 -9999) 121 // (434,1985 07 31 09 111 61 -9999 60 5 -9999 0 -9999) 122 // (497,1985 07 31 10 106 67 -9999 80 0 -9999 0 -9999) 123 // (560,1985 07 31 11 100 56 -9999 50 5 -9999 0 -9999) 124 125 // (03103,[200,172,156,133,122,117,111,111,106,100]) 126 127 // 根据自己业务需要 , map 函数的功能仅限于提取气象站和气温信息 128 129 130 // 1998 #year 131 // 03 #month 132 // 09 #day 133 // 17 #hour 134 // 11 #temperature 感兴趣 135 // -100 #dew 136 // 10237 #pressure 137 // 60 #wind_direction 138 // 72 #wind_speed 139 // 0 #sky_condition 140 // 0 #rain_1h 141 // -9999 #rain_6h 142 143 144 if (temperature != -9999){//过滤无效数据 145 //第三步:提取气象站编号 146 //获取输入分片 147 FileSplit fileSplit = (FileSplit) context.getInputSplit();//提取问加你输入分片,并转换类型 148 // 即由InputSplit -> FileSplit 149 150 // context.getInputSplit() 151 // (FileSplit) context.getInputSplit()这是强制转换 152 // fileSplit的值是file:/D:/Code/MyEclipseJavaCode/myMapReduce/data/temperature/30yr_03870.dat:0+16357956 153 // 即,读的是30yr_03870.dat这个文件 154 155 156 //然后通过文件名称提取气象站编号 157 String weatherStationId = fileSplit.getPath().getName().substring(5, 10);//通过文件名称提取气象站id 158 //首先通过文件分片fileSplit来获取文件路径,然后再获取文件名字,然后截取第5位到第10位就可以得到气象站 编号 159 // fileSplit.getPath() 160 // fileSplit.getPath().getName() 161 162 // 30yr_03870.dat 我们只需获取03870就是气象站编号 163 164 // fileSplit.getPath().getName().substring(5, 10) //从0开始,即第5个开始截取,到第10个为止,第10个没有拿到,所以为03870 165 // weatherStationId是03870 166 167 168 169 context.write(new Text(weatherStationId), new IntWritable(temperature));//写入weatherStationId是k2,temperature是v2 170 // context.write(weatherStationId,temperature);等价 ,但是若是直接这样写会出错,因为, weatherStationId是String类型,注意与Text类型还是有区别的! 171 //气象站编号,气温值 172 } 173 } 174 } 175 176 177 178 public static class TemperatureReducer extends Reducer< Text, IntWritable, Text, IntWritable>{ 179 private IntWritable result = new IntWritable();//存取结果 180 //因为气温是IntWritable类型 181 public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{ 182 // Iterable<IntWritable> values是iterable(迭代器)变量 183 184 185 // Iterable<IntWritable> values和IntWritable values这样有什么区别? 186 // 前者是iterable(迭代器)变量,后者是intwriteable(int的封装)变量 187 188 189 // Iterable<IntWritable> values 190 // 迭代器,valuses是 iterable(迭代器)变量,类型是IntWritable 191 192 193 //reduce输出的key,key的集合,context的实例 194 //第一步:统计相同气象站的所有气温 195 int sum = 0; 196 int count = 0; 197 for (IntWritable val : values) //星型for循环来循环同一个气象站的所有气温值,即将values的值一一传给IntWritable val 198 // IntWritable val是IntWritable(int的封装)变量 199 200 {//对所有气温值累加 201 sum += val.get();//去val里拿一个值,就sum下 202 203 // val.get()去拿值 204 205 count++; 206 } 207 result.set(sum / count);//设为v3 208 // result.set(sum / count)去设置,将sum / count的值,设给result 209 // sum是21299119 count是258616 = 82.3580869 210 211 212 context.write(key,result);//写入key是k3,result是v3 213 } 214 } 215 216 217 218 public int run(String[] args) throws Exception{ 219 // TODO Auto-generated method stub 220 //第一步:读取配置文件 221 Configuration conf = new Configuration();//程序里,只需写这么一句话,就会加载到hadoop的配置文件了 222 //Configuration类代表作业的配置,该类会加载mapred-site.xml、hdfs-site.xml、core-site.xml等配置文件。 223 224 // new Configuration() 225 226 //第二步:输出路径存在就先删除 227 Path mypath = new Path(args[1]);//定义输出路径的Path对象,mypath 228 229 230 // new Path(args[1])将args[1]的值,给mypath 231 232 FileSystem hdfs = mypath.getFileSystem(conf);//程序里,只需写这么一句话,就可以获取到文件系统了。 233 //FileSystem里面包括很多系统,不局限于hdfs,是因为,程序读到conf,哦,原来是hadoop集群啊。这时,才认知到是hdfs 234 235 if (hdfs.isDirectory(mypath))//如果输出路径存在 236 { 237 hdfs.delete(mypath, true);//则就删除 238 } 239 //第三步:构建job对象 240 Job job = new Job(conf, "temperature");//新建一个任务,job名字是tempreature 241 242 // new Job(conf, "temperature")有这么个构造方法 243 244 job.setJarByClass(Temperature.class);// 设置主类 245 //通过job对象来设置主类Temperature.class 246 247 //第四步:指定数据的输入路径和输出路径 248 FileInputFormat.addInputPath(job, new Path(args[0]));// 输入路径,args[0] 249 FileOutputFormat.setOutputPath(job, new Path(args[1]));// 输出路径,args[1] 250 251 //第五步:指定Mapper和Reducer 252 job.setMapperClass(TemperatureMapper.class);// Mapper 253 job.setReducerClass(TemperatureReducer.class);// Reducer 254 255 //第六步:设置map函数和reducer函数的输出类型 256 job.setOutputKeyClass(Text.class); 257 job.setOutputValueClass(IntWritable.class); 258 259 //第七步:提交作业 260 return job.waitForCompletion(true)?0:1;//提交任务 261 } 262 263 264 /** 265 * @function main 方法 266 * @param args 267 * @throws Exception 268 */ 269 public static void main(String[] args) throws Exception { 270 //第一步 271 // String[] args0 = 272 // { 273 // "hdfs://djt002:9000/inputData/temperature/", 274 // "hdfs://djt002:9000/outData/temperature/" 275 // }; 276 277 String[] args0 = {"./data/temperature/","./out/temperature/"}; 278 279 // args0是输入路径和输出路径的属组 280 281 //第二步 282 int ec = ToolRunner.run(new Configuration(), new Temperature(), args0); 283 284 // ToolRunner.run(new Configuration(), new Temperature(), args0)有这么一个构造方法 285 286 //第一个参数是读取配置文件,第二个参数是主类Temperature,第三个参数是输入路径和输出路径的属组 287 System.exit(ec); 288 } 289 290 } 291 TemperatureMapperTest.java 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 6 import org.apache.hadoop.io.IntWritable; 7 import org.apache.hadoop.io.LongWritable; 8 import org.apache.hadoop.io.Text; 9 import org.apache.hadoop.mapreduce.Mapper; 10 import org.apache.hadoop.mrunit.mapreduce.MapDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Mapper 端的单元测试,这里用MRUnit框架,需要使用mrunit-hadoop.jar 16 */ 17 @SuppressWarnings("all")//告诉编译器忽略指定的警告,不用在编译完成后出现警告信息 18 public class TemperatureMapperTest{ 19 private Mapper mapper;//定义一个Mapper对象,是mapper 20 private MapDriver driver;//定义一个MapDriver对象,是driver,因为是要MapDriver去做! 21 22 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 23 public void init(){//初始化方法init 24 mapper = new Temperature.TemperatureMapper();//实例化一个Temperature中的TemperatureMapper对象 25 driver = new MapDriver(mapper);//实例化MapDriver对象 26 } 27 28 29 @Test//@Test是测试方法提示符,一般与@Before组合使用 30 public void test() throws IOException{ 31 //因为测试的是Map 32 //输入一行测试数据 33 String line = "1985 07 31 02 200 94 10137 220 26 1 0 -9999"; 34 driver.withInput(new LongWritable(), new Text(line))//withInput方法是第一行输入 跟TemperatureMapper输入类型一致 35 .withOutput(new Text("03103"), new IntWritable(200))//withOutput方法是输出 跟TemperatureMapper输出类型一致 36 .runTest();//runTest方法是调用运行方法 37 } 38 } TemperatureReduceTest.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import java.util.ArrayList; 6 import java.util.List; 7 import org.apache.hadoop.io.IntWritable; 8 import org.apache.hadoop.io.Text; 9 import org.apache.hadoop.mapreduce.Reducer; 10 import org.apache.hadoop.mrunit.mapreduce.ReduceDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Reducer 单元测试,这里用MRUnit框架,需要使用mrunit-hadoop.jar 16 */ 17 @SuppressWarnings("all")//告诉编译器忽略指定的警告,不用在编译完成后出现警告信息 18 public class TemperatureReduceTest{ 19 private Reducer reducer;//定义一个Reducer对象,是 reducer 20 private ReduceDriver driver;//定义一个ReduceDriver对象,是driver,因为是要ReduceDriver去做! 21 22 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 23 public void init(){//初始化方法init 24 reducer = new Temperature.TemperatureReducer();//实例化一个Temperature中的TemperatureReducer对象 25 driver = new ReduceDriver(reducer);//实例化ReduceDriver对象 26 } 27 28 @Test//@Test是测试方法提示符,一般与@Before搭配使用 29 public void test() throws IOException{//为了模拟在reduer端单元测试,所以需如下 30 String key = "03103";//声明一个key值 31 List values = new ArrayList(); 32 values.add(new IntWritable(200));//添加第一个value值 33 values.add(new IntWritable(100));//添加第二个value值 34 driver.withInput(new Text(key), values)//withInput方法是第一行输入 跟TemperatureReducer输入类型一致 35 .withOutput(new Text(key), new IntWritable(150))//withOutput方法是输出 跟TemperatureReducer输出类型一致 36 .runTest();//runTest方法是调用运行方法 37 } 38 } TemperatureTest.java代码 1 package zhouls.bigdata.myMapReduce.TemperatureTest; 2 3 import java.io.IOException; 4 5 import org.apache.hadoop.io.IntWritable; 6 import org.apache.hadoop.io.LongWritable; 7 import org.apache.hadoop.io.Text; 8 import org.apache.hadoop.mapreduce.Mapper; 9 import org.apache.hadoop.mapreduce.Reducer; 10 import org.apache.hadoop.mrunit.mapreduce.MapReduceDriver; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 /** 15 * Mapper 和 Reducer 集成起来测试,这里用MRUnit框架 16 */ 17 @SuppressWarnings("all") 18 public class TemperatureTest { 19 private Mapper mapper;//定义一个Mapper对象 20 private Reducer reducer;//定义一个Reducer对象 21 private MapReduceDriver driver;//定义一个MapReduceDriver对象是driver,因为是对map和reducer联合起来测试,所以需要MapReduceDriver去做! 22 23 @Before//@Before是在所拦截单元测试方法执行之前执行一段逻辑,读艾特Before 24 public void init(){ //初始化方法init 25 mapper = new Temperature.TemperatureMapper();//实例化一个Temperature中的TemperatureMapper对象 26 reducer = new Temperature.TemperatureReducer();//实例化一个Temperature中的TemperatureReducer对象 27 driver = new MapReduceDriver(mapper, reducer);//实例化MapReduceDriver对象 28 } 29 30 @Test//@Test是测试方法提示符 31 public void test() throws RuntimeException, IOException{ 32 //输入两行行测试数据 33 String line = "1985 07 31 02 200 94 10137 220 26 1 0 -9999"; 34 String line2 = "1985 07 31 11 100 56 -9999 50 5 -9999 0 -9999"; 35 driver.withInput(new LongWritable(), new Text(line))//withInput方法是第一行输入 跟TemperatureMapper输入类型一致 36 .withInput(new LongWritable(), new Text(line2))//第二行输入 37 .withOutput(new Text("03103"), new IntWritable(150))//withOutput方法是输出 跟TemperatureReducer输出类型一致 38 .runTest();//runTest方法是调用运行方法 39 } 40 } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6164003.html,如需转载请自行联系原作者

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

Hadoop MapReduce编程 API入门系列之压缩和计数器(三十)

生成的结果,作为输入源。 代码 package zhouls.bigdata.myMapReduce.ParseTVDataCompressAndCounter; import java.net.URI; import java.util.List; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.io.compress.GzipCodec; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; /** * * @function 统计无效数据和对输出结果进行压缩 * @author 小讲 * */ public class CompressAndCounter extends Configured implements Tool { // 定义枚举对象 public static enum LOG_PROCESSOR_COUNTER { BAD_RECORDS }; /** * * @function Mapper 解析数据,统计无效数据,并输出有效数据 * */ public static class CompressAndCounterMap extends Mapper<LongWritable, Text, Text, Text> { protected void map(LongWritable key, Text value, Context context) throws java.io.IOException, InterruptedException { // 解析每条机顶盒记录,返回list集合 List<String> list = ParseTVData.transData(value.toString()); //调用ParseTVData.java下的transData方法 int length = list.size(); // 无效记录 if (length == 0) { // 动态自定义计数器 context.getCounter("ErrorRecordCounter", "ERROR_Record_TVData").increment(1); // 枚举声明计数器 context.getCounter(LOG_PROCESSOR_COUNTER.BAD_RECORDS).increment(1); } else { for (String validateRecord : list) { //输出解析数据 context.write(new Text(validateRecord), new Text("")); } } } } /** * @function 任务驱动方法 * */ @Override public int run(String[] args) throws Exception { // TODO Auto-generated method stub //读取配置文件 Configuration conf = new Configuration(); //文件系统接口 URI uri = new URI("hdfs://HadoopMaster:9000"); //输出路径 Path mypath = new Path(args[1]); // 创建FileSystem对象 FileSystem hdfs = FileSystem.get(uri, conf); if (hdfs.isDirectory(mypath)) { //删除已经存在的文件路径 hdfs.delete(mypath, true); } Job job = new Job(conf, "CompressAndCounter");//新建一个任务 job.setJarByClass(CompressAndCounter.class);//设置主类 job.setMapperClass(CompressAndCounterMap.class);//只有 Mapper job.setOutputKeyClass(Text.class);//输出 key 类型 job.setOutputValueClass(Text.class);//输出 value 类型 FileInputFormat.addInputPath(job, new Path(args[0]));//输入路径 FileOutputFormat.setOutputPath(job, new Path(args[1]));//输出路径 FileOutputFormat.setCompressOutput(job, true);//对输出结果设置压缩 FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);//设置压缩类型 job.waitForCompletion(true);//提交任务 return 0; } /** * @function main 方法 * @param args 输入 输出路径 * @throws Exception */ public static void main(String[] args) throws Exception { String[] date = {"20120917","20120918","20120919","20120920","20120921","20120922","20120923"}; int ec = 1; for(String dt:date) { String[] args0 = { "hdfs://HadoopMaster:9000/middle/tv/"+dt+".txt", "hdfs://HadoopMaster:9000/junior/tvCompressResult/"+dt }; // String[] args0 = { "./data/compressAndCounter/"+dt+".txt", // "hdfs://HadoopMaster:9000/junior/tvCompressResult/"+dt }; ec = ToolRunner.run(new Configuration(), new CompressAndCounter(), args0); } System.exit(ec); } } package zhouls.bigdata.myMapReduce.ParseTVDataCompressAndCounter; import java.util.ArrayList; import java.util.List; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * * @function 解析数据 * * */ public class ParseTVData { /** * @function 使用 Jsoup 工具,解析输入数据, * @param text * @return list */ public static List<String> transData(String text) { List<String> list = new ArrayList<String>(); Document doc; String rec = ""; try { doc = Jsoup.parse(text);// jsoup解析数据 Elements content = doc.getElementsByTag("WIC"); String num = content.get(0).attr("cardNum");// 记录编号 if (num == null || num.equals("")) { num = " "; } String stbNum = content.get(0).attr("stbNum");// 机顶盒号 if (stbNum.equals("")) { return list; } String date = content.get(0).attr("date");// 日期 Elements els = doc.getElementsByTag("A"); if (els.isEmpty()) { return list; } for (Element el : els) { String e = el.attr("e");// 结束时间 String s = el.attr("s");// 开始时间 String sn = el.attr("sn");// 频道名称 rec = stbNum + "@" + date + "@" + sn + "@" + s + "@" + e; list.add(rec); } } catch (Exception e) { System.out.println(e.getMessage()); return list; } return list; } } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6171823.html,如需转载请自行联系原作者

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

Android GIS开发系列-- 入门季(6)GraphicsLayer添加文字与图片标签

一、GraphicsLayer添加图片 GraphicLayer添加图片Graphic,要用到PictureMarkerSymbol,也是样式的一种。添加代码如下: Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher); PictureMarkerSymbol pictureMarkerSymbol = new PictureMarkerSymbol(this, drawable); Graphic graphic = new Graphic(new Point(113,22), pictureMarkerSymbol); graphicsLayer.addGraphic(graphic); 添加图片效果如下: 二、GraphicsLayer添加文字 GraphicLayer添加文字,要利用TextSymbol。代码如下 TextSymbol textSymbol = new TextSymbol(20,"我是文字" , Color.RED); Graphic graphic = new Graphic(new Point(113,22), textSymbol ); graphicsLayer.addGraphic(graphic); 上面的代码没有设置使用哪种字体,Arcgis会默认的字体。如果 我们想添加中文,要设置textSymbol.setFontFamily("DroidSansFallback.ttf");, 为textSymbol设置字体,arcgis会到system\fonts下找到此字体。但有时我们设置此代码时中文并没有出现,可能会有乱码等,是因为系统的fon ts下面并没有此字体,解决的办法有,将手机root,将DroidSansFallback.ttf字体添加到system\fonts下。华为的手机是有此字体的,而三星5.0以 上则没有此字体,在华为手机上还有一款中文DroidSansChinese.ttf字体arcgis也是支持的。而三星5.0以上的中文字体好像不是ttf字体,而是otf字体 ,Arcgis好像不支持,本人也没有找到好的解决办法。 没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。 本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/7751888.html ,如需转载请自行联系原作者

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

Hadoop MapReduce编程 API入门系列之挖掘气象数据版本3(九)

代码 package zhouls.bigdata.myMapReduce.weather; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import org.apache.hadoop.io.WritableComparable; public class MyKey implements WritableComparable<MyKey>{ //WritableComparable,实现这个方法,要多很多 //readFields是读入,write是写出 private int year; private int month; private double hot; public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public double getHot() { return hot; } public void setHot(double hot) { this.hot = hot; }//这一大段的get和set,可以右键,source,产生get和set,自动生成。 public void readFields(DataInput arg0) throws IOException { //反序列化 this.year=arg0.readInt(); this.month=arg0.readInt(); this.hot=arg0.readDouble(); } public void write(DataOutput arg0) throws IOException { //序列化 arg0.writeInt(year); arg0.writeInt(month); arg0.writeDouble(hot); } //判断对象是否是同一个对象,当该对象作为输出的key public int compareTo(MyKey o) { int r1 =Integer.compare(this.year, o.getYear());//比较当前的年和你传过来的年 if(r1==0){ int r2 =Integer.compare(this.month, o.getMonth()); if(r2==0){ return Double.compare(this.hot, o.getHot()); }else{ return r2; } }else{ return r1; } } } package zhouls.bigdata.myMapReduce.weather; import org.apache.hadoop.io.DoubleWritable; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.mapreduce.lib.partition.HashPartitioner; public class MyPartitioner extends HashPartitioner<MyKey, DoubleWritable>{//这里就是洗牌 //执行时间越短越好 public int getPartition(MyKey key, DoubleWritable value, int numReduceTasks) { return (key.getYear()-1949)%numReduceTasks;//对于一个数据集,找到最小,1949 } } //1949-10-01 14:21:02 34c //1949-10-02 14:01:02 36c //1950-01-01 11:21:02 32c //1950-10-01 12:21:02 37c //1951-12-01 12:21:02 23c //1950-10-02 12:21:02 41c //1950-10-03 12:21:02 27c //1951-07-01 12:21:02 45c //1951-07-02 12:21:02 46c //1951-07-03 12:21:03 47c package zhouls.bigdata.myMapReduce.weather; import org.apache.hadoop.io.WritableComparable; import org.apache.hadoop.io.WritableComparator; public class MySort extends WritableComparator{ public MySort(){ super(MyKey.class,true);//把MyKey传进了 } public int compare(WritableComparable a, WritableComparable b) {//这是排序的精髓 MyKey k1 =(MyKey) a; MyKey k2 =(MyKey) b; int r1 =Integer.compare(k1.getYear(), k2.getYear()); if(r1==0){//年相同 int r2 =Integer.compare(k1.getMonth(), k2.getMonth()); if(r2==0){//月相同 return -Double.compare(k1.getHot(), k2.getHot());//比较气温 }else{ return r2; } }else{ return r1; } } } package zhouls.bigdata.myMapReduce.weather; import org.apache.hadoop.io.WritableComparable; import org.apache.hadoop.io.WritableComparator; public class MyGroup extends WritableComparator{ public MyGroup(){ super(MyKey.class,true);//把MyKey传进了 } public int compare(WritableComparable a, WritableComparable b) {//这是分组的精髓 MyKey k1 =(MyKey) a; MyKey k2 =(MyKey) b; int r1 =Integer.compare(k1.getYear(), k2.getYear()); if(r1==0){ return Integer.compare(k1.getMonth(), k2.getMonth()); }else{ return r1; } } } package zhouls.bigdata.myMapReduce.weather; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.DoubleWritable; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class RunJob { // 1949-10-01 14:21:02 34c WeatherMapper // 1949-10-02 14:01:02 36c // 1950-01-01 11:21:02 32c 分区在MyPartitioner.java // 1950-10-01 12:21:02 37c // 1951-12-01 12:21:02 23c 排序在MySort.java // 1950-10-02 12:21:02 41c // 1950-10-03 12:21:02 27c 分组在MyGroup.java // 1951-07-01 12:21:02 45c // 1951-07-02 12:21:02 46c 再,WeatherReducer // 1951-07-03 12:21:03 47c //key:每行第一个隔开符(制表符)左边为key,右边为value 自定义类型MyKey,洗牌, static class WeatherMapper extends Mapper<Text, Text, MyKey, DoubleWritable>{ SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); NullWritable v =NullWritable.get(); // 1949-10-01 14:21:02是自定义类型MyKey,即key // 34c是DoubleWritable,即value protected void map(Text key, Text value,Context context) throws IOException, InterruptedException { try { Date date =sdf.parse(key.toString()); Calendar c =Calendar.getInstance(); //Calendar 类是一个抽象类,可以通过调用 getInstance() 静态方法获取一个 Calendar 对象, //此对象已由当前日期时间初始化,即默认代表当前时间,如 Calendar c = Calendar.getInstance(); c.setTime(date); int year =c.get(Calendar.YEAR); int month =c.get(Calendar.MONTH); double hot =Double.parseDouble(value.toString().substring(0, value.toString().lastIndexOf("c"))); MyKey k =new MyKey(); k.setYear(year); k.setMonth(month); k.setHot(hot); context.write(k, new DoubleWritable(hot)); } catch (Exception e) { e.printStackTrace(); } } } static class WeatherReducer extends Reducer<MyKey, DoubleWritable, Text, NullWritable>{ protected void reduce(MyKey arg0, Iterable<DoubleWritable> arg1,Context arg2)throws IOException, InterruptedException { int i=0; for(DoubleWritable v :arg1){ i++; String msg =arg0.getYear()+"\t"+arg0.getMonth()+"\t"+v.get();//"\t"是制表符 arg2.write(new Text(msg), NullWritable.get()); if(i==3){ break; } } } } public static void main(String[] args) { Configuration config =new Configuration(); // config.set("fs.defaultFS", "hdfs://HadoopMaster:9000"); // config.set("yarn.resourcemanager.hostname", "HadoopMaster"); // config.set("mapred.jar", "C:\\Users\\Administrator\\Desktop\\wc.jar"); // config.set("mapreduce.input.keyvaluelinerecordreader.key.value.separator", ",");//默认分隔符是制表符"\t",这里自定义,如"," try { FileSystem fs =FileSystem.get(config); Job job =Job.getInstance(config); job.setJarByClass(RunJob.class); job.setJobName("weather"); job.setMapperClass(WeatherMapper.class); job.setReducerClass(WeatherReducer.class); job.setMapOutputKeyClass(MyKey.class); job.setMapOutputValueClass(DoubleWritable.class); job.setPartitionerClass(MyPartitioner.class); job.setSortComparatorClass(MySort.class); job.setGroupingComparatorClass(MyGroup.class); job.setNumReduceTasks(3); job.setInputFormatClass(KeyValueTextInputFormat.class); // FileInputFormat.addInputPath(job, new Path("hdfs://HadoopMaster:9000/weather.txt"));//输入路径,下有weather.txt // // Path outpath =new Path("hdfs://HadoopMaster:9000/out/weather"); FileInputFormat.addInputPath(job, new Path("./data/weather.txt"));//输入路径,下有weather.txt Path outpath =new Path("./out/weather"); if(fs.exists(outpath)){ fs.delete(outpath, true); } FileOutputFormat.setOutputPath(job, outpath); boolean f= job.waitForCompletion(true); if(f){ } } catch (Exception e) { e.printStackTrace(); } } } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6164729.html,如需转载请自行联系原作者

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

Hadoop HDFS编程 API入门系列之合并小文件到HDFS(三)

代码版本1 1 package zhouls.bigdata.myWholeHadoop.HDFS.hdfs7; 2 3 import java.io.IOException; 4 import java.net.URI; 5 import java.net.URISyntaxException; 6 import org.apache.hadoop.conf.Configuration; 7 import org.apache.hadoop.fs.FSDataInputStream; 8 import org.apache.hadoop.fs.FSDataOutputStream; 9 import org.apache.hadoop.fs.FileStatus; 10 import org.apache.hadoop.fs.FileSystem; 11 import org.apache.hadoop.fs.FileUtil; 12 import org.apache.hadoop.fs.Path; 13 import org.apache.hadoop.fs.PathFilter; 14 import org.apache.hadoop.io.IOUtils; 15 /** 16 * function 合并小文件至 HDFS 17 * 18 * 19 */ 20 public class MergeSmallFilesToHDFS 21 { 22 private static FileSystem fs = null; //定义文件系统对象,是HDFS上的 23 private static FileSystem local = null; //定义文件系统对象,是本地上的 24 25 /** 26 * @function main 27 * @param args 28 * @throws IOException 29 * @throws URISyntaxException 30 */ 31 32 public static void main(String[] args) throws IOException,URISyntaxException{ 33 34 list(); 35 } 36 37 /** 38 * 39 * @throws IOException 40 * @throws URISyntaxException 41 */ 42 public static void list() throws IOException, URISyntaxException{ 43 // 读取hadoop配置文件 44 Configuration conf = new Configuration(); 45 // 文件系统访问接口和创建FileSystem对象,在本地上运行模式 46 URI uri = new URI("hdfs://HadoopMaster:9000"); 47 fs = FileSystem.get(uri, conf); 48 // 获得本地文件系统 49 local = FileSystem.getLocal(conf); 50 // 过滤目录下的 svn 文件 51 FileStatus[] dirstatus = local.globStatus(new Path("./data/mergeSmallFilesToHDFS/73/*"),new RegexExcludePathFilter("^.*svn$")); 52 // FileStatus[] dirstatus = local.globStatus(new Path("D://data/73/*"),new RegexExcludePathFilter("^.*svn$")); 53 //获取D:\Data\tvdata目录下的所有文件路径 54 Path[] dirs = FileUtil.stat2Paths(dirstatus); 55 FSDataOutputStream out = null; 56 FSDataInputStream in = null; 57 for (Path dir : dirs) 58 {//比如拿2012-09-17为例 59 //将文件夹名称2012-09-17的-去掉,直接,得到20120901文件夹名称 60 String fileName = dir.getName().replace("-", "");//文件名称 61 //只接受20120917日期目录下的.txt文件 62 FileStatus[] localStatus = local.globStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$")); 63 // 获得20120917日期目录下的所有文件 64 Path[] listedPaths = FileUtil.stat2Paths(localStatus); 65 // 输出路径 66 Path block = new Path("hdfs://HadoopMaster:9000/middle/tv/"+ fileName + ".txt"); 67 System.out.println("合并后的文件名称:"+fileName+".txt"); 68 // 打开输出流 69 out = fs.create(block); 70 //循环20120917日期目录下的所有文件 71 for (Path p : listedPaths){//这是星型for循环,即listedPaths的值传给Path p 72 in = local.open(p);// 打开输入流 73 IOUtils.copyBytes(in, out, 4096, false); // 复制数据 74 // 关闭输入流 75 in.close(); 76 } 77 if (out != null){ 78 // 关闭输出流 79 out.close(); 80 } 81 //当循环完20120917日期目录下的所有文件之后,接着依次20120918,20120919,,, 82 } 83 } 84 85 /** 86 * 87 * @function 过滤 regex 格式的文件 88 * 89 */ 90 public static class RegexExcludePathFilter implements PathFilter{ 91 private final String regex; 92 93 public RegexExcludePathFilter(String regex){ 94 this.regex = regex; 95 } 96 97 98 public boolean accept(Path path){ 99 // TODO Auto-generated method stub 100 boolean flag = path.toString().matches(regex); 101 return !flag; 102 } 103 104 } 105 106 /** 107 * 108 * @function 接受 regex 格式的文件 109 * 110 */ 111 public static class RegexAcceptPathFilter implements PathFilter{ 112 private final String regex; 113 114 public RegexAcceptPathFilter(String regex){ 115 this.regex = regex; 116 } 117 118 119 public boolean accept(Path path){ 120 // TODO Auto-generated method stub 121 boolean flag = path.toString().matches(regex); 122 return flag; 123 } 124 125 } 126 } 代码版本2 1 package com.dajiangtai.Hadoop.HDFS; 2 3 import java.io.IOException; 4 import java.net.URI; 5 import java.net.URISyntaxException; 6 import org.apache.hadoop.conf.Configuration; 7 import org.apache.hadoop.fs.FSDataInputStream; 8 import org.apache.hadoop.fs.FSDataOutputStream; 9 import org.apache.hadoop.fs.FileStatus; 10 import org.apache.hadoop.fs.FileSystem; 11 import org.apache.hadoop.fs.FileUtil; 12 import org.apache.hadoop.fs.Path; 13 import org.apache.hadoop.fs.PathFilter; 14 import org.apache.hadoop.hdfs.DistributedFileSystem; 15 import org.apache.hadoop.io.IOUtils; 16 /** 17 * function 合并小文件至 HDFS , 文件与块大小(比如128M)来比,小的话,称为小文件。是一个相对概念!相对于数据块而言的! 18 * @author 小讲 19 * 我们利用通配符和PathFilter 对象,将本地多种格式的文件上传至 HDFS文件系统,并过滤掉 txt文本格式以外的文件。 20 */ 21 public class MergeSmallFilesToHDFS { 22 private static FileSystem fs = null; 23 private static FileSystem local = null; 24 /** 25 * @function main 26 * @param args 27 * @throws IOException 28 * @throws URISyntaxException 29 */ 30 public static void main(String[] args) throws IOException, 31 URISyntaxException { 32 list(); 33 } 34 35 /** 36 * 37 * @throws IOException 38 * @throws URISyntaxException 39 */ 40 public static void list() throws IOException, URISyntaxException { 41 // 读取hadoop文件系统的配置 42 Configuration conf = new Configuration(); 43 // conf=Configuration 44 // conf是Configuration: core-default.xml, core-site.xml, mapred-default.xml, mapred-site.xml, yarn-default.xml, yarn-site.xml, hdfs-default.xml, hdfs-site.xml 45 46 //文件系统访问接口 47 URI uri = new URI("hdfs://djt002:9000"); 48 // uri=URI 49 // uri是hdfs://djt002:9000 50 51 // URL、URI与Path三者的区别 52 // Hadoop文件系统中通过Hadoop Path对象来代表一个文件 53 // URL(相当于绝对路径) -> (文件) -> URI(相当于相对路径,即代表URL前面的那一部分) 54 // URI:如hdfs://dajiangtai:9000 55 // 如,URL.openStream 56 57 58 59 //获得FileSystem实例,即HDFS 60 fs = FileSystem.get(uri, conf); 61 // fs=DistributedFileSystem 62 // fs是DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1814566850_1, ugi=Administrator (auth:SIMPLE)]] 63 64 //获得FileSystem实例,即Local 65 local = FileSystem.getLocal(conf); 66 // local=LocalFileSystem 67 // local是org.apache.hadoop.fs.LocalFileSystem@3ce1b8c5 68 // 为什么要获取到Local呢,因为,我们要把本地D盘下data/73目录下的文件要合并后,上传到HDFS里,所以,我们需先获取到Local,再来做合并工作啦! 69 70 71 // 18、列出文件或目录内容(主要是存放文件或目录的元数据,即大小,权限,副本,,,) 72 // public FileStatus[] listStatus(Path f) throws IOException 73 // public FileStatus[] listStatus(Path f,PathFilter filter) throws IOException 74 // PathFilter是路径过滤器 75 // public FileStatus[] listStatus(Path[] files) throws IOException 76 // public FileStatus[] listStatus(Path[] files,PathFilter filter) 77 // 传送Path数组和路径过滤器 78 // 79 // 80 // 19、FileUtil中的stat2Paths(),将一个FileStatus元数据对象数组转换为一个Path对象数组 81 // 82 // 20、(1)使用通配符来匹配多个目录下的多个文件,也是列出文件或目录内容(主要是存放文件或目录的元数据,即大小,权限,副本,,,) 83 // public FileStatus[] globStatus(Path pathPattern) throws IOException 84 // public FileStatus[] globStatus(Path pathPattern,PathFilter filter) throws IOException 85 // 86 // (2)PathFilter对象 87 // public interface PathFilter{ 88 // boolean accpet(Path path); 89 // } 90 91 92 93 //过滤目录下的 svn 文件,globStatus从第一个参数通配符合到文件,剔除满足第二个参数到结果,因为PathFilter中accept是return! 94 FileStatus[] dirstatus = local.globStatus(new Path("D://data/73/*"),new RegexExcludePathFilter("^.*svn$"));//一般这是隐藏文件,所以得排除 95 //dirstatus=FileStatus[7] 96 // dirstatus是[DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17; isDirectory=true; modification_time=1427791478002; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 97 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18; isDirectory=true; modification_time=1427791505373; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 98 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-19; isDirectory=true; modification_time=1427791532277; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 99 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-20; isDirectory=true; modification_time=1427791553035; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 100 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-21; isDirectory=true; modification_time=1427791577709; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 101 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-22; isDirectory=true; modification_time=1427791602770; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false} 102 // , DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-23; isDirectory=true; modification_time=1427791647177; access_time=0; owner=; group=; permission=rwxrwxrwx; isSymlink=false}] 103 104 105 // ^表示匹配我们字符串开始的位置 *代表0到多个字符 $代表字符串结束的位置 106 // RegexExcludePathFilter来只排除我们不需要的,即svn格式 107 // RegexExcludePathFilter这个方法我们自己写 108 109 // 但是我们,最终是要处理文件里的东西,最终是要转成Path类型,因为Path对象f,它对应着一个文件。 110 111 //获取73目录下的所有文件路径,注意FIleUtil中stat2Paths()的使用,它将一个FileStatus对象数组转换为Path对象数组。 112 Path[] dirs = FileUtil.stat2Paths(dirstatus);//dirstatus是FileStatus数组类型 113 // dirs=Path[7] 114 // dirs是 [file:/D:/data/73/2012-09-17 115 // , file:/D:/data/73/2012-09-18 116 // , file:/D:/data/73/2012-09-19 117 // , file:/D:/data/73/2012-09-20 118 // , file:/D:/data/73/2012-09-21 119 // , file:/D:/data/73/2012-09-22 120 // , file:/D:/data/73/2012-09-23] 121 122 123 FSDataOutputStream out = null;//输出流 124 // out=HdfsDaDataOutputStream 125 // out是org.apache.hadoop.hdfs.client.HdfsDataOutputStream@2b11624e 126 127 FSDataInputStream in = null;//输入流 128 // in=ChecksumFileSystem&FSDataBoundedInputStream 129 // in是org.apache.hadoop.fs.ChecksumFileSystem$FSDataBoundedInputStream@526d542f 130 131 // 很多人搞不清输入流和输出流,!!!! 132 // 其实啊,输入流、输出流都是针对内存的 133 // 往内存里写,是输入流。 134 // 内存往文件里写,是输出Luis。 135 // 136 // 比如一个文件A复制到另一文件B,那么,先写到内存里,再写到文件B。 137 // => 则文件A写到内存里,叫输入流。 138 // => 则内存里写到文件B,叫输出流 139 140 141 for (Path dir : dirs) {//for星型循环,即将dirs是Path对象数组,一一传给Path dir 142 // dirs=Path[7] 143 // dirs是[file:/D:/data/73/2012-09-17 144 // , file:/D:/data/73/2012-09-18 145 // , file:/D:/data/73/2012-09-19 146 // , file:/D:/data/73/2012-09-20 147 // , file:/D:/data/73/2012-09-21 148 // , file:/D:/data/73/2012-09-22 149 // , file:/D:/data/73/2012-09-23] 150 151 // dir= Path 152 // 先传,dir是file:/D:/data/73/2012-09-17 153 // 再传,file:/D:/data/73/2012-09-18 154 // 再传,file:/D:/data/73/2012-09-19 155 // 再传,file:/D:/data/73/2012-09-20 156 // 再传,file:/D:/data/73/2012-09-21 157 // 再传,file:/D:/data/73/2012-09-22 158 // 再传,file:/D:/data/73/2012-09-23 159 160 String fileName = dir.getName().replace("-", "");//文件名称 161 // 先获取到如2012-09-17,然后经过replace("-", ""),得到20120917 162 // 再获取,20120918 163 // 再获取,20120919 164 // 再获取,20120920 165 // 再获取,20120921 166 // 再获取,20120922 167 // 再获取,20120923 168 169 //只接受日期目录下的.txt文件,^匹配输入字符串的开始位置,$匹配输入字符串的结束位置,*匹配0个或多个字符。 170 FileStatus[] localStatus = local.globStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$")); 171 // 先获取到,localStatus=FileStatus[23] 172 // localStatus是[DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917000000.txt; isDirectory=false; length=1111961; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917001500.txt; isDirectory=false; length=782533; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917003000.txt; isDirectory=false; length=593507; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917004500.txt; isDirectory=false; length=839019; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917010000.txt; isDirectory=false; length=866393; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917011500.txt; isDirectory=false; length=678491; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917013000.txt; isDirectory=false; length=593292; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917014500.txt; isDirectory=false; length=688620; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917020000.txt; isDirectory=false; length=674864; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917021500.txt; isDirectory=false; length=635052; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917023000.txt; isDirectory=false; length=547324; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917024500.txt; isDirectory=false; length=598814; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917030000.txt; isDirectory=false; length=542600; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917031500.txt; isDirectory=false; length=535446; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917033000.txt; isDirectory=false; length=592780; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917034500.txt; isDirectory=false; length=619410; replication=1; blocksize=33554432; modification_time=1398669216000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917040000.txt; isDirectory=false; length=590326; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917041500.txt; isDirectory=false; length=428487; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917043000.txt; isDirectory=false; length=598048; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917044500.txt; isDirectory=false; length=598792; replication=1; blocksize=33554432; modification_time=1398669216000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917050000.txt; isDirectory=false; length=575613; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917051500.txt; isDirectory=false; length=619080; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-17/ars10767@20120917053000.txt; isDirectory=false; length=587763; replication=1; blocksize=33554432; modification_time=1398669214000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}] 173 // 再获取到,localStatus=FileStatus[23] 174 // localStatus是[DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918131500.txt; isDirectory=false; length=1722797; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918133000.txt; isDirectory=false; length=1922955; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918134500.txt; isDirectory=false; length=1388036; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918140000.txt; isDirectory=false; length=1888871; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918141500.txt; isDirectory=false; length=1685719; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918143000.txt; isDirectory=false; length=1541381; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918144500.txt; isDirectory=false; length=1723638; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918150000.txt; isDirectory=false; length=1629322; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918151500.txt; isDirectory=false; length=1658684; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918153000.txt; isDirectory=false; length=1548216; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918154500.txt; isDirectory=false; length=1510965; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918160000.txt; isDirectory=false; length=1559078; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918161500.txt; isDirectory=false; length=1752005; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918163000.txt; isDirectory=false; length=1901994; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918164500.txt; isDirectory=false; length=2234304; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918170000.txt; isDirectory=false; length=1912051; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918171500.txt; isDirectory=false; length=1711317; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918173000.txt; isDirectory=false; length=1799747; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918174500.txt; isDirectory=false; length=2038653; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918180000.txt; isDirectory=false; length=2341515; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918181500.txt; isDirectory=false; length=2396977; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918183000.txt; isDirectory=false; length=2382769; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}, DeprecatedRawLocalFileStatus{path=file:/D:/data/73/2012-09-18/ars10767@20120918184500.txt; isDirectory=false; length=2709048; replication=1; blocksize=33554432; modification_time=1398669244000; access_time=0; owner=; group=; permission=rw-rw-rw-; isSymlink=false}] 175 // 再获取到,,,,不多赘述。 176 177 178 // FileStatus[] localStatus = local.listStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$"));//试试,看有什么区别? 179 180 // 如果不设置过滤器,FileInputFormat 会使用一个默认的过滤器来排除隐藏文件。 181 // 如果通过调用 setInputPathFilter()设置了过滤器,它会在默认过滤器的基础上进行过滤。换句话说,自定义的过滤器只能看到非隐藏文件。 182 183 184 //RegexAcceptPathFilter这个方法,我们自己写 185 // RegexAcceptPathFilter来只接收我们需要,即txt格式 186 // 这里,我们还可以只接收别的格式,自己去改,一定要锻炼学会改别人的代码 187 188 189 // 获得如2012-09-17日期目录下的所有文件 190 Path[] listedPaths = FileUtil.stat2Paths(localStatus); 191 // 同样,但是我们,最终是要处理文件里的东西,最终是要转成Path类型,因为Path对象f,它对应着一个文件。 192 193 // 先获取,listedPaths=Path[23] 194 // 先获取2012-09-17下的所有,这个不多赘述啦! 195 196 // 再获取,listedPaths=Path[23] 197 // listedPaths是[file:/D:/data/73/2012-09-18/ars10767@20120918131500.txt 198 // , file:/D:/data/73/2012-09-18/ars10767@20120918133000.txt 199 // , file:/D:/data/73/2012-09-18/ars10767@20120918134500.txt 200 // , file:/D:/data/73/2012-09-18/ars10767@20120918140000.txt 201 // , file:/D:/data/73/2012-09-18/ars10767@20120918141500.txt 202 // , file:/D:/data/73/2012-09-18/ars10767@20120918143000.txt 203 // , file:/D:/data/73/2012-09-18/ars10767@20120918144500.txt 204 // , file:/D:/data/73/2012-09-18/ars10767@20120918150000.txt 205 // , file:/D:/data/73/2012-09-18/ars10767@20120918151500.txt 206 // , file:/D:/data/73/2012-09-18/ars10767@20120918153000.txt 207 // , file:/D:/data/73/2012-09-18/ars10767@20120918154500.txt 208 // , file:/D:/data/73/2012-09-18/ars10767@20120918160000.txt 209 // , file:/D:/data/73/2012-09-18/ars10767@20120918161500.txt 210 // , file:/D:/data/73/2012-09-18/ars10767@20120918163000.txt 211 // , file:/D:/data/73/2012-09-18/ars10767@20120918164500.txt 212 // , file:/D:/data/73/2012-09-18/ars10767@20120918170000.txt 213 // , file:/D:/data/73/2012-09-18/ars10767@20120918171500.txt 214 // , file:/D:/data/73/2012-09-18/ars10767@20120918173000.txt 215 // , file:/D:/data/73/2012-09-18/ars10767@20120918174500.txt 216 // , file:/D:/data/73/2012-09-18/ars10767@20120918180000.txt 217 // , file:/D:/data/73/2012-09-18/ars10767@20120918181500.txt 218 // , file:/D:/data/73/2012-09-18/ars10767@20120918183000.txt 219 // , file:/D:/data/73/2012-09-18/ars10767@20120918184500.txt] 220 221 //输出路径 222 Path block = new Path("hdfs://djt002:9000/outData/MergeSmallFilesToHDFS/"+ fileName + ".txt"); 223 //fileName是"fileName" 224 // block=Path 225 // block是hdfs://djt002:9000/outData/MergeSmallFilesToHDFS/20120918.txt 226 227 // 打开输出流 228 out = fs.create(block);//因为,合并小文件之后,比如这是,合并2012-09-17日期目录下的所有小文件,之后,要上传到HDFS里。 229 // 类似于,文件A写到内存里,再内存里写到文件B。而这行代码out = fs.create(block);是相当于是,内存里写到文件B。所以是输出流,即是从内存里输出的,所以叫输出流。 230 // 这里,文件A是Local 文件B是HDFS 231 232 // 文件与块大小(比如128M)来比,小的话,称为小文件。是一个相对概念!相对于数据块而言的! 233 234 // 很多人搞不清输入流和输出流,!!!! 235 // 其实啊,输入流、输出流都是针对内存的 236 // 往内存里写,是输入流。 237 // 内存往文件里写,是输出Luis。 238 // 239 // 比如一个文件A复制到另一文件B,那么,先写到内存里,再写到文件B。 240 // => 则文件A写到内存里,叫输入流。 241 // => 则内存里写到文件B,叫输出流 242 243 244 for (Path p : listedPaths) {//for星型循环,即将listedPaths的值一一传给Path p 245 //先获取2012-09-17下的所有,这个不多赘述啦! 246 //现在,获取到2012-09-18下了 247 // p=Path 248 // p是file:/D:/data/73/2012-09-18/ars10767@20120918134500.txt 249 // 得一个一个来,这才叫做一一传给Path p 250 251 in = local.open(p);// 打开输入流in 252 // 类似于,文件A写到内存里,再内存里写到文件B。而这行代码in = local.open(p);是相当于是,文件A写到内存里。所以是输如流,即是写到内存里的,所以叫输入流。 253 // 这里,文件A是Local 文件B是HDFS 254 255 IOUtils.copyBytes(in, out, 4096, false); // 复制数据,IOUtils.copyBytes可以方便地将数据写入到文件,不需要自己去控制缓冲区,也不用自己去循环读取输入源。false表示不自动关闭数据流,那么就手动关闭。 256 // IOUtils.copyBytes这个方法很重要 257 //是否自动关闭输入流和输出流,若是false,就要单独去关闭。则不在这个方法体里关闭输入和输出流了。 258 // 若是true,则在这个方法里关闭输入和输出流。不需单独去关闭了 259 260 261 // 明白,IOUtils类的copyBytes将hdfs数据流拷贝到标准输出流System.out中, 262 // copyBytes前两个参数好理解,一个输入,一个输出,第三个是缓存大小,第四个指定拷贝完毕后是否关闭流。 263 // 要设置为false,标准输出流不关闭,我们要手动关闭输入流。即,设置为false表示关闭输入流 264 265 // 主要是把最后的这个参数定义好, 就可以了。 定义为true还是false,则决定着是否在这个方法体里关闭 266 // 若定义为true,则在这个方法体里直接关闭输入流、输出流。不需单独去关闭了 267 // 若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了 268 269 270 // 关闭输入流 271 in.close();//若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了。这就是单独在关闭输入流!!!懂了吗 272 } 273 if (out != null) {//这里为什么不为空,空指针,则说明里面还有资源。 274 // 关闭输出流 275 out.close();//若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了。这就是单独在关闭输出流!!!懂了吗 276 } 277 } 278 279 } 280 281 /** 282 * 283 * @function 过滤 regex 格式的文件 284 * 285 */ 286 public static class RegexExcludePathFilter implements PathFilter { 287 private final String regex;//变量 288 289 public RegexExcludePathFilter(String regex) {//这个是上面的那个,正在表达式 290 this.regex = regex;//将String regex的值,赋给RegexExcludePathFilter类里的private final String regex的值 291 } 292 293 public boolean accept(Path path) {//主要是实现accept方法 294 // TODO Auto-generated method stub 295 boolean flag = path.toString().matches(regex);//匹配正则表达式,这里是^.*svn$ 296 return !flag; 297 } 298 299 } 300 301 /** 302 * 303 * @function 接受 regex 格式的文件 304 * 305 */ 306 public static class RegexAcceptPathFilter implements PathFilter { 307 private final String regex;//变量 308 309 public RegexAcceptPathFilter(String regex) {//这个是上面的那个,正在表达式 310 this.regex = regex;//将String regex的值,赋给RegexAcceptPathFilter类里的private final String regex的值 311 } 312 313 public boolean accept(Path path) {//主要是实现accept方法 314 // TODO Auto-generated method stub 315 boolean flag = path.toString().matches(regex);//匹配正则表达式,这里是^.*txt$ 316 return flag; 317 } 318 319 } 320 } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6174553.html,如需转载请自行联系原作者

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

Hadoop MapReduce编程 API入门系列之小文件合并(二十九)

Hadoop 自身提供了几种机制来解决相关的问题,包括HAR,SequeueFile和CombineFileInputFormat。 Hadoop 自身提供的几种小文件合并机制 Hadoop HAR 将众多小文件打包成一个大文件进行存储,并且打包后原来的文件仍然可以通过Map-reduce进行操作,打包后的文件由索引和存储两大部分组成 缺点:一旦创建就不能修改,也不支持追加操作,还不支持文档压缩,当有新文件进来以后,需要重新打包。 SequeuesFile Sequence file由一系列的二进制key/value组成,如果key为小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。 优缺点:对小文件的存取都比较自由,也不限制用户和文件的多少,但是该方法不能使用append方法,所以适合一次性写入大量小文件的场景。 CombineFileInputFormat CombineFileInputFormat是一种新的inputformat,用于将多个文件合并成一个单独的split作为输入,而不是通常使用一个文件作为输入。另外,它会考虑数据的存储位置。 目前很多公司采用的方法就是在数据进入 Hadoop 的 HDFS 系统之前进行合并(也是本博文这方法),一般效果较上述三种方法明显。 代码版本1 MergeSmallFilesToHDFS .java package zhouls.bigdata.myMapReduce.MergeSmallFiles; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.PathFilter; import org.apache.hadoop.io.IOUtils; /** * function 合并小文件至 HDFS * * */ public class MergeSmallFilesToHDFS { private static FileSystem fs = null; private static FileSystem local = null; /** * @function main * @param args * @throws IOException * @throws URISyntaxException */ public static void main(String[] args) throws IOException, URISyntaxException { list(); } /** * * @throws IOException * @throws URISyntaxException */ public static void list() throws IOException, URISyntaxException { // 读取hadoop文件系统的配置 Configuration conf = new Configuration(); //文件系统访问接口 URI uri = new URI("hdfs://HadoopMaster:9000"); //创建FileSystem对象aa fs = FileSystem.get(uri, conf); // 获得本地文件系统 local = FileSystem.getLocal(conf); //过滤目录下的 svn 文件 FileStatus[] dirstatus = local.globStatus(new Path("./data/mergeSmallFiles/*"),new RegexExcludePathFilter("^.*svn$")); //获取73目录下的所有文件路径 Path[] dirs = FileUtil.stat2Paths(dirstatus); FSDataOutputStream out = null; FSDataInputStream in = null; for (Path dir : dirs) { String fileName = dir.getName().replace("-", "");//文件名称 //只接受日期目录下的.txt文件a FileStatus[] localStatus = local.globStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$")); // 获得日期目录下的所有文件 Path[] listedPaths = FileUtil.stat2Paths(localStatus); //输出路径 Path block = new Path("hdfs://HadoopMaster:9000/tv/"+ fileName + ".txt"); // 打开输出流 out = fs.create(block); for (Path p : listedPaths) { in = local.open(p);// 打开输入流 IOUtils.copyBytes(in, out, 4096, false); // 复制数据 // 关闭输入流 in.close(); } if (out != null) { // 关闭输出流a out.close(); } } } /** * * @function 过滤 regex 格式的文件 * */ public static class RegexExcludePathFilter implements PathFilter { private final String regex; public RegexExcludePathFilter(String regex) { this.regex = regex; } @Override public boolean accept(Path path) { // TODO Auto-generated method stub boolean flag = path.toString().matches(regex); return !flag; } } /** * * @function 接受 regex 格式的文件 * */ public static class RegexAcceptPathFilter implements PathFilter { private final String regex; public RegexAcceptPathFilter(String regex) { this.regex = regex; } @Override public boolean accept(Path path) { // TODO Auto-generated method stub boolean flag = path.toString().matches(regex); return flag; } } } 代码版本2 MergeSmallFilesToHDFS .java package zhouls.bigdata.myMapReduce.MergeSmallFiles; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.PathFilter; import org.apache.hadoop.io.IOUtils; /** * function 合并小文件至 HDFS , 文件与块大小(比如128M)来比,小的话,称为小文件。是一个相对概念!相对于数据块而言的! * @author 小讲 * */ public class MergeSmallFilesToHDFS { private static FileSystem fs = null; private static FileSystem local = null; /** * @function main * @param args * @throws IOException * @throws URISyntaxException */ public static void main(String[] args) throws IOException, URISyntaxException { list(); } /** * * @throws IOException * @throws URISyntaxException */ public static void list() throws IOException, URISyntaxException { // 读取hadoop文件系统的配置 Configuration conf = new Configuration(); //文件系统访问接口 URI uri = new URI("hdfs://master:9000"); // URL、URI与Path三者的区别 // Hadoop文件系统中通过Hadoop Path对象来代表一个文件 // URL(相当于绝对路径) -> (文件) -> URI(相当于相对路径,即代表URL前面的那一部分) // URI:如hdfs://master:9000 // 如,URL.openStream //获得FileSystem实例,即HDFS fs = FileSystem.get(uri, conf); //获得FileSystem实例,即Local local = FileSystem.getLocal(conf); // 为什么要获取到Local呢,因为,我们要把本地D盘下data/73目录下的文件要合并后,上传到HDFS里,所以,我们需先获取到Local,再来做合并工作啦! //过滤目录下的 svn 文件,globStatus从第一个参数通配符合到文件,剔除满足第二个参数到结果,因为PathFilter中accept是return! FileStatus[] dirstatus = local.globStatus(new Path("D://data/73/*"),new RegexExcludePathFilter("^.*svn$"));//一般这是隐藏文件,所以得排除 // ^表示匹配我们字符串开始的位置 *代表0到多个字符 $代表字符串结束的位置 // RegexExcludePathFilter来只排除我们不需要的,即svn格式 // RegexExcludePathFilter这个方法我们自己写 // 但是我们,最终是要处理文件里的东西,最终是要转成Path类型,因为Path对象f,它对应着一个文件。 //获取73目录下的所有文件路径,注意FIleUtil中stat2Paths()的使用,它将一个FileStatus对象数组转换为Path对象数组。 Path[] dirs = FileUtil.stat2Paths(dirstatus);//dirstatus是FileStatus数组类型 FSDataOutputStream out = null;//输出流 FSDataInputStream in = null;//输入流 // 很多人搞不清输入流和输出流,!!!! // 其实啊,输入流、输出流都是针对内存的 // 往内存里写,是输入流。 // 内存往文件里写,是输出Luis。 // // 比如一个文件A复制到另一文件B,那么,先写到内存里,再写到文件B。 // => 则文件A写到内存里,叫输入流。 // => 则内存里写到文件B,叫输出流 for (Path dir : dirs) {//for星型循环,即将dirs是Path对象数组,一一传给Path dir String fileName = dir.getName().replace("-", "");//文件名称 // 即获取到如2012-09-17,然后经过replace("-", ""),得到20120917 //只接受日期目录下的.txt文件,^匹配输入字符串的开始位置,$匹配输入字符串的结束位置,*匹配0个或多个字符。 FileStatus[] localStatus = local.globStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$")); // FileStatus[] localStatus = local.listStatus(new Path(dir+"/*"),new RegexAcceptPathFilter("^.*txt$"));//试试,看有什么区别?出现错误的!为什么? //RegexAcceptPathFilter这个方法,我们自己写 // RegexAcceptPathFilter来只接收我们需要,即txt格式 // 这里,我们还可以只接收别的格式,自己去改,一定要锻炼学会改别人的代码 // 获得如2012-09-17日期目录下的所有文件 Path[] listedPaths = FileUtil.stat2Paths(localStatus); // 同样,但是我们,最终是要处理文件里的东西,最终是要转成Path类型,因为Path对象f,它对应着一个文件。 //输出路径 Path block = new Path("hdfs://master:9000/outData/MergeSmallFilesToHDFS/"+ fileName + ".txt"); // 打开输出流 out = fs.create(block);//因为,合并小文件之后,比如这是,合并2012-09-17日期目录下的所有小文件,之后,要上传到HDFS里。 // 类似于,文件A写到内存里,再内存里写到文件B。而这行代码out = fs.create(block);是相当于是,内存里写到文件B。所以是输出流,即是从内存里输出的,所以叫输出流。 // 这里,文件A是Local 文件B是HDFS // 文件与块大小(比如128M)来比,小的话,称为小文件。是一个相对概念!相对于数据块而言的! // 很多人搞不清输入流和输出流,!!!! // 其实啊,输入流、输出流都是针对内存的 // 往内存里写,是输入流。 // 内存往文件里写,是输出Luis。 // // 比如一个文件A复制到另一文件B,那么,先写到内存里,再写到文件B。 // => 则文件A写到内存里,叫输入流。 // => 则内存里写到文件B,叫输出流 for (Path p : listedPaths) {//for星型循环,即将listedPaths的值一一传给Path p in = local.open(p);// 打开输入流in // 类似于,文件A写到内存里,再内存里写到文件B。而这行代码in = local.open(p);是相当于是,文件A写到内存里。所以是输如流,即是写到内存里的,所以叫输入流。 // 这里,文件A是Local 文件B是HDFS IOUtils.copyBytes(in, out, 4096, false); // 复制数据,IOUtils.copyBytes可以方便地将数据写入到文件,不需要自己去控制缓冲区,也不用自己去循环读取输入源。false表示不自动关闭数据流,那么就手动关闭。 // IOUtils.copyBytes这个方法很重要 //是否自动关闭输入流和输出流,若是false,就要单独去关闭。则不在这个方法体里关闭输入和输出流了。 // 若是true,则在这个方法里关闭输入和输出流。不需单独去关闭了 // 明白,IOUtils类的copyBytes将hdfs数据流拷贝到标准输出流System.out中, // copyBytes前两个参数好理解,一个输入,一个输出,第三个是缓存大小,第四个指定拷贝完毕后是否关闭流。 // 要设置为false,标准输出流不关闭,我们要手动关闭输入流。即,设置为false表示关闭输入流 // 主要是把最后的这个参数定义好, 就可以了。 定义为true还是false,则决定着是否在这个方法体里关闭 // 若定义为true,则在这个方法体里直接关闭输入流、输出流。不需单独去关闭了 // 若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了 // 关闭输入流 in.close();//若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了。这就是单独在关闭输入流!!!懂了吗 } if (out != null) {//这里为什么不为空,空指针,则说明里面还有资源。 // 关闭输出流 out.close();//若定义为false,则不在这个方法体里直接关闭输入流、输出流。需单独去关闭了。这就是单独在关闭输出流!!!懂了吗 } } } /** * * @function 过滤 regex 格式的文件 * */ public static class RegexExcludePathFilter implements PathFilter { private final String regex;//变量 public RegexExcludePathFilter(String regex) {//这个是上面的那个,正在表达式 this.regex = regex;//将String regex的值,赋给RegexExcludePathFilter类里的private final String regex的值 } public boolean accept(Path path) {//主要是实现accept方法 // TODO Auto-generated method stub boolean flag = path.toString().matches(regex);//匹配正则表达式,这里是^.*svn$ return !flag;//如果要接收 regex 格式的文件,则accept()方法就return flag; 如果想要过滤掉regex格式的文件,则accept()方法就return !flag。 } } /** * * @function 接受 regex 格式的文件 * */ public static class RegexAcceptPathFilter implements PathFilter { private final String regex;//变量 public RegexAcceptPathFilter(String regex) {//这个是上面的那个,正在表达式 this.regex = regex;//将String regex的值,赋给RegexAcceptPathFilter类里的private final String regex的值 } public boolean accept(Path path) {//主要是实现accept方法 // TODO Auto-generated method stub boolean flag = path.toString().matches(regex);//匹配正则表达式,这里是^.*txt$ return flag;//如果要接收 regex 格式的文件,则accept()方法就return flag; 如果想要过滤掉regex格式的文件,则accept()方法就return !flag。 } } } 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6171460.html,如需转载请自行联系原作者

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

OpenStack入门修炼之Cinder服务-->使用NFS作为后端存储(19)

1.安装cinder-volume组件以及nfs [root@linux-node2 ~]# yum install -y openstack-cinder python-keystone [root@linux-node2 ~]# yum install -y nfs-utils rpcbind [root@linux-node2 ~]# mkdir -p /data/nfs [root@linux-node2 ~]# vim /etc/exports /data/nfs *(rw,no_root_squash) [root@linux-node2 ~]# systemctl start rpcbind [root@linux-node2 ~]# systemctl start nfs 2.配置cinder使用nfs [root@linux-node1 ~]# scp /etc/cinder/cinder.conf 192.168.56.12:/etc/cinder [root@linux-node2 ~]# vim /etc/cinder/cinder.conf 删除[lvm]的内容 [default] enabled_backends = nfs [nfs] volume_driver = cinder.volume.drivers.nfs.NfsDriver nfs_shares_config=/etc/cinder/nfs_shares nfs_mount_point_base=$state_path/mnt 驱动查找: 查看在此文件:/usr/lib/pythone.27/site-packages/cinder/volume/drivers/nfs.py内是否有这样的类 [root@linux-node2 ~]# vim /etc/cinder/nfs_shares 192.168.56.12:/data/nfs 3.修改配置文件的权限,否则cinder服务无法读取 [root@linux-node2 ~]# chown root.cinder /etc/cinder/nfs_shares [root@linux-node2 ~]# chmod 640 /etc/cinder/nfs_shares 4.启动openstack-cinder-volume服务 [root@linux-node2 ~]# systemctl enable openstack-cinder-volume [root@linux-node2 ~]# systemctl start openstack-cinder-volume 5.查看volume服务 [root@linux-node1 ~]# source admin-openstack [root@linux-node1 ~]# openstack volume service list +------------------+-----------------+------+---------+-------+----------------------------+ | Binary | Host | Zone | Status | State | Updated At | +------------------+-----------------+------+---------+-------+----------------------------+ | cinder-scheduler | linux-node1 | nova | enabled | up | 2017-12-11T06:28:29.000000 | | cinder-volume | linux-node1@lvm | nova | enabled | up | 2017-12-11T06:28:28.000000 | | cinder-volume | linux-node2@nfs | nova | enabled | up | 2017-12-11T06:28:26.000000 | +------------------+-----------------+------+---------+-------+----------------------------+ 6.创建云硬盘类型NFS和ISCSI [root@linux-node1 ~]# cinder type-create NFS [root@linux-node1 ~]# cinder type-create ISCSI 7.将后端存储和云硬盘类型关联 [root@linux-node1 ~]# vim /etc/cinder/cinder.conf 使用lvm本地存储就需要在[lvm]加入 [lvm] volume_backend_name = ISCSI-Storage [root@linux-node1 ~]# systemctl restart openstack-cinder-volume [root@linux-node2 ~]# vim /etc/cinder/cinder.conf 使用NFS网络存储就需要在[nfs]加入 [nfs] volume_backend_name = NFS-Storage [root@linux-node2 ~]# systemctl restart openstack-cinder-volume 在配置文件cinder.conf加入volume_backend_name可以实现多类型的云硬盘挂载,如ISCSI,NFS [root@linux-node1 ~]# cinder type-key NFS set volume_backend_name=NFS-Storage [root@linux-node1 ~]# cinder type-key ISCSI set volume_backend_name=ISCSI-Storage 8.创建卷 使用NFS作为后端存储(19)" style="margin:0px 0px 15px;padding:0px;border:none;" data-original="http://i2.51cto.com/images/blog/201712/12/8756f6e14e37d6d10e494d565ef8abc4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk="> 使用NFS作为后端存储(19)" style="margin:0px 0px 15px;padding:0px;border:none;" data-original="http://i2.51cto.com/images/blog/201712/12/b7732bca3bde8a9bd1cc5154905e711c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk="> "卷"-->"管理连接"-->"连接云主机"-->在云主机内fdisk -l进行查看 小结: cinder后端存储步骤: (1)把存储准备好,如NFS,ISCSI (2)安装cinder-volume (3)vim /etc/cinder/cinder.conf [xxx] volume_driver=xxx ...... volume_backend_name=xxx-Storage (4)创建类型:cinder type-create xxx (5)关联类型:cinder type-key xxx set volume_backend_name=xxx-Storage 本文转自 IT_外卖小哥 51CTO博客,原文链接:http://blog.51cto.com/jinlong/2049805

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

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

Rocky Linux

Rocky Linux

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

Sublime Text

Sublime Text

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

用户登录
用户注册