在C++中指定路径写入文件

19

我有这段代码可以成功写入文件:

    ofstream outfile (path);
    outfile.write(buffer,size);
    outfile.flush();
    outfile.close();

在代码的其他部分,缓冲区和大小都没问题。如何将文件放入特定路径?


检查您的文件系统和平台的文档。 - Kerrek SB
1
你是如何构建 outfile 的? - hmjd
你的代码中没有文件打开操作。这是决定文件名的关键。 - sehe
你使用的是哪个平台和框架? - rerun
7个回答

17

在流的构造函数中指定完整路径,可以是绝对路径或相对路径(相对于程序运行的位置)。

流的析构函数会在创建对象的函数结束时为您关闭文件(因为 ofstream 是一个 class)。

当您想要重复使用同一文件描述符进行另一个文件操作时,显式关闭是一个好的做法。如果不需要这样做,可以让析构函数完成它的工作。

#include <fstream>
#include <string>

int main()
{
    const char *path="/home/user/file.txt";
    std::ofstream file(path); //open in constructor
    std::string data("data to write to file");
    file << data;
}//file destructor

请注意,在C++11中,您可以在文件构造函数中使用std::string,并且在大多数情况下,它优于const char*。


1
在 C++11 之前的版本中,使用 std::string::c_str() 获取构造函数或 open 方法所需的 C 语言字符串类型。 - Thomas Matthews
4
@ThomasMatthews 这是正确的,我建议仍然按照你建议的方式使用字符串,然而我想表明的是ofstream接受一个const char*(可以通过你展示的方式获得)。 - 111111

10

为何需要发布另一个答案

我发布这篇文章是因为其他答案都没有涵盖此问题。

回答这个问题取决于您如何获取路径。如果您完全在您的应用程序中构建路径,则请参见@James Kanze的答案。但是,如果您从运行程序的环境中读取路径或路径组件(例如环境变量,命令行,配置文件等),则解决方案不同。为了理解原因,我们需要定义什么是路径。

路径的快速概述

在我所知道的操作系统上,路径是符合操作系统和文件系统(简称系统)指定的迷你语言规范的字符串。可以将路径提供给给定系统上的IO函数以访问某些资源。例如,这里是您可能在Windows上遇到的一些路径:

\file.txt
\\bob\admin$\file.txt
C:..\file.txt
\\?\C:\file.txt
.././file.txt
\\.\PhysicalDisk1\bob.txt
\\;WebDavRedirector\bob.com\xyz
C:\PROGRA~1\bob.txt
.\A:B

通过路径操作解决问题

想象以下场景:你的程序支持一个命令行参数--output-path=<path>,允许用户提供一个路径,在这个路径下创建输出文件。实现在指定目录下创建文件的解决方案如下:

  1. 基于你所操作的系统的迷你语言解析用户指定的路径。
  2. 使用文件名和步骤1中解析到的信息,在迷你语言中构建一个指定正确位置写入文件的新路径。
  3. 使用步骤2生成的路径打开文件。

下面是一个例子:

在Linux上,假设用户指定了--output-path=/dir1/dir2

解析这个迷你语言:

/dir1/dir2
--> "/" root
--> "dir1" directory under root
--> "/" path seperator
--> "dir2" directory under dir1

当我们想要在指定的目录中输出文件时,我们会构建新路径。例如,如果我们想要输出一个名为bob.txt的文件,我们可以构建以下路径:

/dir1/dir2/bob.txt
--> "/" root
--> "dir1" directory under root
--> "/" path separator
--> "dir2" directory under dir1
--> "/" path seperator
--> "bob.txt" file in directory dir2

我们可以使用这个新路径来创建文件。
一般来说,完全实现这个解决方案是不可能的。即使你能编写成功解码所有路径小语言并正确表示每个系统信息的代码,以便可以正确构建新路径 - 在未来,您的程序可能会在无法处理的新路径小语言上构建或运行新系统。因此,我们需要使用谨慎的策略来管理路径。
路径处理策略:
1. 完全避免路径操作
不要尝试操作输入到程序中的路径。您应该直接将这些字符串传递给可以正确处理它们的API函数。这意味着您需要直接使用特定于操作系统的API,避免使用C++文件IO抽象(或者您需要确切地了解这些抽象在每个操作系统上的实现方式)。请务必仔细设计程序的接口,以避免可能被迫操作路径的情况。尝试实现程序算法,同样避免需要操作路径。向用户记录程序在每个操作系统上使用的API函数 - 这是因为操作系统API函数本身随时间而过时,因此即使您小心避免路径操作,在未来,您的程序也可能与所有可能的路径不兼容。
2. 记录程序用于操作路径的函数
向用户详细说明如何操作路径。然后明确指出,用户有责任指定能够正确工作的路径,以符合记录下来的程序行为。
3. 仅支持一组受限制的路径
限制程序将接受的路径小语言,直到您有信心正确操作满足此限制集的路径子集。向用户记录此内容。如果输入不符合要求,则报错。
4. 忽略这些问题
进行一些基本的路径操作,不要过于担心。接受您的程序对某些输入路径展示未定义行为的事实。您可以向用户记录程序可能或可能不会在他们向其输入路径时正常工作,并且用户有责任确保程序正确处理了输入路径。但是,您也可以不记录任何内容。用户通常期望您的程序无法正确处理某些路径(许多程序都是如此),因此即使没有文档,他们也能很好地应对。
总之,在程序生命周期的早期决定有效的路径处理策略非常重要。如果必须稍后更改路径处理方式,则可能难以避免行为更改,这可能会破坏现有用户的程序。

1

试试这个:

ofstream outfile;
string createFile = "";    
string path="/FULL_PATH";

createFile = path.as<string>() + "/" + "SAMPLE_FILENAME" + ".txt";          
outfile.open(createFile.c_str());       
outfile.close();

//It works like a charm.

1
path.as<string>() 函数是什么?我以前从未见过这样的东西。 - jvriesem

0

当你打开文件时,需要执行以下操作,请参见std::ofstream构造函数open()成员。


0

不太清楚你的问题是什么;如果我理解正确,你有一个文件名,并且想要在特定目录中创建该文件。如果是这种情况,只需在ofstream的构造函数中指定完整路径即可。您可以使用字符串连接来构建此路径,但我强烈建议使用boost::filesystem::path。它具有所有可移植性所需的功能,而且还有很多其他功能;否则,您将无法实现可移植性(需要大量努力),即使对文件名进行简单操作也需要考虑很多事情。


ofstream 构造函数或 open() 方法是否会在路径中创建缺失的目录? - hmjd
实现定义,但我不知道有哪个实现会这样做。使用boost::filesystem的另一个原因是:如果需要,它有一个简单的函数可以完成此操作。 - James Kanze

0

我曾经卡在这里一段时间,但现在已经解决了。路径是基于你的可执行文件所在的位置,并且会有一些变化。以这个例子为例,在你的可执行目录中执行ls命令,你会看到:

myprogram.out  Saves  

其中Saves是一个文件夹,myprogram.out是你正在运行的程序。

如果你在代码中将字符转换为c_str(),可以像这样进行:

string file;
getline(cin, file, '\n');
ifstream thefile;
thefile.open( ("Saves/" + file + ".txt").c_str() );

如果用户输入了“savefile”,那么它将是什么?
"Saves/savefile.txt"   

这将起作用,以便访问您的“Saves”文件夹中的“savefile.txt”。请注意,没有前置斜杠,您只需从文件夹名称开始。

但是,如果您使用字符串文字,则需要在路径中使用双反斜杠来转义反斜杠。例如:

ifstream thefile;
thefile.open("./Saves/savefile.txt");

要访问相同的文件夹,可以这样做:

"./Saves/savefile.txt"  

注意在文件夹名称前面要加上./


-1
如果您正在使用Linux,可以尝试使用execl()函数,并使用mv命令。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接