6

I have a program that reads and writes a text file that exists in the same directory as the executable. To access that file, I call readFile "./file.txt"

This works when I run the executable from within the directory where it lives. However if i cd to another directory and run the executable (it's on my path), Haskell tries to get the file.txt from the working directory in my terminal. How do I make Haskell access the file.txt from the location of the executable and not my working directory. I don't want to hardcode an absolute path because I want the executable to be somewhat portable.

4

4 回答 4

8

正确的方法是file.txt在文件的data-files字段中列出.cabal并用于getDataFileName检索它。有关前缀独立性,请参阅cabal 文档

于 2012-09-11T01:42:47.317 回答
6

该功能getExecutablePath可以满足您的要求。不幸的是,它只被添加到System.Environment刚刚发布的 GHC 7.6.1 中,还没有被整合到 Haskell 平台中。

编辑:具有此功能的较新的 Haskell 平台已经发布。

于 2012-09-11T03:39:58.923 回答
5

为什么不将您的文件存储在官方应用程序目录中?那么当前目录是什么都没有关系。(请参阅 getAppUserDataDirectory。)

System.Directory中还有其他有用的目录和方便的文件系统实用程序。它是跨平台的,因为它知道根据您的操作系统应该去哪里。

推理:
如果您将工作数据与可执行文件存储在同一目录中,则只有在该目录中具有写入权限的人才能正确运行您的程序。只有超级用户可以写入类似的目录,/usr/local/bin并且只有管理员可以写入C:\Program Files\. 使用用户应用程序目录,任何人都可以运行应用程序,因为应用程序数据目录是特定于用户的并且可由他们写入,因此这是一种好的做法。

就我个人而言,我不喜欢应用程序将我的主要用户区域与配置数据混淆,但确实希望应用程序因此建议我的用户区域作为第一个猜测来保存我自己的一些内容(getHomeDirectory)。我建议了用户应用程序数据目录,因为您建议了可执行文件的目录,所以它听起来像配置数据。

于 2012-09-11T01:47:00.207 回答
0
#!/usr/bin/env stack
{- stack
   script
   --nix
   --nix-packages zlib
   --resolver lts-14.17
   --package turtle
   --package protolude
   --package directory
-}

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}

module Playground where

import Protolude hiding (find)
import Turtle
import System.Directory
import Data.String

main :: IO ()
main = do
  let thisScriptAbsFilePath :: String = __FILE__
  let thisScriptAbsFilePath' :: Turtle.FilePath = decodeString thisScriptAbsFilePath
  let projectRoot :: Turtle.FilePath = directory thisScriptAbsFilePath'
  print projectRoot
  return ()
于 2019-12-14T12:48:02.190 回答