Nebula3学习笔记(5): IO系统

IO子系统

Nebula3的IO系统相对于Nebula1和2是一个巨大的进步, 新系统的主要设计目标有:

  • 使用更标准的机制, 如用URI来定位资源, 用MIME类型来区分数据格式
  • 一个灵活的流模型, 它不关心数据是来自文件, 内存, HTTP连接还是其它地方
  • 从流读写不数据的数据类型也更方便, 例如要读取的XML格式数据来自文件/内存/网络都没问题
  • 另外, 新的流和读写类可以在运行时注册到IO系统中
  • 相对于系统平台的特定IO函数, 像fopen()这样的C Lib函数会有额外的性能或内存损失. 所以在保证可移植性的前提下不损失性能, 必须使用特定平台的IO函数

IO子系统的一些主要概念:

  • 一个中枢的IO::Console 对象连接控制台处理器(console handler)来进行文本的输入和输出. 这保证了所有的Nebula3的文本输出都通过一个集中的进出通道. 特定的控制台处理器可以用特定的方式处理文本输出(例如输出到stdout, 游戏控制台, 日志文件或网络连接).
  • 重定向符做为路径别名. 大体的功能跟Nebula1和2差不多, 除了从AmigaOS 的重定向符得到的灵感. Nebula3重定向符的一个新特性就是它们可以做为URI的别名. 例如, 重定向符”textures:”可以定义为 "http://www.radonlabs.de/textures", 这样简化的资源路径"textures:mytexture.dds"就会解释成这个绝对路径: "http://www.radonlabs.de/textures/mytexture.dds" (太NB了, 把纹理放到网站上加载? 哈哈, 拿来做内置广告肯定很爽)
  • 流(Stream)做为基本的数据进出通道. 它提供了基本的API函数 Open()/Close()/Read()/Write(), 但是可能完全隐藏了传输和存储通道. 典型的例子有IO::FileStream, IO::MemoryStream, 或 Net::HttpStream
  • Stream reader 和 writer 是连接到流上并且实现了简单易用的接口来读写数据格式. 例如你可以把IO::XmlReader连接到IO::FileStream来从文件系统读取XML格式的数据, 或者连接到IO::HttpStream来从HTTP连接读取XML格式的数据.

这里有个很好的代码例子可以反映出Nebula3输入输出系统的强大:

1: IO::FileServer::Instance()->CopyFile("http://www.radonlabs.de/index.html", "temp:index.html");

这一行代码从HTTP服务器拷贝了一个文件到当用户的临时目录里去. 再多加几行代码, 你可以创建一个流对象指向HTTP服务器上的HTML文件, 连接一个XML reader到这个流上, 然后就可以在不存储中间文件的基础上进行解析HTML了.

标准重定向符

Nebula3初始化了以下几个重定向符:

  • home: 指向应用程序目录, 一般在” C:/Program Files “下. Nebula3把这个目录当成只读的, 为的是不需要管理员权限就能运行.
  • user: 这个指向当前登录的用户目录, 一般是指” C:/Documents and Settings/[username] “. Nebula3会自动创建一个本地目录来避免不同程序覆写掉它们的数据. 所以说一般情况下把数据写入用户目录是安全的. 这个地方可以用于保存游戏数据和配置, 或者程序需要调用的持久性数据.
  • temp: 这个指向当前用户的临时目录, 一般是可写的, 但是不要假设下一次启动程序时数据还存在.
  • bin: 这个指向应用程序可执行文件的目录. 它可以跟home相同, 也可能不同. 这个目录应该也当成是只读的来对待.

其它重定向符可以在程序运行时进行定义. 通常情况下会定义一些抽象资源路径, 如textuers, sound, data等等. 这样的话资源的路径就可以只更改重定向符的定义而是不是去替换所有的路径. 重定向符的另一个好处就是减少了路径字符串的长度, 在一定程序上节省了内存占用.

URI(统一资源定位符)

在Nebula3中的资源位置通常都是用URI定义的. URI一般包括下面这几部, 有一些是可选的:

  • 模式(协议?), 如"http:", "file:", 等... Nebula3 没有硬编码任何模式, 而跟流类绑定在一起注册到IO::StreamServer 单件
  • 一个可选的用户信息字段, 这是一个用户名和密码用于HTTP或FTP主机的身份验证
  • 一个主机名, 如"www.radonlabs.de"
  • 一个在主机名后可选的端口号
  • 一个本地路径, 指向主机上的一个资源
  • 一个可选的片段, 通常指向资源内部的一个位置
  • 一个可选的查询部分, 一般包含一个PHP脚本或其它相似的动态响应机制的参数

IO::URI类用来传递URI并且解析URI字符串到它的各个部分中. 值得注意的是URI对象比字符串占用更多的内存, 所以有时把URI保存在字符串中, 并在需要分割的时候才使用IO::URI类会更好一些.

这里有一些URI的例子:

1: file:///c:/temp/bla.txt
2: file://samba/temp/bla.txt
3: http://www.radonlabs.de/index.html
4: http://user:password@www.myserver.com:8080/index.html#main

通过使用重定位符会大大简化路径名称. 要引用一个程序目录的文件你可以使用”home:bla.txt”, 等价于file:///c:/Program Files/[myapp]/bla.txt.

Stream, Reader 和 Writer

流(Stream)提供了用于储存和传输原始数据的接口. 一个流对象提供了传统的Open()/Close()/Read()/Write()/Seek()接口, 其中有些还提供内存映射, 这样数据的读写可以直接通过内存访问来实现. Stream对象用一个IO::URI对象来定义它们的资源位置. 通常情况下, 一个URI格式映射到一个特定的流对象. 例如”http:”URI格式一般映射到Net::HttpStream类, 而”file:”格式则映射到IO:FileStream类. 这个映射由StreamServer构造一个流对象并匹配一个URI. 一个Nebula3应用程序通过StreamServer::Register()方法来注册这个映射关系, 这也是新的流对象和URI格式的注册方法.

让我们来看看有哪些重要的类:

  • IO::FileStream: 提供了访问主机文件系统的功能
  • IO::MemoryStream: 一个具有流接口的动态内存缓冲
  • IO::HttpStream: 提供了一个流接口来访问HTTP服务器文件

Stream reader和writer类提供了一些舒适的接口专门处理特定的数据格式. 这里有一些stream reader和writer:

  • IO::BinaryReader/IOBinaryWriter: 读写二进制数据
  • IO::TextReader/IOTextWriter: 读写文本数据
  • IO::XmlReader/IOXmlWriter: 读写XML格式的数据
  • Messaging::MessageReader/MessagingMessageWriter: 消息序列化

这里有一个用XmlReader从HTTP服务器访问文件的简单例子

 1:     using namespace IO;
 2:  
 3:     Ptr<Stream> stream = StreamServer::Instance()->CreateStream("http://www.radonlabs.de/index.html");
 4:     Ptr<XmlReader> xmlReader = XmlReader::Create();
 5:     xmlReader->SetStream(stream);
 6:  if (xmlReader->Open())
 7:  {
 8:  // parse content here using the XmlReader interface
 9:  }

File Server(文件服务器)

Nebula3 IO::FileServer类提供了一个单件用于访问主机的文件系统进行一些全局操作, 像定义重定向符, 复制, 删除和检查文件是否存在, 列出目录内容, 等等.

这个代码片断介绍FileServer的一些有用的方法:

using namespace IO;
using namespace Util;
FileServer* fs = FileServer::Instance();
// check if a file or directory exists
bool fileExists = fs->FileExists("home:bla.txt");
bool dirExists = fs->DirectoryExists("temp:bla/blub");
// resolve a path with assigns into an absolute filesystem
// path, this is sometimes necessary to interface with
// 3rd party libraries which don't understand Nebula3 paths directly
String absPath = fs->ResolveAssings("user:myapp/savegames");
// create a directory, note that all missing subdirectories will
// be created as well
fs->CreateDirectory("user:myapp/savegames");
// copy and delete files
fs->CopyFile("home:movie.mpg", "temp:movie.mpg");
fs->DeleteFile("temp:movie.mpg");
// list files in a directory matching a pattern
Array<String> files = fs->ListFiles("temp:", "*.txt");
// list all subdirectories in temp:
Array<String> dirs = fs->ListDirectories("temp:", "*");

控制台

一般不直接调用IO::Console, 直接n_printf(), n_error(), n_dbgout(), n_warning()@_@

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python学习路

二、路由、模板

一、路由系统 在settings.py文件中通过ROOT_URLCONF指定根级url的配置 urlpatterns是一个url()实例的列表 一个url()对...

3388
来自专栏枕边书

PHP模拟发送POST请求之二、用PHP和JS处理URL信息

明白了HTTP请求的头信息后,我们还需要对请求地址有所了解。再者,HTTP GET请求是靠URL实现的,所以了解URL的构造,处理URL的重要性不言而喻。 在P...

2245
来自专栏orientlu

FreeRTOS 消息队列

上面这几中方式中, 除了消息通知, 其他几种实现都是基于消息队列。消息队列作为主要的通信方式, 支持在任务间, 任务和中断间传递消息内容。 这一章介绍 Fre...

4192
来自专栏大内老A

使命必达: 深入剖析WCF的可靠会话[协议篇](下)

在《上篇》中,我们认识了从序列创建到终止过程中消息交换的大致流程。接下来,我们进一步将关注点聚焦到单个小消息上,看看在整个基于序列的上下文中,不同类型的消息具有...

2408
来自专栏Java技术栈

高级 Java 面试通关知识点整理!

2093
来自专栏coder修行路

python中重要的模块--asyncio

一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python也是在python 3.4中引入了协程的概念。也通过这次整理...

4987
来自专栏腾讯IVWEB团队的专栏

nodejs 中错误捕获的一些最佳实践

本文为翻译文章,原文比较长,感觉也有点啰嗦,所以根据个人理解猜测梳理出本文。

6260
来自专栏专注 Java 基础分享

Java并发之线程间的协作

     上篇文章我们介绍了synchronized关键字,使用它可以有效的解决我们多线程所带来的一些常见问题。例如:竞态条件,内存可见性等。并且,我们也说明了...

2269
来自专栏Android 研究

Android系统启动——3init.rc解析

init.rc文件是以“块”(section)为单位服务的,,一个“块”(section)可以包含多行。“块”(section)分成两大类:一类称为"动作(ac...

4012
来自专栏自动化测试实战

RF设置全局变量

4697

扫码关注云+社区

领取腾讯云代金券