.NET で作成できる最長の文字列は? クラスのドキュメントは、String
私が見る限り、この質問について沈黙しているため、信頼できる回答には内部に関するある程度の知識が必要になる場合があります。64 ビット システムで最大値は変わりますか?
[これは実用よりも好奇心で求められます - 巨大な文字列を使用するコードを作成するつもりはありません!]
理論上の制限は2,147,483,647である可能性がありますが、実際の制限はそれに近いものではありません。.NETプログラムの単一のオブジェクトは2GBを超えることはできず、文字列型はUTF-16(各文字に2バイト)を使用するため、最善の方法は1,073,741,823ですが、それを割り当てることができない可能性があります。 32ビットマシンで。
私の非常に科学的で正確な実験に基づいて、私のマシンでは 1,000,000,000 文字よりかなり前にトップに達します。(より正確に特定するために、以下のコードを実行しています)。
更新:
数時間後、あきらめました。最終結果: 100,000,000 文字よりもはるかに大きくなる可能性があり、すぐSystem.OutOfMemoryException
に 1,000,000,000 文字になります。
using System;
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
int i = 100000000;
try
{
for (i = i; i <= int.MaxValue; i += 5000)
{
string value = new string('x', i);
//WL(i);
}
}
catch (Exception exc)
{
WL(i);
WL(exc);
}
WL(i);
RL();
}
#region Helper methods
private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
#endregion
}
のLength
プロパティは でSystem.String
あるため、最大長は 2,147,483,647 文字 (最大サイズ)Int32
になると思います。Int32
それ以上許可すると、失敗するため、長さを確認できませんでした。
このトピックに遅れて来た人にとっては、hitscan の「あなたはおそらくそれをすべきではない」ということで、誰かが何をすべきかを尋ねる可能性があることがわかりました…</p>
多くの場合、 StringBuilderクラスは簡単に置き換えることができます。データがファイルから取得されている場合は、特にストリームベースのクラスの 1 つを検討してください。
問題s += "stuff"
は、データを保持するために完全に新しい領域を割り当ててから、古いデータと新しいものをすべてそこにコピーする必要があることです-各ループ反復。したがって、5 バイトを 1,000,000 に追加すると、s += "stuff"
非常にコストがかかります。最後に 5 バイトを書き込んでプログラムを続行したい場合は、拡張の余地があるクラスを選択する必要があります。
StringBuilder sb = new StringBuilder(5000);
for (; ; )
{
sb.Append("stuff");
}
StringBuilder
限界に達すると倍増して自動成長します。したがって、最初に 1 回、5,000 バイトで 1 回、10,000 バイトで 1 回、20,000 バイトで 1 回、成長の痛みが見られます。文字列を追加すると、ループの反復ごとに問題が発生します。
私のマシンの文字列の最大長は1,073,741,791です。
ご覧のとおり、一般に信じられているように、文字列は整数によって制限されません。
Microsoft CLR (共通言語ランタイム) によって 2 GB の制限が課されているため、メモリの制限はさておき、文字列は 2 30 ( 1,073,741,824 ) 文字を超えることはできません。私のコンピューターが許可するよりも33多い。
では、ぜひお試しいただきたいことがあります。
Visual Studio で新しい C# コンソール アプリを作成し、main メソッドをコピーしてここに貼り付けます。
static void Main(string[] args)
{
Console.WriteLine("String test, by Nicholas John Joseph Taylor");
Console.WriteLine("\nTheoretically, C# should support a string of int.MaxValue, but we run out of memory before then.");
Console.WriteLine("\nThis is a quickish test to narrow down results to find the max supported length of a string.");
Console.WriteLine("\nThe test starts ...now:\n");
int Length = 0;
string s = "";
int Increment = 1000000000; // We know that s string with the length of 1000000000 causes an out of memory exception.
LoopPoint:
// Make a string appendage the length of the value of Increment
StringBuilder StringAppendage = new StringBuilder();
for (int CharacterPosition = 0; CharacterPosition < Increment; CharacterPosition++)
{
StringAppendage.Append("0");
}
// Repeatedly append string appendage until an out of memory exception is thrown.
try
{
if (Increment > 0)
while (Length < int.MaxValue)
{
Length += Increment;
s += StringAppendage.ToString(); // Append string appendage the length of the value of Increment
Console.WriteLine("s.Length = " + s.Length + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));
}
}
catch (OutOfMemoryException ex) // Note: Any other exception will crash the program.
{
Console.WriteLine("\n" + ex.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");
Length -= Increment;
Increment /= 10;
Console.WriteLine("After decimation, the value of Increment is " + Increment + ".");
}
catch (Exception ex2)
{
Console.WriteLine("\n" + ex2.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");
Console.WriteLine("Press a key to continue...");
Console.ReadKey();
}
if (Increment > 0)
{
goto LoopPoint;
}
Console.WriteLine("Test complete.");
Console.WriteLine("\nThe max length of a string is " + s.Length + ".");
Console.WriteLine("\nPress any key to continue.");
Console.ReadKey();
}
私の結果は次のとおりです。
ニコラス・ジョン・ジョセフ・テイラーによるストリング・テスト
理論的には、C# は int.MaxValue の文字列をサポートするはずですが、その前にメモリが不足します。
これは、サポートされている文字列の最大長を見つけるために結果を絞り込む簡単なテストです。
テストが開始されます ...今:
s.Length = 1000000000 at 08/05/2019 12:06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後の Increment の値は 100000000 です。
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後の Increment の値は 10000000 です。 :06 s.Length = 1040000000 at 08/05/2019 12:06 s.Length = 1050000000 at 08/05/2019 12:06 s.Length = 1060000000 at 08/05/2019 12:06 s00Length = 107000 2019/08/05 12:06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後の Increment の値は 1000000 です。 :06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後の Increment の値は 100000 です。 :06 s.Length = 1073400000 (2019 年 8 月 5 日 12:06) s.Length = 1073500000 (2019 年 8 月 5 日 12:06) 2019/08/05 12:06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後の Increment の値は 10000 です。 :06 s.Length = 1073740000 at 08/05/2019 12:06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーション後、Increment の値は 1000 です。s.Length = 1073741000 at 08/05/2019 12:06
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019 年 8 月 5 日 12:06。デシメーションの後、Increment の値は 100 です。 :07 s.Length = 1073741400 (2019 年 8 月 5 日 12:07) s.Length = 1073741500 (2019 年 8 月 5 日 12:07) 2019/08/05 12:07
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019/08/05 12:07。デシメーション後の Increment の値は 10 です。 :07 秒の長さ = 1073741740 (2019 年 8 月 5 日 12:07) 秒の長さ = 1073741750 (2019 年 8 月 5 日 12:07) 秒の長さ = 1073741760 (2019 年 8 月 5 日 12:07) 08/05/2019 12:07 s.Length = 1073741780 at 08/05/2019 12:07 s.Length = 1073741790 at 08/05/2019 12:07
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019/08/05 12:07。デシメーション後、Increment の値は 1 です。s.Length = 1073741791 at 08/05/2019 12:07
タイプ 'System.OutOfMemoryException' の例外がスローされました。2019/08/05 12:07。デシメーション後、Increment の値は 0 です。テストは完了しました。
文字列の最大長は 1073741791 です。
何かキーを押すと続行します。
私のマシンの文字列の最大長は 1073741791 です。
以下のコメントとして結果を投稿していただければ幸いです。
人々が同じ結果を得るか、異なる結果を得るかを知ることは興味深いでしょう.
String.Length
は整数 ( のエイリアス) であるため、Int32
そのサイズはInt32.MaxValue
Unicode 文字に制限されます。;-)
200メガ...その時点で、アプリは仮想的に停止し、約1ギガのワーキングセットメモリがあり、o/sは再起動が必要なように動作し始めます.
static void Main(string[] args)
{
string s = "hello world";
for(;;)
{
s = s + s.Substring(0, s.Length/10);
Console.WriteLine(s.Length);
}
}
12
13
14
15
16
17
18
...
158905664
174796230
192275853
211503438