如何在c#中最好地管理一个循环中的多个流

本文关键字:一个 循环 管理 | 更新日期: 2023-09-27 18:02:36

我正在按类型顺序遍历电影列表,并且我正在尝试创建和写入文件,因为我这样做。我想创建一个文件,写一堆,然后当我移动到下一个类型时关闭它,并创建一个新文件。

现在我得到"使用未分配的局部变量'GenStream'",当我试图关闭流。但是,如果我将其注释掉,并且不关闭流,则在ELSE语句中会得到相同的错误。我不清楚为什么我得到这些错误,并将感谢帮助解决它们。我注意到我在下面的代码中得到错误的地方。

/// <summary>
/// Creates a file for each Genre, and writes movie info to each for the cooresponding movies
/// </summary>
/// <param name="cPath">Path to create HTML files in</param>
/// <param name="mList">List of Movies to generate Genre and Movie info from</param>
public static void WriteGenreHTML(string cPath, List<Movie> mList)
{
    int lineID = 0;
    string tmpGen = null;
    string strHeader, strMovie, strGenre, tmpGenre = null;
    StreamWriter genStream;
    // Gets a list of unique Genres from the MovieList
    var distinctGenres = from m in mList
                         from genre in m.Genres
                         group genre by genre into genres
                         select genres.First();
    // Gets a list of Movies with the associated Genres
    var moviesWithGenre = from g in distinctGenres
                          from m in mList
                          where m.Genres.Contains(g)
                          orderby g, m.Title
                          select new { Genre = g, Movie = m };
    // Traverses list of movies creating new HTML Genre files, and writing movie info to the HTML genre files
    foreach (var m in moviesWithGenre)
    {
        // Creates new HTML file if new Genre is detected
        if (m.Genre != tmpGen)
        {
            tmpGen = m.Genre;
            // Closes previously open Stream
            genStream.Close(); // ERROR: "Use of unassigned local variable 'genStream'
            // initiates streamwriter for catalog output file
            FileStream fs = new FileStream(cPath + Path.DirectorySeparatorChar + m.Genre, FileMode.Create);
            genStream = new StreamWriter(fs);
            // Generates header info for new file, and new Genre
            strHeader = "<style type='"text/css'">'r'n" + "<!--'r'n" + "tr#odd {'r'n" + "   background-color:#e2e2e2;'r'n" + "  vertical-align:top;'r'n" + "}'r'n" + "'r'n" + "tr#even {'r'n" + "   vertical-align:top;'r'n" + "}'r'n" + "div#title {'r'n" + "  font-size:16px;'r'n" + "    font-weight:bold;'r'n" + "}'r'n" + "'r'n" + "div#mpaa {'r'n" + "    font-size:10px;'r'n" + "}'r'n" + "'r'n" + "div#genre {'r'n" + " font-size:12px;'r'n" + "    font-style:italic;'r'n" + "}'r'n" + "'r'n" + "div#plot {'r'n" + "   height: 63px;'r'n" + "  font-size:12px;'r'n" + "    overflow:hidden;'r'n" + "}'r'n" + "'r'n" + "div#genre_heading {'r'n" + "    height: 50px;'r'n" + "  font-size: 24px;'r'n" + "   font-weight: bold;'r'n" + " text-align: center;'r'n" + "    text-decoration: underline;'r'n" + "}'r'n" + "-->'r'n" + "</style>'r'n" + "'r'n" + "<html>'r'n" + " <body>'r'n" + "     <table>'r'n";
            strHeader += "          <tr>'r'n" + "               <td colspan=2>'r'n" + "                 <div id='"genre_heading'">" + m.Genre + "</div>'r'n" + "                </td>'r'n" + "          </tr>'r'n" + "'r'n";
            // Writes header HTML to stream
            genStream.WriteLine(strHeader);
            Console.WriteLine();
            Console.WriteLine("Now Processing " + m.Genre);
        }
        // Otherwise creates and writes HTML code for the Movie
        else
        {
            // Creates string of links to the Genre HTML pages
            foreach (string genre in m.Movie.Genres)
                tmpGenre += ", <a href='"" + genre + ".html'" target='"_blank'">" + genre + "</a>";
            strGenre = tmpGenre != null ? tmpGenre.Substring(2) : null;
            // Generates the HTML for the Movie
            strMovie = lineID == 0 ? "          <tr id='"odd'" style='"page-break-inside:avoid'">'r'n" : "          <tr id='"even'" style='"page-break-inside:avoid'">'r'n";
            strMovie += "               <td>'r'n" + "                   <img src='".''images''" + m.Movie.ImageFile + "'" width='"75'" height='"110'">'r'n" + "             </td>'r'n" + "              <td>'r'n" + "                   <div id='"title'">" + m.Movie.Title + "</div>'r'n" + "                  <div id='"mpaa'">" + m.Movie.Certification + " " + m.Movie.MPAA + "</div>'r'n" + "                  <div id='"genre'">" + strGenre + "</div>'r'n" + "                   <div id='"plot'">" + m.Movie.Plot + "</div>'r'n" + "                </td>'r'n" + "          </tr>'r'n";
            // Writes the HTML to the stream
            genStream.WriteLine(strMovie); // ERROR: "Use of unassigned local variable 'genStream'
            lineID = lineID == 0 ? 1 : 0;
        }
    }
    string closingHTML = "      </table>'r'n" + "   </body>'r'n" + "</html>";
    genStream.WriteLine(closingHTML);
    genStream.Close();
}

如何在c#中最好地管理一个循环中的多个流

您可以使用下面的代码来验证流是否已经初始化

如果流已初始化,则可以关闭它

if (genStream == null )
{
genStream.Close()
}

希望这对你有用…

你得到"使用未分配的局部变量'GenStream'"错误的原因是因为你已经声明了它,当你在if块中调用GenStream . close()时,它没有被分配任何东西-它只是一个声明(将其视为占位符)。

当你注释掉genStream.Close()时,你会在else块中再次得到错误,因为(从else块的作用域的角度来看)它再次没有被分配任何东西。

下面是我在评论你之前的文章时建议的一个例子:

foreach (var g in DistinctGenres)
{
    FileStream fs = new FileStream(cPath + Path.DirectorySeparatorChar + g.Genre, FileMode.Create);
    StreamWriter genStream = new StreamWriter(fs);
    // Write your header here
    foreach (var m in Genres)
    {
        // Generates the HTML for the Movie
        // Writes the HTML to the stream
        genStream.WriteLine(strMovie);
        lineID = lineID == 0 ? 1 : 0;
    }
    string closingHTML = "      </table>'r'n" + "   </body>'r'n" + "</html>";
    genStream.WriteLine(closingHTML);
    genStream.Close();
}

这消除了if检查的需要,并且通常简化了你想要完成的任务。

你可能需要调整你的两个查询,或者保留你的第一个查询,并根据你正在构建的网页的当前类型做第二个查询。

另一个想法-将第二个查询移动到第一个foreach循环中,将当前类型分配给一个变量,并像这样调整第二个查询:

var moviesWithGenre = from g in distinctGenres
                      from m in mList
                      where m.Genres.Contains(currentGenre) // currentGenre is assigned a value in the first (outer) foreach loop
                      orderby g, m.Title
                      select new { Genre = g, Movie = m };

也许你也可以添加,除了这里的答案,是使用"using"关键字,因为它会注入到最后的IL try/finally符号,这将确保你的流是关闭的,即使在异常引发的情况下。简而言之,伪代码可以是这样的:

using(StreamWriter genStream = new StreamWriter(…)){

   //use stream here
   genStream.Close();

}//退出"using"时将自动调用genStream的dispose。

希望对你有帮助。

问候。