如何在 Ada 中读取大文件?
Posted
技术标签:
【中文标题】如何在 Ada 中读取大文件?【英文标题】:How can I read large filesizes in Ada? 【发布时间】:2012-10-28 21:00:49 【问题描述】:我编写了一个加密文件的 Ada 程序。它逐块读取它们以节省目标机器上的内存。不幸的是,Ada 的目录库读取 Long_Integer 中的文件大小,将读取限制为近 2GB 文件。尝试读取超过 2GB 的文件时,程序在运行时失败,出现堆栈溢出错误。
它的文档here 是我上面理解的起源。如何将文件大小读入我自己定义的类型?我可以将上限增加到 100GB,需要 25 个字节。
【问题讨论】:
您不需要 25 个字节来保存该大小的数字; 8 个字节(64 位)绰绰有余。 Ada 标准的定义是type File_Size is range 0 ..
*implementation-defined*;
。 GNAT,至少在我拥有的版本中,有File_Size'Last = 9223372036854775807
。你用的是什么编译器?你确定这是堆栈溢出吗?这不是我所期望的错误。试试Ada.Text_IO.Put_Line(Ada.Directories.File_Size'Image(Ada.Directories.File_Size'Last));
查看 GNAT GPL 2012 的源代码,adaint.c
在__gnat_stat_to_attr()
中说“st_size 可能是 32 位,或 64 位转换为长整数。我们不返回有用的值无论哪种情况,文件都大于 2 GB。”它的实际意思是“我们不会费心检查操作系统报告的文件大小是否适合 32 位结果,我们只是分配它。”在 Mac OS X 上,这会丢弃 64 位结果的前 32 位,并可能给出明显的否定结果。我认为您可能必须通过stat(2)
(或您的操作系统上的等效项)读取文件大小。
@SimonWright:你是对的;在我的系统上,File_Size
是 64 位,但 Size()
函数的结果会丢弃除低位 32 位之外的所有位。这是 GNAT 中的一个错误。
【参考方案1】:
我刚刚在此发布了GCC bug 55119。
在您等待时 (!),以下代码可在 Mac OS X Mountain Lion 上运行。在 Windows 上,它更复杂。见adainclude/adaint.c,h
。
Ada 规范:
with Ada.Directories;
package Large_Files is
function Size (Name : String) return Ada.Directories.File_Size;
end Large_Files;
和正文(部分复制自Ada.Directories
):
with GNAT.OS_Lib;
with System;
package body Large_Files is
function Size (Name : String) return Ada.Directories.File_Size
is
C_Name : String (1 .. Name'Length + 1);
function C_Size (Name : System.Address) return Long_Long_Integer;
pragma Import (C, C_Size, "large_file_length");
begin
if not GNAT.OS_Lib.Is_Regular_File (Name) then
raise Ada.Directories.Name_Error
with "file """ & Name & """ does not exist";
else
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
return Ada.Directories.File_Size (C_Size (C_Name'Address));
end if;
end Size;
end Large_Files;
和C接口:
/* large_files_interface.c */
#include <sys/stat.h>
long long large_file_length (const char *name)
struct stat statbuf;
if (stat(name, &statbuf) != 0)
return 0;
else
return (long long) statbuf.st_size;
您可能需要在其他 Unix 系统上使用 struct stat64
和 stat64()
。
正常编译C接口,然后将-largs large_files_interface.o
添加到你的gnatmake命令行。
编辑:在 x86_64 机器的 Mac OS X(和 Debian)上,sizeof(long)
是 8 个字节;所以adaint.c
中的评论具有误导性,Ada.Directories.Size
最多可以返回 2**63-1。
【讨论】:
以上是关于如何在 Ada 中读取大文件?的主要内容,如果未能解决你的问题,请参考以下文章