如何在 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 stat64stat64()

正常编译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 中读取大文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swing 中读取和显示大文本文件?

如何在 pyspark 中读取大的 zip 文件

如何逐行读取大文件?

解决java读取大文件内存溢出问题,如何在不重

如何在 .NET 中读取大 (1GB) 文本文件?

如何在objective-c中按范围读取大文件?