Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中列出TAR归档_Haskell_Tar - Fatal编程技术网

在Haskell中列出TAR归档

在Haskell中列出TAR归档,haskell,tar,Haskell,Tar,我目前正试图找出如何在Haskell中列出(gzip)TAR归档文件。似乎是任务的正确选择,但我不知道如何将入口路径映射到条目上 假设TAR包含条目(仅文件)a.txt、b.txt、c.txt,并命名为foo.TAR.gz。以下是我读取文件的代码: import qualified Codec.Archive.Tar as Tar import qualified Data.ByteString.Lazy as BS import qualified Codec.Compression.GZip

我目前正试图找出如何在Haskell中列出(gzip)TAR归档文件。似乎是任务的正确选择,但我不知道如何将
入口路径映射到
条目上

假设TAR包含条目(仅文件)
a.txt、b.txt、c.txt
,并命名为
foo.TAR.gz
。以下是我读取文件的代码:

import qualified Codec.Archive.Tar as Tar
import qualified Data.ByteString.Lazy as BS
import qualified Codec.Compression.GZip as GZip

foldEntryToPath :: Tar.Entry -> [String] -> [String]
foldEntryToPath entry list = list ++ [show $ Tar.entryPath entry]

-- Converts TAR errors to a string.
entryFailMapper :: String -> [String]
entryFailMapper err = [err]

main = do
        fileContent <- fmap GZip.decompress $ BS.readFile "foo.tar.gz"
        entries <- fmap Tar.read fileContent :: Tar.Entries
        -- Here I don't know how to correctly apply fmap
        entryPaths <- Tar.foldEntries foldEntryToPath [] entryFailMapper entries :: [String]
        -- This should print ["a.txt", "b.txt", "c.txt"]
        print entryPaths
到目前为止,我对Haskell知之甚少,但通过阅读,我不知道为什么
Tar.Entries
是一个typeclass(当它说
需要n个参数时,这是正确的术语吗?)或者正确的类型是什么


任何帮助都将不胜感激

我认为
folderntropath
需要修复:

foldEntryToPath :: Tar.Entry -> [String] -> [String]
foldEntryToPath entry list = (show $ Tar.entryPath entry) : list

fileContent <- fmap GZip.decompress $ BS.readFile "foo.tar.gz"
let entries = Tar.read fileContent
let entryPaths = Tar.foldEntries foldEntryToPath [] entryFailMapper entries
print entryPaths

fileContent我现在有了一个完整的工作示例

主要问题之一是
Tar.foldEntries
foldr
类行为。实际上,我有一个约25GB的TAR文件,其中包含数百万条条目。有关为什么这是一个坏主意的信息,请参阅。(注意:效率不是问题,但我认为
foldEntries
-免费解决方案更适合这个特定用例

因此,我编写了自己的递归
Tar.Entries->[String]
映射函数

import qualified Codec.Archive.Tar as Tar
import qualified Data.ByteString.Lazy as BS
import qualified Codec.Compression.GZip as GZip

entriesToPaths :: Tar.Entries Tar.FormatError -> [String]
entriesToPaths (Tar.Next entry entries) = [Tar.entryPath entry] ++ entriesToPaths entries
entriesToPaths Tar.Done = [] :: [String]
entriesToPaths (Tar.Fail e) = ["Error"]

main = do
        fileContent <- fmap GZip.decompress $ BS.readFile "foo.tar.gz"
        let entries = Tar.read fileContent
        let entryPaths = entriesToPaths entries
        -- This should print ["a.txt", "b.txt", "c.txt"]
        print entryPaths
将合格的Codec.Archive.Tar导入为Tar
将限定数据.ByteString.Lazy导入为BS
将合格的Codec.Compression.GZip导入为GZip
entriesToPaths::Tar.Entries Tar.FormatError->[字符串]
entriesToPaths(Tar.Next条目)=[Tar.entryPath条目]++entriesToPaths条目
entriesToPaths Tar.Done=[]:[String]
entriesToPaths(Tar.Fail e)=[“错误”]
main=do

fileContent注意,这不是lib的最新版本。@Vektorweg谢谢,我没有注意到(我更新了链接!)。但是这只是文档链接(首先通过google找到),我使用
cabal install tar
安装了lib,它实际上安装了0.4.0.1感谢您的努力!我在您发布前几秒钟就有了自己的代码。据我所知,通过您的更改,代码运行良好,但是
foldr
-like
foldEntries
的行为表现出一些严重的性能问题me案例(但是我没有特别要求性能和/或内存效率,因此您的帖子仍然正确)。请参阅我的答案,以获得替换为
foldEntries
的替代解决方案。当我将问题中的更改应用于代码时,我在第15行遇到此错误:
无法将type
Tar.FormatError'与'[Char]匹配“`。你能重现这个问题吗?在这种情况下,我不明白你对foldr的负面评论,因为你的entriesToPaths函数只是一个手写的foldr。@kosmikus我想你是对的。我原本以为我实现了foldl,但事实并非如此。然而,基于
foldEntries
的解决方案仍然在我的计算机上挥之不去e我自己的实现没有这样做。我明天会再次检查您的解决方案,可能问题不是由
foldEntries
本身引起的,而是由另一个语句引起的。好吧,在您的问题中,在
foldEntryToPath
中,您将新元素添加到列表的末尾。这永远不会有效率。在这个解决方案中,在
entryToPaths
,您将新条目追加到开头。因此,这一差异很重要。无论您是否使用
foldEntries
import qualified Codec.Archive.Tar as Tar
import qualified Data.ByteString.Lazy as BS
import qualified Codec.Compression.GZip as GZip

entriesToPaths :: Tar.Entries Tar.FormatError -> [String]
entriesToPaths (Tar.Next entry entries) = [Tar.entryPath entry] ++ entriesToPaths entries
entriesToPaths Tar.Done = [] :: [String]
entriesToPaths (Tar.Fail e) = ["Error"]

main = do
        fileContent <- fmap GZip.decompress $ BS.readFile "foo.tar.gz"
        let entries = Tar.read fileContent
        let entryPaths = entriesToPaths entries
        -- This should print ["a.txt", "b.txt", "c.txt"]
        print entryPaths