如何将 Windows 驱动器盘符从我的改革路径中删除?德尔福或帕斯卡

发布于 2025-01-08 22:02:14 字数 1027 浏览 0 评论 0原文

进一步

简而言之,我有一个串联路径的字符串值,该字符串值是通过获取源目录并在目标目录中重新创建该树而形成的。例如

C:\SourceDir\SubDirA 变成 F:\DestinationDir\SourceDir\SubDirA。

但是,我为 Linux 版本的程序提供的解决方案(如上面链接中发布的)不太适用于 Windows 版本,因为我最终得到的是:

F:\DestionationDir\C:SourceDir\SubDirA。

这是无效的。

因此,我想出了这个“仅在 Windows 中运行”代码来删除改革路径的中心驱动器号,但将第一个驱动器号保留在开头,并说“查看从左侧第 4 个字符开始的字符串。如果您找到‘C:’,将其删除”,使路径变为 F:\DestinationDir\SourceDir\SubDirA。

{$IFDEF Windows} // Only do this for the Windows version
    k := posex('C:', FinalisedDestDir, 4);  // Find 'C:' in the middle of the concatanated path and return its position as k
    Delete(FinalisedDestDir, k, 2);  // Delete the 2 chars 'C:' of 'C:\' if found, leaving the '\' to keep the path valid
{$ENDIF}   

现在,如果 C: 是所选目录的源,则效果很好。但显然,如果用户从另一个驱动器(例如 E:、F:、G: 或 Z: 之前的任何其他驱动器)复制数据,则它将无法工作。

所以我的问题是,如何对其进行编码,以便它显示“如果在左侧第四个字符之后找到任何驱动器号 a: 到 z:,请将其删除”?虽然任何有效的解决方案“都可以”,但理想情况下我需要一个快速的解决方案。最好的解决方案是首先不将其放入其中,但是考虑到我在回复之前的帖子时发布的解决方案,由于我用来形成的程序,我无法弄清楚如何不将其放入其中它。

Further to this answered question I have another sticky problem. My coding is Free Pascal but Delphi solutions will work probably.

In brief, I have a string value of concatenated paths that is formed by taking a source directory and recreating that tree in a destination directory. e.g.

C:\SourceDir\SubDirA
becomes
F:\DestinationDir\SourceDir\SubDirA.

However, the solution I have for the Linux version of my program (as posted in the link above) doesn't quite work with Windows version because I end up with :

F:\DestionationDir\C:SourceDir\SubDirA.

which is invalid.

So I came up with this "only run in Windows" code to remove the central drive letterof the reformed path, but leave the initial one at the start by saying "Look at the string starting from the 4th character in from the left. If you find 'C:', delete it" so that the path becomes F:\DestinationDir\SourceDir\SubDirA.

{$IFDEF Windows} // Only do this for the Windows version
    k := posex('C:', FinalisedDestDir, 4);  // Find 'C:' in the middle of the concatanated path and return its position as k
    Delete(FinalisedDestDir, k, 2);  // Delete the 2 chars 'C:' of 'C:\' if found, leaving the '\' to keep the path valid
{$ENDIF}   

Now, that works fine IF the C: is the source of the chosen directory. But obviously if the user is copying data from another drive (such as E:, F:, G: or whatever else drive up to Z:) it will not work.

So my question is, how do I code it so that it says "if any drive letter a: to z: is found after the 4th character from the left, delete it"? Whilst any solution that works "will do", ideally I need a fast solution. The best solution would be to not have it in there in the first place, but given the solution I posted in reply to my earlier post, I can't work out how not to have it in, due to the procedure I use to form it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小镇女孩 2025-01-15 22:02:14

这是我在应用程序中使用的代码:

function CombinePath(const BaseDir, Path: string): string;
begin
  if IsPathDelimiter(Path, 1) then
    Result := ExcludeTrailingBackSlash(BaseDir) + Path else
    Result := IncludeTrailingBackSlash(BaseDir) + Path;
end;

function MapRootPath(const Path, NewPath: string): string;
var
  Drive, RelativePath: string;
begin
  Drive := ExtractFileDrive(Path); // e.g: "C:"
  RelativePath := ExtractRelativePath(Drive, Path); // e.g: "Program Files\MyApp"
  Result := CombinePath(NewPath, RelativePath);
end;

用法:

ShowMessage(MapRootPath('C:\SourceDir\SubDirA', 'F:\DestionationDir'));
// result is "F:\DestionationDir\SourceDir\SubDirA"

Here is a code I use in my application:

function CombinePath(const BaseDir, Path: string): string;
begin
  if IsPathDelimiter(Path, 1) then
    Result := ExcludeTrailingBackSlash(BaseDir) + Path else
    Result := IncludeTrailingBackSlash(BaseDir) + Path;
end;

function MapRootPath(const Path, NewPath: string): string;
var
  Drive, RelativePath: string;
begin
  Drive := ExtractFileDrive(Path); // e.g: "C:"
  RelativePath := ExtractRelativePath(Drive, Path); // e.g: "Program Files\MyApp"
  Result := CombinePath(NewPath, RelativePath);
end;

Usage:

ShowMessage(MapRootPath('C:\SourceDir\SubDirA', 'F:\DestionationDir'));
// result is "F:\DestionationDir\SourceDir\SubDirA"
九公里浅绿 2025-01-15 22:02:14

我为您提供两种解决方案:

在连接文件夹之前标准化您的路径

您知道这句话,预防总是胜于治疗。为什么不在进行串联之前“标准化”路径?这使您有机会:

  • 如果名称以路径开头,则从路径中删除驱动器号。如果字符串中的第二个字符是 :,第三个字符是 \,则您知道它是包含驱动器号的 Windows 路径。您可以删除所有前 3 个字符。
  • 处理 UNC 名称,您没有提到这些: \\ComputerName\ShareName\SubFolder
  • 修复斜杠,使它们符合您当前的平台

稍后删除驱动器号

这很丑陋(因为您不应该得到首先进入这种情况),但您始终可以查找 :\ - 而不是 C:: 在 Windows 上的文件夹或文件名中无效,因此如果您找到它,您就知道它前面正好有一个字符,那就是 DRIVE 字母。获取 :\ 的索引,减去 `,从该索引中删除 2 个字符。

I offer you two solutions:

Normalize your paths before concatenating folders

You know the saying, prevention is always better then the cure. Why don't you "normalize" paths before you do your concatentations? This gives you the chance to:

  • Delete the drive letter from the path if the name starts with a path. If the second char in the string is : and the third is \ you know it's a Windows path containing a drive letter. You may delete all of the first 3 characters.
  • Deal with UNC names, you didn't mention those: \\ComputerName\ShareName\SubFolder
  • Fix slashes so they conform to your current platform

Remove the drive letter later

This is ugly (because you shouldn't get into this situation in the first place), but you can always look for :\ - not for C:. The : is not valid in folder or file names on windows, so if you find it you know it's preceded by exactly one char, and that's the DRIVE letter. Get the index for :\, substract `, delete 2 chars from that index.

多情出卖 2025-01-15 22:02:14

我不知道 freepascal,但对于这个问题,请使用正则表达式,例如 [A-Za-z]\: 来查找这样的字符串。我从 freepascal wiki 看到它支持正则表达式http://wiki.freepascal.org/Regexpr

I don't know freepascal but for this problem use regular expression such as [A-Za-z]\: to find such string. I see from freepascal wiki that it supports regular expressions http://wiki.freepascal.org/Regexpr.

神经大条 2025-01-15 22:02:14

您还可能会看到一些 SysUtils 函数是否可以提供帮助,包括:

  • ExpandFileName()

  • IncludeTrailingSlashes()

  • 等..

将您的路径置于“规范化”形式(就像这些函数可能为您做的那样)使得在 Linux 和 Windows 路径约定之间进行转换变得很简单。

只是一个想法...

You might also see if some of the SysUtils functions can help, including:

  • ExpandFileName()

  • IncludeTrailingSlashes()

  • etc..

Putting your path in a "normalized" form - like these functions might be able to do for you - makes it trivial to convert between Linux and Windows path conventions.

Just a thought...

标点 2025-01-15 22:02:14

感谢您对此提供的所有帮助。特别感谢 kobik,他的代码示例非常清晰且易于理解。这当然是一种方法,但在我等待回复时,我想出了以下方法,这似乎对我来说也很有效:

type
TRange = 'A'..'Z';
...

{$IFDEF Windows}
    // Due to the nonsenseories of Windows, we have to allow for driver lettering.

  for DriveLetter in TRange do
      begin
        k := posex(DriveLetter+':', FinalisedDestDir, 4);  // Find e.g 'C:' in the middle of the concatanated path and return its position, leaving the first 'C:\' at the start in place
        Delete(FinalisedDestDir, k, 2);  // Delete 'C:' of 'C:\' if found, leaving the '\'
      end;
{$ENDIF}

Thanks for all the help with this. Special thanks to kobik who's code sample is very clear and easy to follow. That is certainly one way to do it, but whilst I was waiting for replies I came up with the following which also seems to work quite well for me :

type
TRange = 'A'..'Z';
...

{$IFDEF Windows}
    // Due to the nonsenseories of Windows, we have to allow for driver lettering.

  for DriveLetter in TRange do
      begin
        k := posex(DriveLetter+':', FinalisedDestDir, 4);  // Find e.g 'C:' in the middle of the concatanated path and return its position, leaving the first 'C:\' at the start in place
        Delete(FinalisedDestDir, k, 2);  // Delete 'C:' of 'C:\' if found, leaving the '\'
      end;
{$ENDIF}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文