.NET文字列の最大長はどれくらいですか?


239

.NETで作成できる最も長い文字列は何ですか?Stringクラスのドキュメントは、私が見る限りこの質問については触れていません。そのため、信頼できる回答には内部の知識が必要になる場合があります。64ビットシステムで最大の変更はありますか?

[これは実際の使用よりも好奇心を求められます-私は巨大な文字列を使用するコードを作成するつもりはありません!]

回答:


345

理論上の制限は2,147,483,647ですが、実際の制限はそれに近いものではありません。.NETプログラムの単一のオブジェクトは2GBを超えることはなく、文字列タイプはUTF-16(各文字に2バイト)を使用するため、最善の方法は1,073,741,823ですが、これを割り当てることができる可能性はほとんどありません32ビットマシン上。

これは、「質問する必要がある場合は、おそらく何か間違っている」という状況の1つです。


8
これが正解です。文字列の長さを使い果たすのに十分な割り当てができる前に、メモリが不足する可能性が高くなります。フレッシュブートでは、ここで説明したように、2 GB(1M文字)の割り当てをプルできる場合がありますが、それだけです。
スティーブンデケン2008

4
「1つのオブジェクトで2Gbを超えることはできない」というアサーションが正確であると仮定すると、これは理論上の制限であり、実際の制限でもあります。文字列の長さの制限は、オブジェクトの合計サイズであり、長さフィールドの容量ではありません。
マッケンジー

12
正確な値に興味がある場合、64ビットマシンでは1,073,741,791(1024・1024・1024-33)文字です。の正確な最大サイズに関する私の質問byte[]も参照してください。
2013年

4
短いが詳細な説明を含む回答に夢中です。
Mikayil Abdullayev

3
64ビットマシンでは、.NET 4.5以降のオブジェクトを2GBより大きくできるオプションがあります。ここをチェック
Anderson Matos

72

私の非常に科学的で正確な実験に基づいて、それは私のマシンで10億文字よりもはるかに上です。(より正確なピンポイントを得るために、以下のコードをまだ実行しています)。

更新: 数時間後、私はあきらめました。最終結果: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
}

35
ここではバイナリサーチを適用する、おそらくあなたはたくさん速く、この答えを見つけるのに役立つだろう...
マリオ

49

ためLengthのプロパティがSystem.StringありInt32、私はその最大長は2,147,483,647文字(最大であろうと推測Int32サイズ)。それより長くなると、失敗するため、長さを確認できません。


2
@ m.edmondson:私は実際には確信していません。インスタンスの配列LongLengthもがあり、ストリームはlong長さとして使用します。これは有効な回答ですが、これを測定する正確な方法です。
Willem Van Onsem、2015年

1
ただし、この記事で述べているように、最初の2ビットはASCII /非ASCII表示に使用されるため、2 ^ 30 = 1 073 741 824
斎藤

28

このトピックに遅れて来る人のために、hitscanの「おそらくあなたはそれをしてはいけない」が誰かに彼らに何をすべきかを尋ねさせるかもしれないことがわかりました…

StringBuilderクラスは、多くの場合、簡単に交換です。データがファイルからのものである場合は、特にストリームベースのクラスの 1つを検討してください。

の問題s += "stuff"は、データを保持するために完全に新しい領域を割り当ててから、古いデータとすべてに新しいデータをコピーする必要があることです。したがって、1バイトに5バイトを追加するs += "stuff"と、非常にコストがかかります。最後に5バイトを書き込むだけでプログラムを続行したい場合は、成長の余地があるクラスを選択する必要があります。

StringBuilder sb = new StringBuilder(5000);
for (; ; )
    {
        sb.Append("stuff");
    }

StringBuilder意志の倍増により、自動拡張、それの制限がヒットしたとき。したがって、最初は5,000バイトで、1度は10,000で、もう1度は20,000で、成長の痛みを感じるでしょう。文字列を追加すると、ループを繰り返すたびに問題が発生します。


4
StringBuilderで初期サイズを設定できることにも注意する価値があります。事前に10,000,000エントリを使用することがわかっている場合に役立ちます。これにより、クランチの一部を無視できます。
カイルバラン14

3
+1質問をよく読み、優れたデザインに答えるため。比較すると、「これは、文字列が大きくなる前の大きさです」とは対照的に、「本当に大量のテキストを保存する必要がある場合は、これを使用してください...」
StevoInco

8

私のマシンの文字列の最大長は1,073,741,791です。

ご存知のように、文字列は、一般的に信じられているように整数によって制限されていません。

メモリの制限は別として、Microsoft CLR(共通言語ランタイム)によって2GBの制限が課されているため、文字は2 301,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 = 08/05/2019 12:06で1000000000

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後のIncrementの値は100000000です。

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後の増分の値は10000000です。s.Length= 1010000000 at 08/05/2019 12:06 s.Length = 1020000000 at 08/05/2019 12:06 s.Length = 1030000000 at 08/05/2019 12 :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 s.Length = 1070000000 at 08/05/2019 12:06

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後、インクリメントの値は1000000です。s.Length= 1071000000 at 08/05/2019 12:06 s.Length = 1072000000 at 08/05/2019 12:06 s.Length = 1073000000 at 08/05/2019 12 :06

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後、インクリメントの値は100000です。s.Length= 1073100000 at 08/05/2019 12:06 s.Length = 1073200000 at 08/05/2019 12:06 s.Length = 1073300000 at 08/05/2019 12 :06 s.Length = 1073400000 at 08/05/2019 12:06 s.Length = 1073500000 at 08/05/2019 12:06 s.Length = 1073600000 at 08/05/2019 12:06 s.Length = 1073700000 at 08/05/2019 12:06

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後、増分の値は10000です。s.Length= 1073710000 at 08/05/2019 12:06 s.Length = 1073720000 at 08/05/2019 12:06 s.Length = 1073730000 at 08/05/2019 12 :06 s.Length = 1073740000 08/05/2019 12:06

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーションの後、インクリメントの値は1000です。s.Length= 1073741000 at 08/05/2019 12:06

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:06に。デシメーション後、インクリメントの値は100です。s.Length= 1073741100 at 08/05/2019 12:06 s.Length = 1073741200 at 08/05/2019 12:06 s.Length = 1073741300 at 08/05/2019 12 :07 s.Length = 1073741400 at 08/05/2019 12:07 s.Length = 1073741500 at 08/05/2019 12:07 s.Length = 1073741600 at 08/05/2019 12:07 s.Length = 1073741700 at 08/05/2019 12:07

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:07。デシメーション後、インクリメントの値は10です。s.Length= 1073741710 at 08/05/2019 12:07 s.Length = 1073741720 at 08/05/2019 12:07 s.Length = 1073741730 at 08/05/2019 12 :07 s.Length = 1073741740 08/05/2019 12:07 s.Length = 1073741750 at 08/05/2019 12:07 s.Length = 1073741760 at 08/05/2019 12:07 s.Length = 1073741770 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」の例外がスローされました。08/05/2019 12:07。デシメーション後、インクリメントの値は1です。s.Length= 1073741791 at 08/05/2019 12:07

タイプ「System.OutOfMemoryException」の例外がスローされました。08/05/2019 12:07。デシメーションの後、インクリメントの値は0です。テストが完了しました。

文字列の最大長は1073741791です。

何かキーを押すと続行します。

私のマシンでの文字列の最大長は1073741791です。

以下のコメントとして結果を投稿していただければ幸いです。

人々が同じまたは異なる結果を得るかどうかを学ぶことは興味深いでしょう。


「ご存知のように、文字列は一般的に信じられているように整数に制限されていません。」-> c#の整数は最大2,147,483,647になり、結果はこの値を2で割った値に非常に近く(32バイト少ない)です。これは、文字列のすべての文字が2バイトのUnicodeとして格納されるため、論理的です。したがって、制限が整数のサイズによって課されなくても、それは非常にそれに近いです。
ベン

2

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

5
本当に大きな文字列を1つだけ作成することで得られる動作が、それらの束を割り当てて連結することで得られる動作と同じかどうかはわかりません。
Casey

1

ためString.Length(の別名である整数であるInt32)、そのサイズはこれらに限定されているInt32.MaxValueUnicode文字。;-)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.