// Changes the extension of a file path. The path parameter // specifies a file path, and the extension parameter // specifies a file extension (with a leading period, such as // ".exe" or ".cs"). // // The function returns a file path with the same root, directory, and base // name parts as path, but with the file extension changed to // the specified extension. If path is null, the function // returns null. If path does not contain a file extension, // the new file extension is appended to the path. If extension // is null, any existing extension is removed from path. public static string ChangeExtension(string path, string extension) { if (path != null) { PathInternal.CheckInvalidPathChars(path); string s = path; for (int i = path.Length - 1; i >= 0; i--) { char ch = path[i]; if (ch == '.') { s = path.Substring(0, i); break; } if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) { break; } } if (extension != null && path.Length != 0) { s = (extension.Length == 0 || extension[0] != '.') ? s + "." + extension : s + extension; } return(s); } return(null); }
public static string GetExtension(string path) { if (path == null) { return(null); } PathInternal.CheckInvalidPathChars(path); int length = path.Length; for (int i = length - 1; i >= 0; i--) { char ch = path[i]; if (ch == '.') { if (i != length - 1) { return(path.Substring(i, length - i)); } else { return(string.Empty); } } if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) { break; } } return(string.Empty); }
/// <summary> /// Returns the extension of the given path. /// </summary> /// <remarks> /// The returned value is an empty ReadOnlySpan if the given path doesnot include an extension. /// </remarks> public static ReadOnlySpan <char> GetExtension(ReadOnlySpan <char> path) { int length = path.Length; for (int i = length - 1; i >= 0; i--) { char ch = path[i]; if (ch == '.') { if (i != length - 1) { return(path.Slice(i, length - i)); } else { return(ReadOnlySpan <char> .Empty); } } if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) { break; } } return(ReadOnlySpan <char> .Empty); }
private static string CombineNoChecks(string path1, string path2, string path3) { if (path1.Length == 0) { return(CombineNoChecks(path2, path3)); } if (path2.Length == 0) { return(CombineNoChecks(path1, path3)); } if (path3.Length == 0) { return(CombineNoChecks(path1, path2)); } if (IsPathRooted(path3)) { return(path3); } if (IsPathRooted(path2)) { return(CombineNoChecks(path2, path3)); } bool hasSep1 = PathInternal.IsDirectoryOrVolumeSeparator(path1[path1.Length - 1]); bool hasSep2 = PathInternal.IsDirectoryOrVolumeSeparator(path2[path2.Length - 1]); if (hasSep1 && hasSep2) { return(path1 + path2 + path3); } else if (hasSep1) { return(path1 + path2 + PathInternal.DirectorySeparatorCharAsString + path3); } else if (hasSep2) { return(path1 + PathInternal.DirectorySeparatorCharAsString + path2 + path3); } else { // string.Concat only has string-based overloads up to four arguments; after that requires allocating // a params string[]. Instead, try to use a cached StringBuilder. StringBuilder sb = StringBuilderCache.Acquire(path1.Length + path2.Length + path3.Length + 2); sb.Append(path1) .Append(PathInternal.DirectorySeparatorChar) .Append(path2) .Append(PathInternal.DirectorySeparatorChar) .Append(path3); return(StringBuilderCache.GetStringAndRelease(sb)); } }
public static bool HasExtension(ReadOnlySpan <char> path) { for (int i = path.Length - 1; i >= 0; i--) { char ch = path[i]; if (ch == '.') { return(i != path.Length - 1); } if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) { break; } } return(false); }
public static bool HasExtension(string path) { if (path != null) { PathInternal.CheckInvalidPathChars(path); for (int i = path.Length - 1; i >= 0; i--) { char ch = path[i]; if (ch == '.') { return(i != path.Length - 1); } if (PathInternal.IsDirectoryOrVolumeSeparator(ch)) { break; } } } return(false); }
private static string CombineNoChecks(string path1, string path2) { if (path2.Length == 0) { return(path1); } if (path1.Length == 0) { return(path2); } if (IsPathRooted(path2)) { return(path2); } char ch = path1[path1.Length - 1]; return(PathInternal.IsDirectoryOrVolumeSeparator(ch) ? path1 + path2 : path1 + PathInternal.DirectorySeparatorCharAsString + path2); }
public static string Combine(params string[] paths) { if (paths == null) { throw new ArgumentNullException(nameof(paths)); } Contract.EndContractBlock(); int finalSize = 0; int firstComponent = 0; // We have two passes, the first calculates how large a buffer to allocate and does some precondition // checks on the paths passed in. The second actually does the combination. for (int i = 0; i < paths.Length; i++) { if (paths[i] == null) { throw new ArgumentNullException(nameof(paths)); } if (paths[i].Length == 0) { continue; } PathInternal.CheckInvalidPathChars(paths[i]); if (IsPathRooted(paths[i])) { firstComponent = i; finalSize = paths[i].Length; } else { finalSize += paths[i].Length; } char ch = paths[i][paths[i].Length - 1]; if (!PathInternal.IsDirectoryOrVolumeSeparator(ch)) { finalSize++; } } StringBuilder finalPath = StringBuilderCache.Acquire(finalSize); for (int i = firstComponent; i < paths.Length; i++) { if (paths[i].Length == 0) { continue; } if (finalPath.Length == 0) { finalPath.Append(paths[i]); } else { char ch = finalPath[finalPath.Length - 1]; if (!PathInternal.IsDirectoryOrVolumeSeparator(ch)) { finalPath.Append(PathInternal.DirectorySeparatorChar); } finalPath.Append(paths[i]); } } return(StringBuilderCache.GetStringAndRelease(finalPath)); }