在C#中使Streamreader全局化

时间:2015-12-19 21:36:02

标签: c# global-variables streamreader

我想知道是否可以将StreamReader对象公开,以便其他函数可以访问该对象。问题是当我在main()之外声明Streamreader对象时我能够做到这一点,但是因为StreamReader正在将文件作为命令行参数之一进行读取,所以我必须在Main()中声明它。最初,当我创建它时,他们希望文件名可以在appconfig中配置,但他们将其更改为使用脚本自动执行,并将其作为命令行arg传递,现在我无法使其工作因为其他功能无法访问'文件'宾语。如果我通过' file'作为一个参数,每次我回到主页时都不会从头开始读取文件?请帮忙!谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using System.Configuration;

namespace Elan_File_Cleanser
{
    class Program
    {
        //public static StreamReader file = new StreamReader(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),@"Folder\\*.txt"));

        public static string readPath = ConfigurationManager.AppSettings["readPath"];


        private const char EmvRecordHeader = '2';
        private const string EmvEndMarker = "#END#";
        private const char FileHeaderIdentifier = 'F';
        private const char BatchHeaderIdentifier = 'B';
        private const char DetailedRecord0Identifier = '0';
        private const char DetailedRecord1Identifier = '1';
        private const char DetailedRecord2Identifier = '2';
        private const char CleansedCharacter = 'X';
        private static readonly Dictionary<int, int> DetailedRecord0CleansedPositions = new Dictionary<int, int>()
            { //{start position, span}
                {8, 12},
                {44, 2}, 
                {47, 2}, 
                {105, 97}
            };
        private static readonly Dictionary<int, int> DetailedRecord1CleansedPositions = new Dictionary<int, int>()
            { //{start position, span}
                {1, 12}
            };

        static void Main(string[] args)
        {

            string inputPath = args[0];
            int cltId = Convert.ToInt32(args[1]);
            string destination = args[2];
            string line = "";

            StreamReader file = new StreamReader(inputPath);

            string fileName = Path.GetFileNameWithoutExtension(file.ToString());

            using (StreamWriter newFile = new StreamWriter(destination+ "\\" + fileName +"_" + cltId + "_"+ DateTime.Now + ".txt"))
            {


                do
                {
                    line = GetLineWithEmbeddedLineFeeds();

                    if (!string.IsNullOrEmpty(line))
                    {
                        switch (line[0])
                        {
                            case FileHeaderIdentifier:
                            case BatchHeaderIdentifier:
                                newFile.WriteLine(line);
                                break;
                            case DetailedRecord0Identifier:
                                newFile.WriteLine(CleanseDetailedRecord0And1(line, DetailedRecord0CleansedPositions));
                                break;
                            case DetailedRecord1Identifier:
                                newFile.WriteLine(CleanseDetailedRecord0And1(line, DetailedRecord1CleansedPositions));
                                break;
                            case DetailedRecord2Identifier:
                                newFile.WriteLine(CleanseDetailedRecord2(line));
                                break;
                            default:
                                newFile.WriteLine();
                                break;
                        }


                    }
                    else
                    {
                        newFile.WriteLine();
                    }
                } while (!file.EndOfStream);
                file.Close();
            }
        }


        private static string GetLineWithEmbeddedLineFeeds()
        {
            int i = file.Read();
            // When there is nothing more to read we MUST return null in order to signal the caller that we have reached EOF.
            if (i == -1)
            {
                return null;
            }

            var line = new StringBuilder(5000);
            bool endOfLine = false;

            while (i >= 0 && !endOfLine)
            {
                var ch = (char)i;

                if (ch == '\r')
                {
                    int n = file.Peek();
                    var nextChar = (char)n;
                    if (nextChar == '\n')
                    {
                        string lineStr = line.ToString();
                        if ((lineStr.Length == 0) ||
                            (lineStr.Length > 0 && lineStr[0] != EmvRecordHeader) ||
                            (lineStr.Length > EmvEndMarker.Length && lineStr[0] == EmvRecordHeader && (lineStr.Substring(lineStr.Length - EmvEndMarker.Length) == EmvEndMarker)))
                        {
                            endOfLine = true;
                        }
                    }
                    else
                    {
                        line.Append(ch);
                    }
                }
                else
                {
                    line.Append(ch);
                }
                i = file.Read();
            }

            return line.ToString();
        }


        //**************************************************************
        private static string CleanseDetailedRecord0And1 (string line, Dictionary<int,int> position)
        {
             foreach (int startIndex in position.Keys)
             {

                 int span = position[startIndex];
                 line = line.Remove(startIndex, span);
                 line = line.Insert(startIndex, new string(CleansedCharacter, span));
             }
             return line;
        }


        //**************************************************************
        private static string CleanseDetailedRecord2 (string line)
        {
            int span = line.Length - 25;    
                        line = line.Remove(25, span);
                        line = line.Insert(25, new string(CleansedCharacter, span));
                         return line;

        }
    }
}

2 个答案:

答案 0 :(得分:1)

你可以把它变成全球性的吗?是不是好主意。

全局变量的问题在于谁将创建它以及谁将确保它被清理/关闭。

您应该尝试在伪代码中执行类似的操作

void main(string[] args) {
   var inputFileName= DetermineInputFileName(args);
    var outputFileName= DetermineOutputFileName(args);
   ReadAndWriteFile(inputFileName, outputFileName)
}

void ReadAndWriteFile(string inputFileName, string outputFileName) {
  //only use the streamreader here
   using(var inputFile = new StringReader) {
      using (var outputFile = new StringWriter) {
         do {
             string line = String.Empty;
             do {
              var input = inputFile.ReadLine();
              line += input;
             while (ContinueReadingAfterThisInput(input))

             var processedLine = Process(line);

             outputFile.WriteLine(processedLine);
         }

      }

   }

}

现在,您可以从线的实际处理中分离读/写循环(读取一行,执行某些操作,写一行)。其余代码不需要了解文件/流程读取器等

更新以回答问题的第二部分,如果您将流作为参数传递给函数,它将只跟踪它的位置。它不会重置/重新开始。

答案 1 :(得分:0)

您是否考虑过使用静态类来处理读/写文件?