Чтение файлов из архива tar.gz в Nim

Ищите способ чтения файла из архива tar.gz с использованием языка программирования Nim (версия 0.11.2). Скажи у меня есть архив

/my/path/to/archive.tar.gz

и файл в этом архиве

my/path/to/archive/file.txt

Моя цель - прочитать содержимое файла построчно в Nim. В Python я могу сделать это с помощью модуля tarfile. В Nim есть модули libzip и zlib, но документация минимальна и примеров нет. Есть также модуль zipfiles, но я не уверен, что он способен работать с архивами tar.gz.

3 ответа

Решение

Насколько мне известно, libzip и zlib нельзя использовать для чтения файлов tar (afaik поддерживает только архивы zip и / или сжатие необработанных строк, в то время как tar.gz требует gzip + tar). К сожалению, похоже, что пока нет библиотек Nim, которые читают архивы tar.gz.

Если ты в порядке с быстрым и грязным tarрешение, вы можете сделать это:

import osproc

proc extractFromTarGz(archive: string, filename: string): string =
  # -z extracts
  # -f specifies filename
  # -z runs through gzip
  # -O prints to STDOUT
  result = execProcess("tar -zxf " & archive & " " & filename & " -O")

let content = extractFromTarGz("test.tar.gz", "some/subpath.txt")

Если вам нужно чистое и гибкое решение, это хорошая возможность написать оболочку для библиотеки libarchive;).

В проекте моей компании мы использовали следующий модуль, представляющий файлы gzip в виде потоков:

import
  zlib, streams

type
  GZipStream* = object of StreamObj
    f: GzFile

  GzipStreamRef* = ref GZipStream

proc fsClose(s: Stream) =
  discard gzclose(GZipStreamRef(s).f)

proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
  return gzread(GZipStreamRef(s).f, buffer, bufLen)

proc fsAtEnd(s: Stream): bool =
  return gzeof(GZipStreamRef(s).f) != 0

proc newGZipStream*(f: GzFile): GZipStreamRef =
  new result
  result.f = f
  result.closeImpl = fsClose
  result.readDataImpl = fsReadData
  result.atEndImpl = fsAtEnd
  # other methods are nil!

proc newGZipStream*(filename: cstring): GZipStreamRef =
  var gz = gzopen(filename, "r")
  if gz != nil: return newGZipStream(gz)

Но вам также необходимо иметь возможность прочитать заголовок tar, чтобы найти правильное местоположение нужного файла в несжатом потоке gzip. Для этого вы можете обернуть какую-нибудь существующую библиотеку C, например libtar, или развернуть собственную реализацию.

Я создал основной untar пакет, который может помочь с этим: https://github.com/dom96/untar

Другие вопросы по тегам