开发者

How to best manage multiple streams in a loop in C#

I am traversing a list of Movies in order of Genre, and I'm trying to create and write to files as I do it. I want to create a file, write a bunch to it, then close it when I move to the next genre, and create a new file.

Right now I am getting "Use of unassigned local variable 'GenStream'" when I try to close the Stream. However, if I comment it out, and don't close the stream, I get the same error in my ELSE statement. I'm not clear why I'm getting those errors, and would appreciate help resolving them. I noted where I am getting errors in the code below.

/// <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.开发者_C百科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();
}


you can use the below code to validate the stream is already initialized or not

if the stream is initialized then you can close it

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

hope this will work for you...


The reason you're getting the "Use of unassigned local variable 'GenStream'" error is because you've declared it, when you call genStream.Close() in your if block it hasn't been assigned anything - it's just a declaration (think of it as a placeholder).

When you comment out the genStream.Close(), you get the error again in your else block because (from the scope point of view of the else block) it again hasn't been assigned anything.

Here's an example of what I was suggesting in my last comment on your previous post:

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();
}

This elminates the need for an if check and generally streamlines what you're trying to accomplish, IMO.

You'll probably have to adjust your two queries, or keep your first query and do a second query based on the current genre you're building the web page for.

An additional thought - move the second query to inside the first foreach loop, assign the current genre to a variable, and tweak your second query like this:

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 };


May be you can add also, in addition to answers here, is using "using" keyword, cause it will inject into final IL try/finally notation which will ensure that you stream is closed even in case of exception raised. In short a pseudocode can be something like this:

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

   //use stream here

   genStream.Close();

} // dispose of genStream will be called automatically on exit from "using".

Hope this helps.

Regards.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜