0

I am trying to select specific string "Compression: " value which is Deflate in this case.

below is the code:

static void Main(string[] args)
{
    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" + 
        "         File type: binary\n       Compression: Deflate\n        " + 
        "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

    string s1 = info.Substring((info.IndexOf("Compression:")), 
        info.Length - info.IndexOf("Compression:") - 1);

    var replace = s1.Replace("Compression: ", "");
}

here, i am getting all the string having substring "Compression"

is there a efficient way to get only Deflate of Compression ?

Thanks!

4
  • 1
    Split the string on carriage returns, then split each element on colon? Commented Feb 12, 2019 at 12:19
  • What does the code do now? What do you want it to do instead? Commented Feb 12, 2019 at 12:20
  • Actually split on newlines since the OP has \n in the string not \r. Commented Feb 12, 2019 at 12:26
  • @mjwills Currently,I am getting response like this: replace = "Deflate\n Compressed: 0x35556371\n Uncompressed: 0x1D626FBDB\n .." I just want Deflatestring. Commented Feb 12, 2019 at 12:26

7 Answers 7

2

You could split the string on the \n character to get an array of name-value pairs, then find the one that starts with your search string ("Compression"), then split that on the : character and return the second part.

To generalize it, you could write a function that takes in your search string and the string to search, which returns the value for the specified name if found (or null if not found):

public static string GetValue(string name, string source)
{
    if (source == null || name == null) return null;

    var result = source.Split('\n')
        .Select(i => i.Trim())
        .FirstOrDefault(i => i.StartsWith(name + ":", StringComparison.OrdinalIgnoreCase))
        ?.Split(':');

    return result?.Length == 2 ? result[1].Trim() : null;
}

Then you could call this with different "names" to find their values:

private static void Main()
{
    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" +
                "         File type: binary\n       Compression: Deflate\n        " +
                "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

    var compression = GetValue("Compression", info);
    var zipEntry = GetValue("ZipEntry", info);

    Console.WriteLine($"Compression = {compression}, ZipEntry = {zipEntry}");

    GetKeyFromUser("\nDone! Press any key to exit...");
}

Output

enter image description here

Alternatively, you could write the method so it returns ALL the key/value pairs from the string in the form of a Dictionary<string, string>. Then you can lookup values by name:

public static Dictionary<string, string> GetNameValuePairs(string source)
{
    return source?.Split('\n')
        .Select(i => i.Split(':'))
        .ToDictionary(k => k[0].Trim(), v => v.Length > 1 ? v[1].Trim() : null,
            StringComparer.OrdinalIgnoreCase);
}

For example:

private static void Main()
{
    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" +
                "         File type: binary\n       Compression: Deflate\n        " +
                "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

    var keyValuePairs = GetKeyValuePairs(info);

    // Write out all the name/value pairs found
    foreach (var kvp in keyValuePairs)
    {
        Console.WriteLine($"{kvp.Key} = {kvp.Value}");
    }

    GetKeyFromUser("\nDone! Press any key to exit...");
}

Output

![enter image description here

Sign up to request clarification or add additional context in comments.

Comments

1

is there a efficient way to get only Deflate of Compression ?

You could use the Span<T>/ReadOnlySpan<char> type that was introduced in .NET Core 2.1 and the System.Memory NuGet package:

static void Main(string[] args)
{
    string info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" +
            "         File type: binary\n       Compression: Deflate\n        " +
            "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

    ReadOnlySpan<char> span = info.AsSpan();
    ReadOnlySpan<char> compression = "Compression: ".AsSpan();
    int startIndex = span.IndexOf(compression);
    if (startIndex != -1)
    {
        ReadOnlySpan<char> deflate = span.Slice(startIndex + compression.Length);
        int endIndex = deflate.IndexOf('\n');
        if (endIndex != -1)
        {
            string s1 = deflate.Slice(0, endIndex).ToString();
        }
    }
}

It saves you from having to allocate necessary substrings and allocated memory in vain. Please refer to Stephen Toub's MSDN Magazine article for more information.

Comments

0

Of course you can as well work with cutting your string into pieces using Substring().

But it's most easily possible using a regular expression:

static void Main(string[] args)
{
    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" + 
        "         File type: binary\n       Compression: Deflate\n        " + 
        "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

    MatchCollection matches = Regex.Matches(info, @"(?<=Compression: )([^\\n]*)");

    foreach (Match match in matches)
    {
        Debug.WriteLine($"- Match: {match.Value}");
    }
}

The regular expression uses a lookaround (specifically a lookbehind in this case) clause to check for a string that is preceeded by "Compression: ". It then starts capturing any character that is not \n (which has to be double escaped). Everything else is discarded.

Comments

0

If you are sure that it's going to be \n after the value "Deflate", you can do this:

if(s1.Contains('\n'))
{
     s1 = s1.Split('\n')[0];
}
var replace = s1.Replace("Compression: ", "");

Comments

0

I would parse the string into a dictionary, so that you can access any desired value easily:

        var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n         File type: binary\n       Compression: Deflate\n        Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n      ...";

        var values = new Dictionary<string, string>();
        IList<string> split = info.Split(new char[] { ':', '\n' }).Select(x => x.Trim()).ToList();

        if (split.Count > 0)
        {
            for (int i = 1; i < split.Count; i++)
            {
                if (i % 2 != 0)
                    values.Add(split[i - 1], split[i]);
                else if (i == split.Count - 1)
                    values.Add(split[i], "");
            }
        }

        string compression = values["Compression"];

Comments

0

Assuming that all your leading and trailing space are useless, here is way you can do it with Split and linq. Explanations are in code comment.

var compressionValue = info
     // Process data per line 
    .Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries)
     // Remove leading and trailing space
    .Select(s => s.Trim())
    // Check for "Compression" header
    .Where(r => r.StartsWith("Compression: "))
    // Get corresponding value
    .Select(s => s.Substring("Compression: ".Length))
    // Select the first Match, null if "Compression : " is not found
    .FirstOrDefault();

Comments

0
static void Main(string[] args)
{

    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" +
        "         File type: binary\n       Compression: Deflate\n        " +
        "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n  ";
    List<string> splittedinfo = info.Split('\n');
    foreach (string s in splittedinfo)
    {
        if (!string.IsNullOrEmpty(s.Trim()))
        {
            var ss = s.Split(':');
            if (ss[0].Trim() == "Compression")
            {
                Console.WriteLine(ss[1]);
                break;
            }
        }
    }
    Console.ReadLine();
}

Or

static void Main(string[] args)
{
    string key = "Compressed",  endstring = "\n";
    char separator = ':';
    var info = "ZipEntry: testfile.txt\n   Version Made By: 45\n Needed to extract: 45\n" +
        "         File type: binary\n       Compression: Deflate\n        " +
        "Compressed: 0x35556371\n      Uncompressed: 0x1D626FBDB\n  ";

    info = info.Substring(info.IndexOf(key));
    info = info.Substring(0, info.IndexOf(endstring));
    info = info.Split(separator)[1].Trim();
    Console.WriteLine(info);
    Console.ReadLine();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.