简体   繁体   中英

Reading, Manipulating, and Writing text files C#

I need to convert any flat delimited file into a pipe delimited format. I wrote this console app as a POC but the second file it tries to write will include the all of the text from the first file. Any suggestions?

        string sourceDir = @"c:\temp\";
        string targetDir = @"c:\dest\";

        List<string> listLines = new List<string>();

        string[] files = Directory.GetFiles(sourceDir);

        foreach(string file in files)
        {
            using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
            {
                do
                {
                    listLines.Add(sr.ReadLine());
                } while (!sr.EndOfStream);

                for (int i = 0; i < listLines.Count; i++)
                {
                    listLines[i] = listLines[i].Replace(',', '|');
                    listLines[i] = listLines[i].Replace('\t', '|');                        
                }                                         
            }

            using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
            {
                foreach (string line in listLines)
                {
                    sw.WriteLine(line);
                }           
            }
        }

You're adding lines to listLines and never clearing the list after the foreach iteration.

by @Jonathan Carroll

Beside that, you can improve your code to this:

string sourceDir = @"c:\temp\";
string targetDir = @"c:\dest\";

List<string> listLines = new List<string>();

string[] files = Directory.GetFiles(sourceDir);

foreach (string file in files)
{
    using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
    using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
    {
        do
        {
            var line = sr.ReadLine();

            line = line.Replace(',', '|').Replace('\t', '|');

            sw.WriteLine(line);

        } while (!sr.EndOfStream);
    }
}

You need to either move the instantiation of listLines into the foreach, or re-initialize the list at the end of the loop.

    string sourceDir = @"c:\temp\";
    string targetDir = @"c:\dest\";

    string[] files = Directory.GetFiles(sourceDir);

    foreach(string file in files)
    {
        List<string> listLines = new List<string>();
        using (StreamReader sr = new StreamReader(sourceDir + Path.GetFileName(file)))
        {
            do
            {
                listLines.Add(sr.ReadLine());
            } while (!sr.EndOfStream);

            for (int i = 0; i < listLines.Count; i++)
            {
                listLines[i] = listLines[i].Replace(',', '|');
                listLines[i] = listLines[i].Replace('\t', '|');                        
            }                                         
        }

        using (StreamWriter sw = new StreamWriter(targetDir + Path.GetFileName(file)))
        {
            foreach (string line in listLines)
            {
                sw.WriteLine(line);
            }           
        }
    }

I'd argue that the other answers are considerably clearer, but just thought I'd throw in a short alternative solution using LINQ and Regex:

foreach (var file in Directory.GetFiles(sourceDir).Select(x => Path.GetFileName(x)))
    File.WriteAllText(targetDir + file, new Regex("[,\t]").Replace(File.ReadAllText(sourceDir + file), "|"));

The LINQ select query is used to transform the full paths into file names - this collection of file names is then iterated over. Regex is used to match all ',' and '\\t' characters that are read from the source file and replace them with the '|' character. This resulting string is then written to the target file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM