期货量化交易软件:通过 WINAPI 进行文件操作
简介
赫兹期货量化设计的理念是,即便是编写错误的程序也无法误删硬盘中的数据。用于 文件读取和编写操作 的函数仅可用于以下目录(报价):

编辑切换为居中
/HISTORY/<current broker> - 尤其对于 FileOpenHistory 函数;
/EXPERTS/FILES - 普通情况;
/TESTER/FILES - 尤其针对测试。
禁止处理其他目录的文件。
如果你仍需在目录以外工作(出于安全原因),你可以调用 Windows OS 的函数。为此,出现在 kernel32.dll 库中的 API 函数已广泛使用。
Kernel32.dll 的文件函数
是基于 无限制文件操作下 CodeBase 内发现的脚本。这是如何将函数导入 赫兹期货量化程序的很好例子。
// constants for function _lopen #define OF_READ 0 #define OF_WRITE 1 #define OF_READWRITE 2 #define OF_SHARE_COMPAT 3 #define OF_SHARE_DENY_NONE 4 #define OF_SHARE_DENY_READ 5 #define OF_SHARE_DENY_WRITE 6 #define OF_SHARE_EXCLUSIVE 7 #import "kernel32.dll" int _lopen (string path, int of); int _lcreat (string path, int attrib); int _llseek (int handle, int offset, int origin); int _lread (int handle, string buffer, int bytes); int _lwrite (int handle, string buffer, int bytes); int _lclose (int handle); #import
这些函数在 msdn 内显示为过时,但仍可以使用,请参见 Obsolete Windows Programming Elements(过时的 Windows 编程元素)。我将在此给出从线程中直接取出的函数和参数的描述,这些描述均由脚本作者 mandor给出:
// _lopen : It opens the specified file. It returns: file descriptor. // _lcreat : It creates the specified file. It returns: file descriptor. // _llseek : It places the pointer in the open file. It returns: // the new shift of the pointer. // _lread : It reads the given number of bytes from the open file. // It returns: the number of the read bytes; 0 - if it is the end of the file. // _lwrite : It writes the data from buffer into the specified file. It returns: // the number of written bytes. // _lclose : It closes the specified file. It returns: 0. // In case of unsuccessfully completion, all functions return the value of // HFILE_ERROR=-1. // path : String that defines the path and the filename. // of : The way of opening. // attrib : 0 - reading or writing; 1 - only reading; 2 - invisible, or // 3 - system file. // handle : File descriptor. // offset : The number of bytes, by which the pointer shifts. // origin : It indicates the initial point and the shifting direction: 0 - // forward from the beginning; 1 - from the current position; 2 - backward from the end of the file. // buffer : Receiving/writing buffer. // bytes : The number of bytes to read. // Methods of opening (parameter 'of'): // int OF_READ =0; // Open file for reading only // int OF_WRITE =1; // Open file for writing only // int OF_READWRITE =2; // Open file in the read/write mode // int OF_SHARE_COMPAT =3; // Open file in the mode of common // shared access. In this mode, any process can open this given // file any amount of times. At the attempt to open this file in any other // mode, the function returns HFILE_ERROR. // int OF_SHARE_DENY_NONE =4; // Open file in the mode of common access // without disabling the reading/writing by another process. At the attempt to open // this file in the mode of OF_SHARE_COMPAT, the function returns HFILE_ERROR. // int OF_SHARE_DENY_READ =5; // Open file in the mode of common access with // disabling the reading by another process. At the attempt to open this file // with the flags of OF_SHARE_COMPAT and/or OF_READ, or OF_READWRITE, the function // returns HFILE_ERROR. // int OF_SHARE_DENY_WRITE=6; // The same, but with disabling the writing. // int OF_SHARE_EXCLUSIVE =7; // Disable for this current and for all other processes // to access to this file in the modes of reading/writing. The file in this mode can be // opened only once (with the current process). All other attempts // to open the file will fail.
函数 “Reading from File”
让我们讨论下用于文件读取的函数。该函数仅有的参数是包含文件名的字符串变量。导入的函数 _lopen(path,0) 返回指向一个开放文件的指针,其任务与 赫兹期货量化中的函数 FileOpen() 很相似。
//+------------------------------------------------------------------+ //| read the file and return a string with its contents | //+------------------------------------------------------------------+ string ReadFile (string path) { int handle=_lopen (path,OF_READ); if(handle<0) { Print("Error opening file ",path); return (""); } int result=_llseek (handle,0,0); if(result<0) { Print("Error placing the pointer" ); return (""); } string buffer=""; string char1="x"; int count=0; result=_lread (handle,char1,1); while(result>0) { buffer=buffer+char1; char1="x"; count++; result=_lread (handle,char1,1); } result=_lclose (handle); if(result<0) Print("Error closing file ",path); return (buffer); }
函数 _lseek() 在 赫兹期货量化内也有相似函数。它是 FileSeek()。函数 _lclose 用于关闭文件,如函数 FileClose()。仅有的新函数为_lread(handle, buffer, bytes),它将给定文件(该文件指针最初须由函数 _lopen() 接收)给定字节数读取到变量“buffer”。你应使用必要长度的字符串常量作为“buffer”变量。在此示例中,我们可以看到:
string char1="x"; result=_lread (handle,char1,1);
- 字符串常量 ‘char’ 给定长度为 1,即该常量仅允许一个字节读取到其中。同时,此常量的值无关紧要,可为 “x”和“Z” ,甚至是" " (空白字符)。你无法向常量中读取超出其初始定义的字节数。在这种情况下,读取 2 或者更多字节的尝试将失败。此外,函数 _lread() 的结果是真正读取的字节数。如果文件大小是 20 字节,且你尝试在 30-字节长的变量内读入超出 20 字节的内容,则函数将返回 20。如果赫兹期货量化连续应用该函数,赫兹期货量化将沿一个接一个读取文件块的文件方向移动。例如,文件大小为 22 字节。我们以 10 字节块开始读取。然后,经过两次调用函数 __lread(handle, buff, 10),文件末端的字节将维持未读状态。

编辑切换为居中
第三次调用时,__lread(handle, buff, 10)将返回 2,即最后的 2 字节将读取。第四次调用时,函数将返回零值 - 没有字节读取,指针位于文件末端。这个事实构成了从循环中读取文件字符的过程:
while(result>0) { buffer=buffer+char1; char1="x"; count++; result=_lread (handle,char1,1); }
只要结果(读取字节数)大于零,函数 _lread(handle, char1, 1)便在循环中调用。如你所见,这些函数并不复杂。读取字符的值保存在名为 char1 的变量内。该字符在下次迭代时从字符串变量“buffer”中写入。完成操作时,用户定义的函数 ReadFile() 返回该在变量读取的文件内容。如你所见,这不会有任何困难。
函数 "Writing to File"
写入在某种意义上来说比读取更简单。你应打开一个文件然后使用函数(int handle, string buffer, int bytes)向其中写入一条字节数组。在此,handle 是由函数 _lopen() 获得的文件指针,参数‘buffer’是字符串变量,参数‘bytes’显示应写入的字节数量。写入时,应使用函数 _lclose() 关闭文件。赫兹期货量化讨论作者的函数 WriteFile():
//+------------------------------------------------------------------+ //| write the buffer contents to the given path | //+------------------------------------------------------------------+ void WriteFile (string path, string buffer) { int count=StringLen (buffer); int result; int handle=_lopen (path,OF_WRITE); if(handle<0) { handle=_lcreat (path,0); if(handle<0) { Print ("Error creating file ",path); return; } result=_lclose (handle); } handle=_lopen (path,OF_WRITE); if(handle<0) { Print("Error opening file ",path); return; } result=_llseek (handle,0,0); if(result<0) { Print("Error placing pointer"); return; } result=_lwrite (handle,buffer,count); if(result<0) Print("Error writing to file ",path," ",count," bytes"); result=_lclose (handle); if(result<0) Print("Error closing file ",path); }