4


0

文字列を安全に分割する方法は?

何らかの理由でスティングを分割する場合、(少なくとも自分自身)(パイプ) `|`文字を使用して分割する傾向があります。 .. しかし、それを使用するとどうなりますか?

さて、単純な*クラッシュ*がスローされます:)

大学ではhttp://en.wikipedia.org/wiki/Control_character[non-printable] charsを使用して同じ手法を使用していることがわかりました。たとえば、

String.Format(
         "{1}{0}{2}{0}{3}{0}{4}",
         (char)2,
         myFirstString,
         mySecondString,
         myThirdString,
         myFourthString);

そして、穴文字列をその部分に抽出したいとき

String.Split((char)2);

*これは安全ですか? *文字列を安全に分割するこの方法を採用すべきですか? *他に安全技術はありますか?

6 Answer


8


まれなのでパイプよりも「安全」かもしれませんが、両方の方法は可能な文字列のサブセットに制限されるため、次善の方法です。

適切なエンコードを使用することを検討してください— _unambiguously_は、_arbitrary_文字列のリストをエンコードします。 コーディングに関して最も簡単なのは、おそらく `string []`を単純にシリアル化することです。 「BinaryFormatter」または「XmlSerializer」などを使用できます。

結果が_has_で文字列であり、_short_でなければならない場合、次のようなものを試すことができます。

  • エンコーディング:(単一の文字列への文字列のリスト)

  • すべての「!」を「!e」に、すべての「|」を「!p」にすべての文字列で置き換えます。 これで、文字列に `|`が含まれなくなり、これを簡単に元に戻すことができます。

  • 区切り文字として「|」を使用して文字列を連結します。

  • デコード:(単一の文字列を文字列のリストに戻す)

  • `|`文字で分割します。

  • すべての文字列で、すべての「!p」を「|」に、「!e」を「!」に置き換えます。 This 元の文字列を復元します。


3


これは基本的に、この形式で文字列を生成するアプリケーションと、それらを使用するアプリケーションとの間の契約です。状況に適したものを使用してください。

そもそも、複数の文字列を単一の巨大な文字列に統合する必要があるかどうかを検討する必要があります。 それらが存在する理由が、アプリケーション内で「分離された」テキストデータを表すためだけである場合、最初から文字列のシーケンス(たとえば、「string []」)としてデータを生成することができます。 この場合、「解析」は必要ありません。

一方、データを「永続化」し、後で使用する必要がある場合、いくつかのオプションがあります。 例えば:

  1. データベース:各文字列をデータベーステーブルの行として保存します。 No 分割が必要です。

  2. 指定デリミタ:文字列をフラットファイルに保存します 現在の文字列の終わりを示す「特別な」セパレータ。 明らかに、この文字は正当な部分文字列の一部になれないようなものでなければなりません。 E.g. あなたが言うように文字列にパイプ文字を含めることができない場合、これは区切り文字の合理的な選択です。

  3. エスケープシーケンス:例 「」は区切り記号、「*」は アスタリスク_within_文字列。 これは、センチネルとして使用するために予約されている文字がないことを意味します(表現できません)。 欠点として、構文解析は重要なタスクになります。

  4. 専用ビルド形式:例 XML. これが必要と考える場合 特定の文字が「エスケープ」されること、これは本質的にポイント3の拡張ですが、問題はXMLライブラリにパントされました。


2


あなたがそれを助けることができれば、そもそも文字列を一緒に連結しないことをお勧めします。 このような分割はコードのにおいです。

確かに、制御文字を使用することは問題を起こさない「可能性が高い」が、それでも完全ではない。 本当にこれを行う必要がある場合は、NUL( \ 0)を使用します。 そのキャラクターには、少なくとも文字列センチネルの歴史があります。


2


印刷できない文字を使用することは、安全というよりも不明瞭だと思います。 安全を望むなら、解決策は `List`をシリアライズ/デシリアライズすることです。


1


通常のCSVリーダー/ライターを使用できます。 これは、値に区切り文字がある場合、二重引用符で囲まれているため役立ちます。

a,b,"c,d"

生成します:

new[] { "a", "b", "c,d" }

これにより、http://www.codeproject.com/KB/database/CsvReader.aspxが役立つ場合があります。


0


予想される文字列の内容に依存します。 予想される文字列に印刷できない文字が含まれている可能性がある場合は、そうでない可能性があります。 もう1つの方法は、分割しようとしている文字列をエスケープすることです。これはより多くの作業のように見えますが、再利用可能なヘルパーに入れることができます。

var string1 = "string|1";
var string2 = "string |2";
var string3 = "string| 3";
var string4 = "string | 4";

var stringToSplit = MergeStrings(string1, string2, string3, string4);

var results = SplitString( stringToSplit );

foreach(string result in results)
{
    Trace.WriteLine( result );
}

次の方法を使用します。

public string MergeStrings(params string[] strings)
{
    var stringBuilder = new StringBuilder();

    foreach(var s in strings)
    {
        stringBuilder.Append( s.Replace( "|", "||" ) );
        stringBuilder.Append( " | " );
    }

    return stringBuilder.ToString();
}

public IEnumerable SplitString(string stringToSplit)
{
    var results = stringToSplit.Split( new[] { " | " }, StringSplitOptions.RemoveEmptyEntries );

    return results.Select( result => result.Replace( "||", "|" ) );
}

おそらく分離文字をカスタマイズ可能にしたいと思うでしょう。