Nim 中的 streams 模块


        streams 模块是 Nim\lib\pure\streams.nim 文件,该模块提供了一个流接口和两个实现,一个是字符串流`StringStream`,一个是文件流`FileStream`。很显然字符串流是通过字符串来实现 stream接口的,文件流是通过 Nim中的”File" 对象来实现的。下面先看一个例子:

import streams

var
  ss = newStringStream("""The first line
the second line
the third line""")
  line = ""
while ss.readLine(line):
  echo line
ss.close()

var fs = newFileStream("somefile.txt", fmRead)       ##第二个参数是读文件的模式

if not isNil(fs):
  while fs.readLine(line):
    echo line
fs.close()

         从streams 模块中也可以看出在 Nim 中怎么构造接口,怎么实现接口。如果看 streams 文件感觉乱的话,可以看我之前的一篇博文。里面简单的介绍了 Nim 中“接口” 的实现。 这个模块提供了很多操作流的过程,有读取也有写操作,其中基本上读取操作提供了两个相同功能的过程,这两个过程不同之处是一个读取数据后标记位会有相应的增加,一个不会增加。例如:

import streams
var
  ss = newStringStream("""The first line
the second line
the third line""")
  line = ""

echo ss.getPosition()
echo ss.readLine()
echo ss.getPosition()
echo ss.peekLine()
echo ss.getPosition()

ss.close()

        这样的过程还有readChar、peekChar,readStr、peekStr 等等。


        这里还有一个需要注意的是,过程readInt 系列。这里的readInt8、readInt16、readInt32等,读取的是相应字节数的位数,返回的是整型,读取多字节时,后读取的字节在高位。例如过程 readInt16() 读取字符串流 “10”, 返回的是12337。12337是 16位的二进制数。高8位是字符 ‘0’ 的二进制数,低8位是字符'1' 的二进制数。同样文件流也是这样读取的。

import streams

var 
  ss = newStringStream("0123456789")
  fs = newFileStream(stdin)
  x:int16
  y:int16

x = ss.readInt16()
y = fs.readInt16()

echo "x = ", x
echo "y = ", y

       那有人可能希望得到这样的效果:在终端输入10,得到的就是整型10。那么我想到的有两种方法,一种是读取字符串,再转换为整型。一种是通过C FFI (C 的外部接口函数)来实现,下面来看看怎么实现的。

转换字符串:

import streams,strutils

var 
  ss = newStringStream("0123456789")
  fs = newFileStream(stdin)
  x:int8
  y:int16

x = int8(parseInt(ss.readStr(sizeof(x))))
y = int16(parseInt(fs.readStr(sizeof(int16))))

echo "x = ", x
echo "y = ", y

C FFI

# declare a C procedure..
proc unsafeScanf(f: File, s: cstring)
  {.varargs,
    importc: "fscanf",
    header: "<stdio.h>".}

# ..and use it...
var x: cint
stdin.unsafeScanf("%d", addr x)


      如果我们用过程 readInt 系列读取数据,有读取后的整型数据,想要知道原来的数字字符串怎么办呢。可以通过下面的程序来实现:


#这个程序是把使用标准输入文件流或字符串流读取的整型转换为原来的字符串。注意后读取的字符的二进制在高位。

import streams

proc StreamReadIntToString[T](strInt:T, size:int):string =
  ##strInt是从文件流读取的整型,stdin.readInt16()
  ##size是字节数
  
  var 
    temp = strInt
    judge = size
    singleChar:char
    singleInt:int
    result = ""

  while(judge > 0) :
    judge = judge - 1  
    singleInt = temp shr ((size - 1)*8)       #整型右移 (size-1)*8 位,剩余最高八位。
    singleChar = char(singleInt)              #把最高8位转换为char型
    result = singleChar & result              #小端在前,大端在后

    if judge > 0:
      temp = temp shl (8)                   #左移读取过的高8位
    else:
      return result

var 
  fs = newFileStream(stdin)
  ss = newStringStream("0123456789")
  strInt1:int32
  strInt2:int32

strInt1 = fs.readInt32()
strInt2 = ss.readInt32()

echo "strInt1 =  ",StreamReadIntToString(strInt1,sizeof(type(strInt1))) 
echo "strInt2 =  ",StreamReadIntToString(strInt2,sizeof(type(strInt1)))
     







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值