1

我正在尝试编写接收[String]文件名的函数,String即文件目录的名称和*f. 该函数将在每个文件最后附加一个整数。

这是我到目前为止得到的:

import StdEnv
import StdFile
import FileManipulation

appendNumInEndOfVmFiles :: [String] String *f -> String
appendNumInEndOfVmFiles [] dirname w = "finished"
appendNumInEndOfVmFiles [x:xs] dirname w
# path = dirname +++ "\\\\" +++ x
# (ok,file,files) = fopen path FAppendText w
# file = fwritei 12 file 
# (ok2,_) = fclose file w
= appendNumInEndOfVmFiles xs dirname w


Start w
// 1. Receive name of directory from the user.
# (io,w) = stdio w                                  // open stdio
# io = fwrites "Enter name of directory:\n" io      // ask for name
# (name,io) = freadline io                          // read in name
# name = name % (0, size name - 2)                  // remove \n from name
# (ok,w) = fclose io w                              // close stdio
| not ok = abort "Couldn't close stdio"             // abort in case of         failure

// 2. Get a list of all file names in that directory.
# (dir,w) = getDirectoryContents (RelativePath [PathDown name]) w
# fileList = getNamesOfFilesInDirectory (getEntriesList dir)

= appendNumInEndOfVmFiles (getVmFiles fileList) name w

假设getVmFiles在我的FileManipulation.dcl文件中定义并且在这个问题的上下文中name"myDir"并且文件列表是["hello.vm","Wiki.vm"]

出于某种原因,即使我在屏幕上收到“完成”消息,文件也没有被修改。无论我给什么类型的整数fopen,即使它FWriteTextFWriteData它仍然什么都不做......即使我正在使用fwritecfwrites使用字符也没有发生任何事情。

我在这里缺少什么?非常感谢!

4

1 回答 1

1

出于某种原因,即使我在屏幕上收到“完成”消息,文件也没有被修改。

这是由于懒惰的评估。在appendNumInEndOfVmFiles中,不使用 的结果fclose,因此fclose不求值。因此,fwritei也不需要评估。您可以通过在以下位置添加防护来解决此问题ok2

# (ok2,_) = fclose file w
| not ok2 = abort "fclose failed\n"
= appendNumInEndOfVmFiles xs dirname w

但是,执行此操作的典型方法是重写函数以返回 a*f而不是 a String,这样这个唯一值就不会丢失。只要使用结果,fwritei就会评估 。您可以使*f参数严格(即!在前面添加一个)。这将确保在进入函数之前对其进行评估,以便所有延迟文件关闭都已执行。


您的代码还有一些问题:

  1. 在这里,w使用了两次,这是非法的,因为它是严格类型。您应该使用(ok2,w)in the guard 来继续使用相同的环境。

    # (ok2,_) = fclose file w
    = appendNumInEndOfVmFiles xs dirname w
    
  2. appendNumInEndOfVmFiles需要有一个类型上下文| FileSystem f来解决fopen和的重载fclose


最后:

...即使它FWriteTextFWriteData...

正如你所知:不同之处在于第一个将整数写入 ASCII 表示,而第二个将二进制写入 4 或 8 个字节(取决于系统的位宽)。

于 2019-03-13T09:41:23.597 回答