C# で 2ギガを超えるファイルを StreamWriter で書き込むと例外が投げられる。

以下のようなコードを実行すると、ファイルサイズが 2GB を超えた時点で例外が投げられる。

Encoding enc = Encoding.GetEncoding(932);
string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\r\n";

string filepath = Path.GetTempFileName();
long count = 0;
try
{
    // ファイルを新規作成
    using (StreamWriter writer = new StreamWriter(filepath, false, enc))
    {
        while (true)
        {
            writer.Write(str);

            if (count++ > 100000)
            {
                count = 0;
                Console.Write("{0:#,0} KB\r", writer.BaseStream.Position / 1024);
            }
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine();
    Console.WriteLine(ex);
}
finally
{
    try
    {
        File.Delete(filepath);
    }
    catch { }
}

例外は、こんな感じ。

System.ArgumentException: GetBytes() または GetByteCount() を呼び出す前に、Convert() 操作を完了するか、または Encoder.Reset() を呼び出さなければなりません。エンコーダ '日本語 (シフト JIS)' フォールバック 'System.Text.InternalEncoderBestFitFallback'。
 場所 System.Text.DBCSCodePageEncoding.GetBytes(Char* chars, Int32 charCount, Byte* bytes, Int32 byteCount, EncoderNLS encoder)
 場所 System.Text.EncoderNLS.GetBytes(Char* chars, Int32 charCount, Byte* bytes, Int32 byteCount, Boolean flush)
 場所 System.Text.EncoderNLS.GetBytes(Char[] chars, Int32 charIndex, Int32 charCount, Byte[] bytes, Int32 byteIndex, Boolean flush)
 場所 System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
 場所 System.IO.StreamWriter.Dispose(Boolean disposing)
 場所 System.IO.TextWriter.Dispose()

この2ギガ問題を解決するには・・・ファイルサイズが2ギガを越える前に、一度ストリームを閉じて、その後、ファイルに追記する形でストリームを開きなおすと良い。
具体的なコードは以下の通り。

Encoding enc = Encoding.GetEncoding(932);
string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\r\n";

string filepath = Path.GetTempFileName();
long count = 0;

long cycle = 1 * 1024 * 1024 * 1024; // 1G
long streamsize = cycle;

// ファイルを新規作成
StreamWriter writer = new StreamWriter(filepath, false, enc);
try
{
    while (true)
    {
        writer.Write(str);

        if (count++ > 100000)
        {
            count = 0;
            Console.Write("{0:#,0} KB\r", writer.BaseStream.Position / 1024);
        }

        if (writer.BaseStream.Position > streamsize)
        {
            streamsize += cycle;
            writer.Flush();
            writer.Close();
            // ファイルに追記する
            writer = new StreamWriter(filepath, true, enc);
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine();
    Console.WriteLine(ex);
}
finally
{
    try
    {
        writer.Close();
    }
    catch { }
    try
    {
        File.Delete(filepath);
    }
    catch { }
}

こんな感じ。
ここでは、1ギガごとに、ストリームを作り直すようにした。
ちなみに、using を使うと、変数が読み取り専用になり StreamWriter を作り直せないので外した。
そのため、 finally で閉じ忘れないようにした。