Combines two path strings.

image_pdfimage_print
   
 

#region License and Copyright
/* -------------------------------------------------------------------------
 * Dotnet Commons IO
 *
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 
 * for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this library; if not, write to the 
 * 
 * Free Software Foundation, Inc., 
 * 59 Temple Place, 
 * Suite 330, 
 * Boston, 
 * MA 02111-1307 
 * USA 
 * 
 * -------------------------------------------------------------------------
 */
#endregion

using System;
using System.Collections;
using System.Globalization;
using System.IO;

namespace Dotnet.Commons.IO
{
    class MainClass
    {
        /// ---------------------------------------------------------------
        /// <summary>
        /// Combines two path strings.
        /// </summary>
        /// <param name="path1">The first path.</param>
        /// <param name="path2">The second path.</param>
        /// <returns>
        /// A string containing the combined paths. If one of the specified 
        /// paths is a zero-length string, this method returns the other path. 
        /// If <paramref name="path2" /> contains an absolute path, this method 
        /// returns <paramref name="path2" />.
        /// </returns>
        /// <remarks>
        ///   <para>
        ///   On Unix, processing is delegated to <see cref="Path.Combine(string, string)" />.
        ///   </para>
        ///   <para>
        ///   On Windows, this method normalized the paths to avoid running into
        ///   the 260 character limit of a path and converts forward slashes in 
        ///   both <paramref name="path1" /> and <paramref name="path2" /> to 
        ///   the platform&#039;s directory separator character.
        ///   </para>
        /// 
        ///  Courtesy of NAnt project.
        /// </remarks>
        /// ---------------------------------------------------------------
        public static string CombinePaths(string path1, string path2)
        {


            if (path1 == null)
            {
                throw new ArgumentNullException("path1");
            }
            if (path2 == null)
            {
                throw new ArgumentNullException("path2");
            }

            if (Path.IsPathRooted(path2))
            {
                return path2;
            }

            char separatorChar = Path.DirectorySeparatorChar;
            char[] splitChars = new char[] { &#039;/&#039;, separatorChar };

            // Now we split the Path by the Path Separator
            String[] path2Parts = path2.Split(splitChars);

            ArrayList arList = new ArrayList();

            // for each Item in the path that differs from ".." we just add it 
            // to the ArrayList, but skip empty parts
            for (int iCount = 0; iCount < path2Parts.Length; iCount++)
            {
                string currentPart = path2Parts&#91;iCount&#93;;

                // skip empty parts or single dot parts
                if (currentPart.Length == 0 || currentPart == ".")
                {
                    continue;
                }

                // if we get a ".." Try to remove the last item added (as if 
                // going up in the Directory Structure)
                if (currentPart == "..")
                {
                    if (arList.Count > 0 &amp;&amp; ((string)arList[arList.Count - 1] != ".."))
                    {
                        arList.RemoveAt(arList.Count - 1);
                    }
                    else
                    {
                        arList.Add(currentPart);
                    }
                }
                else
                {
                    arList.Add(currentPart);
                }
            }

            bool trailingSeparator = (path1.Length > 0 &amp;&amp; path1.IndexOfAny(splitChars, path1.Length - 1) != -1);

            // if the first path ends in directory seperator character, then 
            // we need to omit that trailing seperator when we split the path
            string[] path1Parts;
            if (trailingSeparator)
            {
                path1Parts = path1.Substring(0, path1.Length - 1).Split(splitChars);
            }
            else
            {
                path1Parts = path1.Split(splitChars);
            }

            int counter = path1Parts.Length;

            // if the second path starts with parts to move up the directory tree, 
            // then remove corresponding parts in the first path
            //
            // eg. path1 = d:whateveryouwant	odo 
            //     path2 = ../../test
            //     
            //     ->
            //
            //     path1 = d:whateveryouwant
            //     path2 = test
            ArrayList arList2 = (ArrayList)arList.Clone();
            for (int i = 0; i < arList2.Count; i++)
            {
                // never discard first part of path1
                if ((string)arList2&#91;i&#93; != ".." || counter < 2)
                {
                    break;
                }

                // skip part of current directory
                counter--;

                arList.RemoveAt(0);
            }

            string separatorString = separatorChar.ToString(CultureInfo.InvariantCulture);

            // if path1 only has one remaining part, and the original path had
            // a trailing separator character or the remaining path had multiple
            // parts (which were discarded by a relative path in path2), then
            // add separator to remaining part
            if (counter == 1 &amp;&amp; (trailingSeparator || path1Parts.Length > 1))
            {
                path1Parts[0] += separatorString;
            }

            string combinedPath = Path.Combine(string.Join(separatorString, path1Parts,
                0, counter), string.Join(separatorString, (String[])arList.ToArray(typeof(String))));

            // if path2 ends in directory separator character, then make sure
            // combined path has trailing directory separator character
            if (path2.EndsWith("/") || path2.EndsWith(separatorString))
            {
                combinedPath += Path.DirectorySeparatorChar;
            }

            return combinedPath;
        }
    }
}

   
     


This entry was posted in File Stream. Bookmark the permalink.